野狗云的API说实话,不是特别的好用,对于分页操作和查询是鸡肋,对于这两个操作我就不过多吐槽了,但是我想吐槽一下,野狗云的确很坑,当里把数据往死里写,超过了250MB后,你的服务就用不了了(当时我用多线程,做的实验,后悔死了),开启今天的正文,我的项目源码在github上,过多的就不介绍了。
封装官方的API
wilddog.properties
这个配置文件用于配置自己的项目id,这个配置文件,我不删,你们随便拿我的玩,反正不花钱,哈哈哈哈哈….
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());
}
}
}
}