野狗云的API说实话,不是特别的好用,对于分页操作和查询是鸡肋,对于这两个操作我就不过多吐槽了,但是我想吐槽一下,野狗云的确很坑,当里把数据往死里写,超过了250MB后,你的服务就用不了了(当时我用多线程,做的实验,后悔死了),开启今天的正文,我的项目源码在github上,过多的就不介绍了。

封装官方的API

wilddog.properties

这个配置文件用于配置自己的项目id,这个配置文件,我不删,你们随便拿我的玩,反正不花钱,哈哈哈哈哈….

野狗云API之详解(分页,查询,删除,更新)-yellowcong_api

appid=https://doub.wilddogio.com/

Wilddog .java

官方的这个查询类中,我主要添加了下面的几个方法
1. limitToFirst
        设置从第一条开始,一共返回多少条数据(节点)。
2. limitToLast
        设置从最后一条开始,一共返回多少条(返回结果仍是升序,降序要自己处理)。
3. startAt
        返回大于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
4. endAt
         返回小于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
5. equalTo
        返回等于指定的键、值或优先级的数据,具体取决于所选的排序方法。可用于精确查询。

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.ParameterizedType;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.wilddog.client.rest.error.JacksonUtilityException;
import com.wilddog.client.rest.error.WilddogException;
import com.wilddog.client.rest.model.WilddogResponse;
import com.wilddog.client.rest.util.JacksonUtility;
import com.yellowcong.utils.JsonUtils;

import okhttp3.*;
import org.apache.log4j.Logger;

/**
 * 基于 [Wilddog REST API](https://z.wilddog.com/rest/quickstart)的封装
 * 
 * 给服务器添加了
 * limitToFirst 
 * 设置从第一条开始,一共返回多少条数据(节点)。 
 * limitToLast
 * 设置从最后一条开始,一共返回多少条(返回结果仍是升序,降序要自己处理)。 
 * startAt
 * 返回大于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。 
 * endAt
 * 返回小于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
 *  equalTo
 * 返回等于指定的键、值或优先级的数据,具体取决于所选的排序方法。可用于精确查询。
 */
public class Wilddog {

    protected static final Logger           LOGGER                  = Logger.getRootLogger();

    public static final String WILDDOG_API_JSON_EXTENSION
                                                                    = ".json";



///
//
// PROPERTIES & CONSTRUCTORS
//
///


    private final String baseUrl;
    private String secureToken = null;
    private List<BasicNameValuePair> query;

    public Wilddog(String baseUrl ) throws WilddogException {

        if( baseUrl == null || baseUrl.trim().isEmpty() ) {
            String msg = "baseUrl cannot be null or empty; was: '" + baseUrl + "'";
            LOGGER.error( msg );
            throw new WilddogException( msg );
        }
        this.baseUrl = baseUrl.trim();
        query = new ArrayList<BasicNameValuePair>();
        LOGGER.info( "intialized with base-url: " + this.baseUrl );
    }

    public Wilddog(String baseUrl, String secureToken) throws WilddogException {
        if( baseUrl == null || baseUrl.trim().isEmpty() ) {
            String msg = "baseUrl cannot be null or empty; was: '" + baseUrl + "'";
            LOGGER.error( msg );
            throw new WilddogException( msg );
        }
        this.secureToken = secureToken;
        this.baseUrl = baseUrl.trim();
        query = new ArrayList<BasicNameValuePair>();
        LOGGER.info( "intialized with base-url: " + this.baseUrl );
    }



///
//
// PUBLIC API
//
///



    /**
     * GETs data from the base-url.
     * 
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link WilddogException}
     */
    public WilddogResponse get() throws WilddogException, UnsupportedEncodingException {
        return this.get( null );
    }

    /**
     * GETs data from the provided-path relative to the base-url.
     * 
     * @param path -- if null/empty, refers to the base-url
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link WilddogException}
     */
    public WilddogResponse get(String path ) throws WilddogException, UnsupportedEncodingException {

        // make the request
        String url = this.buildFullUrlFromRelativePath( path );
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response httpResponse = this.makeRequest( request );

        // process the response
        WilddogResponse response = this.processResponse( WilddogRestMethod.GET, httpResponse );

        return response;
    }

    /**
     * PATCHs data to the base-url
     * 
     * @param data -- can be null/empty
     * @return
     * @throws {@link WilddogException}
     * @throws {@link JacksonUtilityException}
     * @throws UnsupportedEncodingException
     */

    public WilddogResponse patch(Map<String, Object> data) throws WilddogException, JacksonUtilityException, UnsupportedEncodingException {
        return this.patch(null, data);
    }

    /**
     * PATCHs data on the provided-path relative to the base-url.
     * 
     * @param path -- if null/empty, refers to the base-url
     * @param data -- can be null/empty
     * @return {@link WilddogResponse}
     * @throws {@link WilddogException}
     * @throws {@link JacksonUtilityException}
     * @throws UnsupportedEncodingException
     */

    public WilddogResponse patch(String path, Map<String, Object> data) throws WilddogException, JacksonUtilityException, UnsupportedEncodingException {
        // make the request
        String url = this.buildFullUrlFromRelativePath( path );

        Request request = new Request.Builder()
                .url(url)
                .patch(this.buildRequestBodyFromDataMap( data ))
                .build();

        Response httpResponse = this.makeRequest( request );

        // process the response
        WilddogResponse response = this.processResponse( WilddogRestMethod.PATCH, httpResponse );

        return response;
    }

    /**
     * 
     * @param jsonData
     * @return
     * @throws UnsupportedEncodingException
     * @throws WilddogException
     */

    public WilddogResponse patch(String jsonData) throws UnsupportedEncodingException, WilddogException {
        return this.patch(null, jsonData);
    }

    /**
     * 
     * @param path
     * @param jsonData
     * @return
     * @throws UnsupportedEncodingException
     * @throws WilddogException
     */

    public WilddogResponse patch(String path, String jsonData) throws UnsupportedEncodingException, WilddogException {
        // make the request
        String url = this.buildFullUrlFromRelativePath( path );

        Request request = new Request.Builder()
                .url(url)
                .patch(this.buildRequestBodyFromJsonData( jsonData ))
                .build();

        Response httpResponse = this.makeRequest( request );


        // process the response
        WilddogResponse response = this.processResponse( WilddogRestMethod.PATCH, httpResponse );

        return response;        
    }

    /**
     * PUTs data to the base-url (ie: creates or overwrites).
     * If there is already data at the base-url, this data overwrites it.
     * If data is null/empty, any data existing at the base-url is deleted.
     * 
     * @param data -- can be null/empty
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link JacksonUtilityException}
     * @throws {@link WilddogException}
     */
    public WilddogResponse put(Map<String, Object> data ) throws JacksonUtilityException, WilddogException, UnsupportedEncodingException {
        return this.put( null, data );
    }

    /**
     * PUTs data to the provided-path relative to the base-url (ie: creates or overwrites).
     * If there is already data at the path, this data overwrites it.
     * If data is null/empty, any data existing at the path is deleted.
     * 
     * @param path -- if null/empty, refers to base-url
     * @param data -- can be null/empty
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link JacksonUtilityException}
     * @throws {@link WilddogException}
     */
    public WilddogResponse put(String path, Map<String, Object> data ) throws JacksonUtilityException, WilddogException, UnsupportedEncodingException {

        // make the request
        String url = this.buildFullUrlFromRelativePath( path );

        Request request = new Request.Builder()
                .url(url)
                .put(this.buildRequestBodyFromDataMap( data ))
                .build();

        Response httpResponse = this.makeRequest( request );

        // process the response
        WilddogResponse response = this.processResponse( WilddogRestMethod.PUT, httpResponse );

        return response;
    }

    /**
     * PUTs data to the provided-path relative to the base-url (ie: creates or overwrites).
     * If there is already data at the path, this data overwrites it.
     * If data is null/empty, any data existing at the path is deleted.
     * 
     * @param jsonData -- can be null/empty
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link WilddogException}
     */
    public WilddogResponse put(String jsonData ) throws WilddogException, UnsupportedEncodingException {
        return this.put( null, jsonData );
    }

    /**
     * PUTs data to the provided-path relative to the base-url (ie: creates or overwrites).
     * If there is already data at the path, this data overwrites it.
     * If data is null/empty, any data existing at the path is deleted.
     * 
     * @param path -- if null/empty, refers to base-url
     * @param jsonData -- can be null/empty
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link WilddogException}
     */
    public WilddogResponse put(String path, String jsonData ) throws WilddogException, UnsupportedEncodingException {

        // make the request
        String url = this.buildFullUrlFromRelativePath( path );

        Request request = new Request.Builder()
                .url(url)
                .put(this.buildRequestBodyFromJsonData( jsonData ))
                .build();

        Response httpResponse = this.makeRequest( request );

        WilddogResponse response = this.processResponse( WilddogRestMethod.PUT, httpResponse );

        return response;        
    }

    /**
     * POSTs data to the base-url (ie: creates).
     * 
     * NOTE: the Wilddog API does not treat this method in the conventional way, but instead defines it
     * as 'PUSH'; the API will insert this data under the base-url but associated with a Wilddog-
     * generated key; thus, every use of this method will result in a new insert even if the data already 
     * exists.
     * 
     * @param data -- can be null/empty but will result in no data being POSTed
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link JacksonUtilityException}
     * @throws {@link WilddogException}
     */
    public WilddogResponse post(Map<String, Object> data ) throws JacksonUtilityException, WilddogException, UnsupportedEncodingException {
        return this.post( null, data );
    }

    /**
     * POSTs data to the provided-path relative to the base-url (ie: creates).
     * 
     * NOTE: the Wilddog API does not treat this method in the conventional way, but instead defines it
     * as 'PUSH'; the API will insert this data under the provided path but associated with a Wilddog-
     * generated key; thus, every use of this method will result in a new insert even if the provided path
     * and data already exist.
     * 
     * @param path -- if null/empty, refers to base-url
     * @param data -- can be null/empty but will result in no data being POSTed
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link JacksonUtilityException}
     * @throws {@link WilddogException}
     */
    public WilddogResponse post(String path, Map<String, Object> data ) throws JacksonUtilityException, WilddogException, UnsupportedEncodingException {

        // make the request
        String url = this.buildFullUrlFromRelativePath( path );

        Request request = new Request.Builder()
                .url(url)
                .post(this.buildRequestBodyFromDataMap( data ))
                .build();

        Response httpResponse = this.makeRequest( request );

        // process the response
        WilddogResponse response = this.processResponse( WilddogRestMethod.POST, httpResponse );

        return response;
    }

    /**
     * POSTs data to the base-url (ie: creates).
     * 
     * NOTE: the Wilddog API does not treat this method in the conventional way, but instead defines it
     * as 'PUSH'; the API will insert this data under the base-url but associated with a Wilddog-
     * generated key; thus, every use of this method will result in a new insert even if the provided data 
     * already exists.
     * 
     * @param jsonData -- can be null/empty but will result in no data being POSTed
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link WilddogException}
     */
    public WilddogResponse post(String jsonData ) throws WilddogException, UnsupportedEncodingException {
        return this.post( null, jsonData );
    }

    /**
     * POSTs data to the provided-path relative to the base-url (ie: creates).
     * 
     * NOTE: the Wilddog API does not treat this method in the conventional way, but instead defines it
     * as 'PUSH'; the API will insert this data under the provided path but associated with a Wilddog-
     * generated key; thus, every use of this method will result in a new insert even if the provided path
     * and data already exist.
     * 
     * @param path -- if null/empty, refers to base-url
     * @param jsonData -- can be null/empty but will result in no data being POSTed
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link WilddogException}
     */
    public WilddogResponse post(String path, String jsonData ) throws WilddogException, UnsupportedEncodingException {

        // make the request
        String url = this.buildFullUrlFromRelativePath( path );

        Request request = new Request.Builder()
                .url(url)
                .post(this.buildRequestBodyFromJsonData( jsonData ))
                .build();

        Response httpResponse = this.makeRequest( request );

        // process the response
        WilddogResponse response = this.processResponse( WilddogRestMethod.POST, httpResponse );

        return response;
    }

    /**
     * Append a query to the request.
     * 
     * @param query -- Query string based on Wilddog REST API
     * @param parameter -- Query parameter
     * @return Wilddog -- return this Wilddog object
     */

    public Wilddog addQuery(String query, String parameter) {
        this.query.add(new BasicNameValuePair(query, parameter));
        return this;
    }

    /**
     * 返回大于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
     * @param param
     * @return
     */
    public Wilddog startAt(String param,Integer val) {
        this.orderBy(param);
        this.query.add(new BasicNameValuePair("startAt", String.valueOf(val)));
        return this;
    }

    /**
     * 返回小于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
     * @param param
     * @return
     */
    public Wilddog endAt(String param,Integer endAt) {
        this.orderBy(param);
        this.query.add(new BasicNameValuePair("endAt", String.valueOf(endAt)));
        return this;
    }

    /**
     * 查询云端时间戳
     * @return
     */
    public String timestamp(){
        try {
            //查询云端时间戳
            this.addQuery("sv", "timestamp");
            WilddogResponse resp= this.get();
            System.out.println(resp.getRawBody());
            return resp.getRawBody();
        } catch (UnsupportedEncodingException | WilddogException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 排序 ,检索数据的时候,必须要有orderBy
     * @param orderBy
     * @return
     */
    private Wilddog orderBy(String orderBy) {
        boolean hasOrder = false;
        for(BasicNameValuePair val:this.query){
            if("orderBy".equals(val.getName())){
                hasOrder = true;
            }
        }
        if(!hasOrder){
            this.query.add(new BasicNameValuePair("orderBy", "\""+orderBy+"\""));
        }
        return this;
    }

    /**
     * 返回等于指定的键、值或优先级的数据,具体取决于所选的排序方法。可用于精确查询。
     * @param equalTo
     * @return
     */
    public Wilddog equalTo(String param,String equalTo) {
        this.orderBy(param);
        this.query.add(new BasicNameValuePair("equalTo", String.valueOf(equalTo)));
        return this;
    }

    /**
     * 设置从最后一条开始,一共返回多少条(返回结果仍是升序,降序要自己处理)。
     * @param count
     * @return
     */
    public Wilddog limitToLast(String param,Integer count) {
        this.orderBy(param);
        this.query.add(new BasicNameValuePair("limitToLast", String.valueOf(count)));
        return this;
    }
    /**
     * 设置从第一条开始,一共返回多少条数据(节点)。
     * @param count
     * @return
     */
    public Wilddog limitToFirst(String param,Integer count) {
        this.orderBy(param);
        this.query.add(new BasicNameValuePair("limitToFirst", String.valueOf(count)));
        return this;
    }

    /**
     * DELETEs data from the base-url.
     * 
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link WilddogException}
     */
    public WilddogResponse delete() throws WilddogException, UnsupportedEncodingException {
        return this.delete( null );
    }

    /**
     * DELETEs data from the provided-path relative to the base-url.
     * 
     * @param path -- if null/empty, refers to the base-url
     * @return {@link WilddogResponse}
     * @throws UnsupportedEncodingException 
     * @throws {@link WilddogException}
     */
    public WilddogResponse delete(String path ) throws WilddogException, UnsupportedEncodingException {

        // make the request
        String url = this.buildFullUrlFromRelativePath( path );

        Request request = new Request.Builder()
                .url(url)
                .delete()
                .build();

        Response httpResponse = this.makeRequest( request );

        // process the response
        WilddogResponse response = this.processResponse( WilddogRestMethod.DELETE, httpResponse );

        return response;
    }



///
//
// PRIVATE API
//
///


    private RequestBody buildRequestBodyFromDataMap(Map<String, Object> dataMap ) throws WilddogException, JacksonUtilityException {

        String jsonData = JacksonUtility.GET_JSON_STRING_FROM_MAP( dataMap );

        return this.buildRequestBodyFromJsonData( jsonData );
    }

    public static final MediaType JSON
            = MediaType.parse("application/json; charset=utf-8");

    private RequestBody buildRequestBodyFromJsonData(String jsonData ) throws WilddogException {

        RequestBody result =  null;
        try {

            result = RequestBody.create(JSON, jsonData);

        } catch( Throwable t ) {

            String msg = "unable to create entity from data; data was: " + jsonData;
            LOGGER.error( msg );
            throw new WilddogException( msg, t );

        }

        return result;
    }

    private String buildFullUrlFromRelativePath( String path ) throws UnsupportedEncodingException {

        // massage the path (whether it's null, empty, or not) into a full URL
        if( path == null ) {
            path = "";
        }
        path = path.trim();
        if( !path.isEmpty() && !path.startsWith( "/" ) ) {
            path = "/" + path;
        }
        String url = this.baseUrl + path + Wilddog.WILDDOG_API_JSON_EXTENSION;

        if(query != null) {
            url += "?";

            Iterator<BasicNameValuePair> it = query.iterator();
            BasicNameValuePair e;
            while(it.hasNext()) {
                e = it.next();
                url += e.getName() + "=" + URLEncoder.encode(e.getValue(), "UTF-8") + "&";
            }
        }

        if(secureToken != null) {
            if(query != null) {
                url += "auth=" + secureToken;
            } else {
                url += "?auth=" + secureToken;
            }
        }

        if(url.lastIndexOf("&") == url.length()) {
            StringBuilder str = new StringBuilder(url);
            str.deleteCharAt(str.length());
            url = str.toString();
        }

        LOGGER.info( "built full url to '" + url + "' using relative-path of '" + path + "'" );

        return url;
    }

   static class LoggingInterceptor implements Interceptor {
        @Override public Response intercept(Interceptor.Chain chain) throws IOException {
            Request request = chain.request();

            long t1 = System.nanoTime();
            LOGGER.info(String.format("Sending request %s on %s%n%s",
                    request.url(), chain.connection(), request.headers()));

            Response response = chain.proceed(request);



            long t2 = System.nanoTime();
            LOGGER.info(String.format("Received response for %s in %.1fms %dbyte %n%s",
                    response.request().url(), (t2 - t1) / 1e6d,  response.body().contentLength(), response.headers()));

            return response;
        }
    }


    private Response makeRequest( Request request ) throws WilddogException {
        // sanity-check
        if( request == null ) {

            String msg = "request cannot be null";
            LOGGER.error( msg );
            throw new WilddogException( msg );
        }
        Response response = null;
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .addNetworkInterceptor(new LoggingInterceptor())
                    .build();

            response = client.newCall(request).execute();

        } catch( Throwable t ) {
            String msg = "unable to receive response from request(" + request.method() +  ") @ " + request.url();
            LOGGER.error( msg );
            throw new WilddogException( msg, t );
        }
        return response;
    }

    private WilddogResponse processResponse(WilddogRestMethod method, Response httpResponse ) throws WilddogException {

        WilddogResponse response = null;

        // sanity-checks
        if( method == null ) {

            String msg = "method cannot be null";
            LOGGER.error( msg );
            throw new WilddogException( msg );
        }
        if( httpResponse == null ) {

            String msg = "httpResponse cannot be null";
            LOGGER.error( msg );
            throw new WilddogException( msg );
        }

        // get the response-entity
        ResponseBody entity = httpResponse.body();

        // get the response-code
        int code = httpResponse.code();

        // set the response-success
        boolean success =  httpResponse.isSuccessful();

        // get the response-body
        String  responseBody = null;

//        if (entity.contentLength() > 0) {
        try {
            responseBody =  new String(entity.bytes(), "UTF-8");
        } catch (IOException e) {
            String msg = "unable to convert response-body into string; response-body was: '" + responseBody + "'";
            LOGGER.error(msg);
            throw new WilddogException(msg, e);
        }
//        }

        // convert response-body to map
        Map<String, Object> body = null;
        try {

            body = JacksonUtility.GET_JSON_STRING_AS_MAP(responseBody);

        } catch( JacksonUtilityException jue ) {

            String msg = "unable to convert response-body into map; response-body was: '" + responseBody + "'";
            LOGGER.error( msg );
            throw new WilddogException( msg, jue );
        }

        // build the response
        response = new WilddogResponse( success, code, body, responseBody);

        //clear the query
        query = null;

        return response;
    }



///
//
// INTERNAL CLASSES
//
///


    public enum WilddogRestMethod {

        GET,
        PATCH,
        PUT,
        POST,
        DELETE;
    }



    static class BasicNameValuePair {
        private final String name;
        private final String value;

        public BasicNameValuePair(String name, String value) {
            this.name = name;
            this.value = value;
        }

        public String getName() {
            return this.name;
        }

        public String getValue() {
            return this.value;
        }

        public String toString() {
            if (this.value == null) {
                return this.name;
            } else {
                int len = this.name.length() + 1 + this.value.length();
                StringBuilder buffer = new StringBuilder(len);
                buffer.append(this.name);
                buffer.append("=");
                buffer.append(this.value);
                return buffer.toString();
            }
        }
    }

    }

BaseDao接口

BaseDao接口里面,写了基本的CURD的操作,基本足够项目的普通操作了,对于一些没啥意义的API,我就 没咋具体研究了,到时候,看自己 做项目啥的,如果需要,就更深入研究,然后给大家贴出代码来

package com.yellowcong.dao;

import java.util.List;

import com.wilddog.client.rest.service.Wilddog;

public interface BaseDao<T> {

    /**
     * 一次获取到所有的条数 , 这样,我们的数据中,不可以存在{}的字符
     * @return
     */
    public List<T> listAll();

    /**
     * 获取记录的条数
     * @return
     */
    public int getCount();

    /**
     * 直接删除这个表
     * 
     * @return
     */
    public boolean deleteAll();

    /**
     * 更细数据
     * @param t
     */
    public void update(T t);

    /**
     * 删除数据
     * @param t
     * @return
     */
    public boolean delete(T t) ;

    /**
     * 直接删除数据,删除具体的数据
     * @param param 数据的field
     * @param val 值
     * @return
     */
    public boolean delete(String param,String val);

    /**
     * 获取一个新的链接对象
     * 
     * @return
     */
    public Wilddog getNewWilddog();

    /**
     * 获取一个操作当前类节点的对象
     * @return
     */
    public Wilddog getWilddog();

    /**
     * 获取节点的数据,通过id来获取
     * @param id
     * @return
     */
    public Wilddog getWilddogById(String id);

    /**
     * 添加单个的数据
     * 
     * @param paramT
     * @return
     */
    public T add(T paramT) ;

    /**
     * 添加多个节点的对象
     * @param objs
     * @return
     */
    public List<T> addList(List<T> objs);

    /**
     * 设置从第一条开始,一共返回多少条数据(节点)。
     * @param param 查询的属性  
     * @param count 条数
     * @return
     */
    public List<T> limitToFirst(String param,Integer count);

    /**
     * 查询云端时间戳
     * @return
     */
    public String timestamp();

    /**
     * 设置从最后一条开始,一共返回多少条(返回结果仍是升序,降序要自己处理)。
     * @param param 查询的属性  
     * @param count 条数
     * @return
     */
    public List<T> limitToLast(String param,Integer count);

    /**
     * 返回大于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
     * @param param 查询的属性  
     * @param val 大于的值
     * @return
     */
    public List<T> startAt(String param,Integer val);

    /**
     * 返回小于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
     * @param param 查询的属性  
     * @param val 大于的值
     * @return
     */
    public List<T> endAt(String param,Integer val);

    /**
     * 查询在某个字段中间的数据  ,age >1 ,age<20
     * @param param 参数
     * @param start 开始时间
     * @param end 结束时间
     * @return
     */
    public List<T> between(String param,Integer start,Integer end);

    /**
     * 返回等于指定的键、值或优先级的数据,具体取决于所选的排序方法。可用于精确查询。
     * @param field  字段名称 我们要查询的对象的字段
     * @param val  值
     * @return
     */
    public List<T> equalTo(String field,String val) ;

    /**
     * 获取数据,同eqaulTo方法类似,但是名字改了一下
     * @param field 字段名称 我们要查询的对象的字段
     * @param val
     * @return
     */
    public List<T> load(String field,String val) ;

    /**
     * 清空野狗云上的所有数据
     */
    public void deleteAllData();

    /**
     * 查询分页,默认的字段是id 
     * @param pageNow
     * @param pageSize
     * @return
     */
    public List<T> queryByPage(int pageNow,int pageSize);

    /**
     * 可以改变分页的默认查询字段
     * @param field  分页字段
     * @param pageNow 当前页码
     * @param pageSize  页面大小
     * @return
     */
    public List<T> queryByPage(String field,int pageNow,int pageSize);

}

BaseDaoImpl(实现类)

package com.yellowcong.dao.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.wilddog.annotation.WilddogTable;
import com.wilddog.client.rest.error.JacksonUtilityException;
import com.wilddog.client.rest.error.WilddogException;
import com.wilddog.client.rest.model.WilddogResponse;
import com.wilddog.client.rest.service.Wilddog;
import com.yellowcong.dao.BaseDao;
import com.yellowcong.utils.JsonUtils;

/**
PUT     向指定 节点写入数据。若此节点已存在数据,会覆盖原有数据。 ->这个用于更新和添加操作
POST    向指定节点添加 子节点。子节点的 key 自动生成并保证唯一。  这个方法蛋疼,所以没法用
PATCH   更新指定子节点。 ->用于更新具体类容
DELETE  删除指定节点。  ->删除节点
 * @author yellowcong
 *
 * @param <T>
 */
public class BaseDaoImpl<T> implements BaseDao<T>{

    /** 默认分页的大小*/
    private static Integer DEFAULT_PAGE_SIZE = 10;

    /** 默认所在页面*/
    private static Integer DEFAULT_PAGE_NOW = 1;

    private Class<T> clazz;

    private Wilddog wilddog;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private Class<T> getClazz() {
        if (this.clazz == null) {
            ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
            this.clazz = ((Class) type.getActualTypeArguments()[0]);
        }
        return this.clazz;
    }

    /**
     * 获取添加节点
     * 
     * @return
     */
    public Wilddog getWilddog() {
        if (wilddog == null) {
            wilddog = getNewWilddog();
        }
        return wilddog;
    }

    /**
     * 一次获取到所有的条数 , 这样,我们的数据中,不可以存在{}的字符
     * @return
     */
    public List<T> listAll() {
        List<T> result = new ArrayList<T>();
        try {
            //获取这个节点的所有数据
            WilddogResponse response = this.getWilddog().get();

            //获取数据
            String content = response.getRawBody();

            return this.formatDate(content);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (WilddogException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 格式化请求获取返回的数据
     * @param content
     * @return
     */
    private List<T> formatDate(String content){
        System.out.println(content);
        //当没有数据的情况
        if(content == null || "".equals(content.trim()) || "null".equals(content.trim())){
            return null;
        }

        List<T> result = new ArrayList<T>();

        String [] nodes = content.split("\":\\{\"");
        if(nodes.length>0){
            for(int i=1;i<nodes.length-1;i++){
                int index = nodes[i].indexOf("\"},\"");
                String node = nodes[i].substring(0, index);
                T res = JsonUtils.json2Object("{\""+node+"\"}", this.getClazz());
                result .add(res);
            }
            //尾巴下面的node去除
            String lastNode = nodes[nodes.length-1];
            lastNode = lastNode.substring(0, lastNode.indexOf("\"}}"));
            T res = JsonUtils.json2Object("{\""+lastNode+"\"}", this.getClazz());
            result .add(res);
        }

        return result;
    }

    /**
     * 获取记录的条数
     * @return
     */
    public int getCount() {
        Wilddog wilddog =  this.getNewWilddog();
        wilddog.addQuery("count", "true");
        try {
            WilddogResponse resp = wilddog.get();
            String ret = resp.getRawBody();
            if(isNumeric(ret)){
                return Integer.parseInt(ret);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (WilddogException e) {
            e.printStackTrace();
        }
        return 0;

    }

    /**
     * 直接删除这个表
     * 
     * @return
     */
    public boolean deleteAll() {
        try {
            WilddogResponse response = this.getWilddog().delete();
            return response.getSuccess();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (WilddogException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 直接删除数据,删除具体的数据, 不是 < >这种
     * @param param 数据的
     * @param val
     * @return
     */
    public boolean delete(String param,String val) {
        try {
            //排序  精确查询  orderBy 和equalTo ,判断等于的情况 
            Wilddog dog = this.getNewWilddog();
            dog.equalTo(param, val);
            WilddogResponse resp = dog.get();
            String content = resp.getRawBody();

            //获取删除的节点
            List<String> nodes = this.getNodes(content);
            for(String node:nodes){
                Wilddog  rs = this.getWilddogById(node);
                rs.delete();
            }
            return true;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (WilddogException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获取节点的ID
     * @param content
     * @return
     */
    private List<String> getNodes(String content){
        System.out.println(content);
        //当没有数据的情况
        if(content == null || "".equals(content.trim()) || "null".equals(content.trim())){
            return null;
        }

        String [] nodeIds = content.split("\":\\{\"");
        List<String> nodeList  =  new ArrayList<String>();
        if(nodeIds.length>0){
            nodeList.add(nodeIds[0].substring(2));
            for(int i=1;i<nodeIds.length-1;i++){
                int index = nodeIds[i].indexOf("\"},\"");
                String node = nodeIds[i].substring(index+4);
                 System.out.println(node);
                 nodeList.add(node);
            }
        }
        return nodeList;
    }

    /**
     * 获取表格的名称
     * 
     * @return
     */
    public Wilddog getNewWilddog() {
        Wilddog wilddog = null;
        try {
            // 创建节点
            wilddog = new Wilddog(this.getAppUrl());
        } catch (WilddogException e) {
            e.printStackTrace();
        }

        return wilddog;
    }
    /**
     * 获取当前操作 的table的URL
     * @return
     */
    private String getAppUrl(){
        // 获取用户的Appid
        String appid = this.getAppid();

        // 获取节点
        WilddogTable table = this.getClazz().getAnnotation(WilddogTable.class);
        String nodeUrl ;
        //结尾的地址带有 / 就不需要添加斜杠了
        if(appid.endsWith("/")){
            nodeUrl = appid + table.value();
        }else{
            nodeUrl = appid + "/" + table.value();
        }

        return nodeUrl;
    }
    /**
     * 获取节点的数据,通过id来获取
     * @param id
     * @return
     */
    public Wilddog getWilddogById(String id) {
        Wilddog wilddog = null;
        try {

            // 创建节点
            wilddog = new Wilddog( getAppUrl()+"/"+id);
        } catch (WilddogException e) {
            e.printStackTrace();
        }

        return wilddog;
    }

    /**
     * Query 
     * 
     * https://docs.wilddog.com/sync/REST/guide/retrieve-data.html
     * 
     * 进行这个查询操作的时候,我们都需要手动在wilddog中添加 索引对象
     * {
  "rules": {
    ".read": true,
    ".write": true,
     "user": { //我们需要添加索引的对象
      ".indexOn": ["age","username"]
    }
  }
}
     * orderBy&limitToFirst 
     * 设置从第一条开始,一共返回多少条数据(节点)。 
     * orderBy&limitToLast
     * 设置从最后一条开始,一共返回多少条(返回结果仍是升序,降序要自己处理)。 
     * orderBy&startAt
     * 返回大于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。 
     * orderBy&endAt
     * 返回小于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
     *  orderBy&equalTo
     * 返回等于指定的键、值或优先级的数据,具体取决于所选的排序方法。可用于精确查询。
     * 
     * @param function
     *            调用的Function
     * @param param
     *            查询的属性
     * @param val
     *            条数
     * @return
     */
    private List<T> query(String function,String param,String val){
        WilddogResponse resp;
        try {
            //排序  查询两条数据  limitToLast 最后几条
            Wilddog dog = this.getNewWilddog();
            dog.addQuery("orderBy", "\""+param+"\""); //对于查询的参数需要添加 \"\"
            dog.addQuery(function, val);
            resp = dog.get();
            List<T> result = this.formatDate(resp.getRawBody());
            return result;
        } catch (UnsupportedEncodingException | WilddogException e) {
            e.printStackTrace();
        }

        return null;
    }
    /**
     * 
     * @return
     */
    public String timestamp(){

        //查询云端时间戳
        Wilddog dog = this.getNewWilddog();
        return dog.timestamp();
    }
    /**
     * 设置从第一条开始,一共返回多少条数据(节点)。
     * @param param 查询的属性  
     * @param count 条数
     * @return
     */
    public List<T> limitToFirst(String param,Integer count) {
        return this.query("limitToFirst", param,String.valueOf(count));
    }

    /**
     * 设置从最后一条开始,一共返回多少条(返回结果仍是升序,降序要自己处理)。
     * @param param 查询的属性  
     * @param count 条数
     * @return
     */
    public List<T> limitToLast(String param,Integer count) {
        return this.query("limitToLast", param,String.valueOf(count));
    }

    /**
     * 返回大于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
     * @param param 查询的属性  
     * @param val 大于的值
     * @return
     */
    public List<T> startAt(String param,Integer val) {
        return this.query("startAt", param,String.valueOf(val));
    }

    /**
     * 返回小于或等于指定的键、值或优先级的数据,具体取决于所选的排序方法。
     * @param param 查询的属性  
     * @param val 大于的值
     * @return
     */
    public List<T> endAt(String param,Integer val) {

        return this.query("endAt", param,String.valueOf(val));
    }

    /**
     * 查询在某个字段中间的数据  ,age >1 ,age<20
     * @param param 参数
     * @param start 开始时间
     * @param end 结束时间
     * @return
     */
    public List<T> between(String param,Integer start,Integer end){
        try {
            Wilddog dog = this.getNewWilddog();
            WilddogResponse resp = dog.startAt(param, start).endAt(param, end).get();
            List<T> result = this.formatDate(resp.getRawBody());
            return result;
        } catch (UnsupportedEncodingException | WilddogException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 返回等于指定的键、值或优先级的数据,具体取决于所选的排序方法。可用于精确查询。
     * @param param 
     * @param val 
     * @return
     */
    public List<T> equalTo(String param,String val) {
        WilddogResponse resp;
        try {
            //排序  精确查询  orderBy 和equalTo ,判断等于的情况 
            Wilddog dog = this.getNewWilddog();
            resp = dog.equalTo(param,val).get();
            List<T> result = this.formatDate(resp.getRawBody());
            return result;
        } catch (UnsupportedEncodingException | WilddogException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 获取应用的Appid
     * 
     * @return
     */
    private String getAppid() {
        InputStream in = BaseDao.class.getClassLoader().getResourceAsStream("wilddog.properties");
        Properties prop = new Properties();
        try {
            prop.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return prop.getProperty("appid");
    }

    /**
     * 判断是否是数字
     * @param str
     * @return
     */
    public boolean isNumeric(String str) {
        //当没有数据的情况
        if(str == null || "".equals(str.trim())){
            return false;
        }

        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }

    @SuppressWarnings("deprecation")
    @Override
    public void update(T t) {
        try {
            String id = this.getParamteId(t);
            String jsonData = JsonUtils.object2Json(t);
            WilddogResponse resp =this.getWilddog().put(id, jsonData);
            System.out.println("["+new Date().toLocaleString()+"]\t UPDATE\t"+resp.getBody());
        } catch (UnsupportedEncodingException | WilddogException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean delete(T t) {
            try {
                String id = this.getParamteId(t);
                if(id != null && !"".equals(id)){
                    this.getWilddog().delete(id);
                    return true;
                }else{
                    return false;
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (WilddogException e) {
                e.printStackTrace();
            }
        return false;
    }

    /**
     * 获取参数的ID
     * @param t
     * @return
     */
    private String getParamteId(T t){
        try {
            return this.getClazz().getMethod("getId").invoke(t).toString();
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new RuntimeException("获取ID失败");
        }

    }
    /**
     * 添加数据
     * 
     * @param paramT
     * @return
     */
    @SuppressWarnings("deprecation")
    public T add(T paramT) {
        try {
            String id = UUID.randomUUID().toString();
            this.getClazz().getMethod("setId", String.class).invoke(paramT, id);
            String jsonDate= JsonUtils.object2Json(paramT);

            WilddogResponse resp = this.getWilddog().put(id,jsonDate);
            //updateId(resp);
            System.out.println("["+new Date().toLocaleString()+"]\t ADD\t"+resp.getBody());
        } catch (Exception e) {
            e.printStackTrace();
        } catch (WilddogException e) {
            e.printStackTrace();
        }
        return paramT;
    }

    /**
     * 插入了数据后,我们需要做更新Id的处理
     */
    @SuppressWarnings("unused")
    private void updateId(WilddogResponse resp){
        try {
            String id = this.getReturnId(resp);
            Map<String,Object> param = new HashMap<String,Object>();
            param.put("id", id);
            this.getWilddog().patch(id, param);
        } catch (UnsupportedEncodingException | WilddogException | JacksonUtilityException e) {
            throw new RuntimeException("id更新失败");
        }
    }

    /**
     * 获取返回的ID
     * @param resp
     * @return
     */
    private String getReturnId(WilddogResponse resp){
        String str = resp.getRawBody();

        return str.substring(9,str.length()-2);
    }

    @SuppressWarnings("deprecation")
    @Override
    public List<T> addList(List<T> objs) {
        try {
            Map<String, T> map = new HashMap<String, T>();
            for (T obj : objs) {
                String id = UUID.randomUUID().toString();
                this.getClazz().getMethod("setId", String.class).invoke(obj, id);

                map.put(id, obj);
            }
            String jsonDate = JsonUtils.object2Json(map);
            WilddogResponse resp = this.getWilddog().put(jsonDate);
            System.out.println("["+new Date().toLocaleString()+"]\t ADD LIST \t"+resp.getBody());

        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException | UnsupportedEncodingException | WilddogException e) {
            throw new RuntimeException("添加集合失败");
        }

        return  objs;
    }


    @Override
    public void deleteAllData() {
        try {
            Wilddog wilddog = new Wilddog(this.getAppUrl());

            wilddog.delete();           

            SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
            String dateNow = format.format(new Date());
            System.out.println("["+dateNow+"]\tDELETE ALL DATA");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (WilddogException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<T> load(String param, String val) {
        return this.equalTo(param, val);
    }

    @Override
    public List<T> queryByPage(int pageNow, int pageSize) {
        return this.queryByPage("id",  pageNow, pageSize);
    }

    @Override
    public List<T> queryByPage(String field,int pageNow, int pageSize) {
        // TODO Auto-generated method stub
        try {
            if(pageNow <= 0){
                pageNow = DEFAULT_PAGE_NOW;
            }
            if(pageSize <=0){
                pageSize = DEFAULT_PAGE_SIZE;
            }

            int recordCnt = this.getCount();
            //页面的数目
            int pageCnt = (recordCnt-1)/pageSize +1;

            //当页面超过最大页条数,就可以直接返回空了,不用去查询数据了
            if(pageNow >pageCnt){
                return null;
            }
            //当不是从第一页开始的情况
            WilddogResponse resp = this.getNewWilddog().limitToFirst(field,pageNow*pageSize).get();
            String content = resp.getRawBody();
            List<T> result = this.formatDate(content);
            //由于有删除的操作,数据不是静态的,所以分页就显得比较的麻烦了
            //将数据过滤掉
            result = result.subList((pageNow-1)*pageSize, result.size());

            return result;
        } catch (UnsupportedEncodingException | WilddogException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //int pageStart = 
        return null;
    }
}

案例

User数据模型类

数据模型类中,必须有String id这个属性,因为我们的分页查询、删除、更新都是基于这个ID来做的,这个地方,我是继承了Model对象,这个对象里面有setId 和getId的操作

package com.yellowcong.model;

import com.wilddog.annotation.WilddogTable;

/**
 * 定义的表格对象,都必须继承Model这个对象,因为Model中有设定ID的方法,id是自己生成的,不是服务器生成的
 * @author yellowcong
 * @date 2017年7月16日
 */
@WilddogTable("user")
public class User extends Model{
    private String username;
    private String nickname;
    private String email;
    private int age;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getNickname() {
        return nickname;
    }
    public void setNickname(String nickname) {
        this.nickname = nickname;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

UserDao

package com.yellowcong.dao;

import com.yellowcong.model.User;

public interface UserDao extends BaseDao<User>{

}

UserDaoImpl

package com.yellowcong.dao.impl;

import com.yellowcong.dao.UserDao;
import com.yellowcong.dao.impl.BaseDaoImpl;
import com.yellowcong.model.User;

/**
 * 用户对象操作
 * @author yellowcong
 *
 */
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao{

}

测试类

package com.yellowcong.client.test;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import com.wilddog.client.rest.error.WilddogException;
import com.wilddog.client.rest.model.WilddogResponse;
import com.wilddog.client.rest.service.Wilddog;
import com.yellowcong.dao.UserDao;
import com.yellowcong.dao.impl.UserDaoImpl;
import com.yellowcong.model.User;

/**

写入数据

 * @author yellowcong
 * @date 2017年7月16日
 */
public class UserDaoTest {
    private UserDao dao ;
    @Before
    public void setUp(){
        dao = new UserDaoImpl();
    }
    //添加数据
    @Test
    public void testAddUser() throws Throwable{
        for(int i=1;i<100;i++){
            User user = new User();
            user.setAge(i);
            user.setEmail("717350389@qq.com");

            UserDao dao = new UserDaoImpl();
            dao.add(user);
        }
    }

    /**
     * 一次添加多个数据
     */
    @Test
    public void testAddList(){
        List<User> users = new ArrayList<User>();
        for(int i=1;i<100;i++){
            User user = new User();
            user.setAge(i);
            user.setEmail("717350389@qq.com");

            users.add(user);
        }

        dao.addList(users);
    }
    /**
     * 获取所有数据
     */
    @Test
    public void testList(){

        List<User> users = dao.listAll();
        for(User user:users){
            System.out.println(user.getId());
            System.out.println(user.getEmail());
        }
    }

    /**
     * 获取数据的行数
     */
    @Test
    public void testGetCount(){
        int cnt = this.dao.getCount();
        System.out.println("tiao shu \t "+cnt);
    }

    /**
     * 删除所有数据
     */
    @Test
    public void testDeletAll(){
        dao.deleteAll();

    }

    /**
     * 删除一条数据,删除具体的莫一条数据
     */
    @Test
    public void testDelete(){

        System.out.println(dao.getCount());
        List<User> users = dao.equalTo("age", "2");
        if(users != null && users.size() >0){
            for(User user:users){
                this.dao.delete(user);
            }
        }
        System.out.println(dao.getCount());
    }
    /**
     * 通过字段,删除数据
     */
    @Test
    public void testDeletByParam(){
        System.out.println(dao.getCount());
        this.dao.delete("age", "12");
        System.out.println(dao.getCount());
    }

    //清空数据库所有数据
    @Test
    public void testDeleteAllDate(){
        UserDao dao = new UserDaoImpl();
        dao.deleteAllData();
    }

    /**
     * 更新数据
     */
    @Test
    public void testUpdate(){
        List<User> users = dao.load("age", "22");

        for(User user: users){
            System.out.println(user.getAge()+":"+user.getEmail());
            System.out.println(user.getNickname()+":"+user.getEmail());

            /*user.setEmail("yellowcong@qq.com");
            user.setNickname("doubi");

            dao.update(user);*/
        }
    }

    @Test
    public void testPage(){
        int pageSize = (this.dao.getCount()-1)/10+1;
        for(int i=1;i<=pageSize;i++){
            List<User> users = this.dao.queryByPage(i,10);
            System.out.println("____________________第"+i+"页__________________");
            System.out.println("____________________共"+users.size()+"条__________________");
            for(User user:users){
                System.out.println(user.getAge());
            }
        }
    }

}