androidasync 搭建个人Android 小型服务器
由于需求问题,当前一台设备创建一个Android小型的服务器供下方关联的设备的获取主设备的一些数据
于是就用到了androidasync
1.引入:implementation ‘com.koushikdutta.async:androidasync:3.1.0’`
2.创建:ApiCodeMsg文件
public class ApiCodeMsg {
private int code;
private String msg;
public ApiCodeMsg fillArgs(Object...args){
int code = this.code;
String message = String.format(this.msg,args);
return new ApiCodeMsg(code,message);
}
private ApiCodeMsg(int code, String msg) {
this.code=code;
this.msg=msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
@Override
public String toString() {
return "ApiCodeMsg{" +
"code=" + code +
", msg='" + msg + '\'' +
'}';
}
/**
* 返回码
*/
class CODE {
//成功
static final int REQUEST_SUCCESS = 200;
static final int REQUEST_ERROR_CONTEXT_IS_NULL = 201;
static final int REQUEST_ERROR_404 = 404;
}
/**
* 描述信息
*/
class MSG {
//成功
static final String REQUEST_SUCCESS = "request success!";
static final String REQUEST_ERROR_CONTEXT_IS_NULL = "HttpServer init error, context is null!";
static final String REQUEST_ERROR_404 = "No this url!";
}
//通用的异常
public static ApiCodeMsg REQUEST_ERROR_CONTEXT_IS_NULL = new ApiCodeMsg(CODE.REQUEST_ERROR_CONTEXT_IS_NULL, MSG.REQUEST_ERROR_CONTEXT_IS_NULL);
public static ApiCodeMsg REQUEST_ERROR_404 = new ApiCodeMsg(CODE.REQUEST_ERROR_404, MSG.REQUEST_ERROR_404);
}
2.创建ApiResult
public class ApiResult<T> {
private int code;
private String msg;
private T data;
private ApiResult(T data) {
this.code = ApiCodeMsg.CODE.REQUEST_SUCCESS;
this.msg = ApiCodeMsg.MSG.REQUEST_SUCCESS;
this.data = data;
}
private ApiResult(ApiCodeMsg mg) {
if (mg == null) {
return;
}
this.code = mg.getCode();
this.msg = mg.getMsg();
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
/**
* 成功
*
* @param data
* @param <T>
* @return
*/
public static <T> ApiResult<T> success(T data) {
return new ApiResult<>(data);
}
public static <T> ApiResult<T> fail(ApiCodeMsg msg) {
return new ApiResult<>(msg);
}
}
4.设置缓存策略接口ICache
/**
* 缓存接口定义
*/
public interface ICache {
/**
* 获取缓存
*
* @param key
* @return
*/
Object getValueBySearch(String key);
/**
* 获取缓存大小
*
* @return int
*/
int size();
/**
* 缓存是否为空
*
* @return boolean
*/
boolean isEmpty();
/**
* 是否包含指定key的缓存
*
* @param key
* @return boolean
*/
boolean containsKey(String key);
/**
* 是否包含指定value的缓存
*
* @param value
* @return boolean
*/
boolean containsValue(String value);
/**
* 获取缓存
*
* @param key
* @return Object
*/
Object get(String key);
/**
* 设置缓存
*
* @param key
* @param value
*/
void put(String key, Object value);
/**
* 删除对于key-value
*
* @param key
*/
void remove(String key);
/**
* 清除全部缓存
*/
void clear();
}
5.使用ConcurrentHashMap缓存数据类
/**
* 此缓存策略是,读写都加锁,线程安全
*/
public class ConcurrentHashMapCache implements ICache {
private static final String TAG = "ConcurrentHashMapCache";
//声明一个线程安全的ConcurrentHashMap,用来作为缓存模型
private static ConcurrentHashMap<String, Object> cacheMap = new ConcurrentHashMap<>();
private StringBuffer stringBuffer = new StringBuffer();
@Override
public Object getValueBySearch(String key) {
if (cacheMap.isEmpty()) {
return "";
}
stringBuffer.setLength(0);
stringBuffer.append("[");
for (Map.Entry<String, Object> entry : cacheMap.entrySet()) {
LogUtils.i( "getValueBySearch: " + Thread.currentThread().getName() + " - [" + entry.getKey() + ", " + entry.getValue() + ']');
if (entry.getKey().contains(key) && !TextUtils.isEmpty(String.valueOf(entry.getValue()))) {
stringBuffer.append(entry.getValue());
stringBuffer.append(",");
}
}
stringBuffer.setCharAt(stringBuffer.length() - 1, ']');
return stringBuffer.toString();
}
@Override
public int size() {
return cacheMap.size();
}
@Override
public boolean isEmpty() {
return cacheMap.isEmpty();
}
@Override
public boolean containsKey(String key) {
return cacheMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return cacheMap.containsValue(value);
}
@Override
public Object get(String key) {
return cacheMap.get(key);
}
@Override
public void put(String key, Object value) {
cacheMap.put(key, value);
}
@Override
public void remove(String key) {
cacheMap.remove(key);
}
@Override
public void clear() {
cacheMap.clear();
}
}
6.创建缓存管理类 HttpServerCache
/**
* 数据缓存处理
*/
public class HttpServerCache {
private static class InstanceHolder {
private static final HttpServerCache INSTANCE = new HttpServerCache();
}
public static HttpServerCache getInstance() {
return InstanceHolder.INSTANCE;
}
/**
* 缓存策略
*/
private ICache iCache;
public ICache getCache() {
if (iCache == null) {
iCache = new ConcurrentHashMapCache();
}
return iCache;
}
public void setCache(ICache iCache) {
this.iCache = iCache;
}
}
7.httpServier ,最重要的一个环节
public class HttpServer implements HttpServerRequestCallback {
private static final String TAG = "HttpServer";
private volatile static HttpServer httpServer;
@SuppressLint("StaticFieldLeak")
private static Context mContext;
public static void setContext(Context mContext) {
HttpServer.mContext = mContext;
}
private HttpServer() {
}
//双重检测
public static HttpServer getHttpServer() {
if (httpServer == null) {
synchronized (HttpServer.class) {
if (httpServer == null) {
httpServer = new HttpServer();
}
}
}
return httpServer;
}
//静态内部类
private static class httpServerHolder {
private static final HttpServer INSTANCE = new HttpServer();
}
public static final HttpServer getInstance() {
return httpServerHolder.INSTANCE;
}
private AsyncHttpServer asyncHttpServer = new AsyncHttpServer();
private static int DEFAULT_PORT = 8088;
/**
* 开启本地服务
*/
public void startServer() {
asyncHttpServer.addAction("OPTIONS", "[\\d\\D]*", this);
asyncHttpServer.get("[\\d\\D]*", this);
asyncHttpServer.post("[\\d\\D]*", this);
asyncHttpServer.listen(DEFAULT_PORT);
}
@Override
public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
// Log.d(TAG, "onRequest: uri = " + request.getPath());
System.out.println("onRequest: uri = " + request.getPath());
String uri = request.getPath();
//这个是获取header参数的地方,一定要谨记哦
Multimap headers = request.getHeaders().getMultiMap();
if (headers != null) {
//Log.i(TAG, "onRequest: " + headers.toString());
System.out.println("onRequest: " + headers.toString());
}
//注意:这个地方是获取post请求的参数的地方,一定要谨记哦
Multimap multimap = ((AsyncHttpRequestBody<Multimap>) request.getBody()).get();
//GET/POST等请求方式
String method = request.getMethod();
// Log.i(TAG, "onRequest: method=" + method);
System.out.println("onRequest: method=" + method);
//query 是GET请求方式的参数
String query = request.getQuery().toString();
// Log.i(TAG, "onRequest:query= " + query);
System.out.println("onRequest:query= " + query);
//目前采用GET方式
if (TextUtils.equals(method, AsyncHttpGet.METHOD)) {
newApiResult(uri, request.getQuery());
} else {
if (TextUtils.isEmpty(newApiResult(uri, multimap))) {
newApiResult(uri, multimap);
}
}
}
private static String newApiResult(String uri, Multimap multimap) {
String lastModifyTime;
String num;
if (multimap == null) {
multimap = new Multimap();
}
lastModifyTime = multimap.getString("lastModifyTime");
num = multimap.getString("num");
String result;
switch (uri) {
case "/test":
return GsonUtils.toJson(ApiResult.success("请求成功!"));
case "/getMessage":
if (TextUtils.isEmpty(num)) {
if (HttpServerCache.getInstance().getCache().isEmpty()) {
return GsonUtils.toJson(ApiResult.success(new ArrayList()));
}
result = HttpServerCache.getInstance().getCache().getValueBySearch(uri) + "";
} else {
result = HttpServerCache.getInstance().getCache().get(num + uri) + "";
}
List<String> zoneList = GsonUtils.fromJson(result, new TypeToken<ArrayList<String>>() {
}.getType());
return GsonUtils.toJson(ApiResult.success(zoneList));
default:
return GsonUtils.toJson(ApiResult.fail(ApiCodeMsg.REQUEST_ERROR_404));
}
}
}
最后,开启服务
只要调用:
HttpServer.setContext(getApplicationContext());
HttpServer.getInstance().startServer();
9.接下来我们就要请求服务器的数据了
创建一个客户端管理HttpClient;
/**
* 和HttpServer配套的客户端
*/
public class HttpClient {
private static final String TAG = "HttpServer";
private static HttpClient mInstance;
private AsyncHttpClient asyncHttpClient = AsyncHttpClient.getDefaultInstance();
private static class Instance {
private static HttpClient instance = new HttpClient();
}
private HttpClient() {
}
public static HttpClient getInstance() {
return Instance.instance;
}
// public static HttpClient getInstance() {
// if (mInstance == null) {
// synchronized (HttpClient.class) {
// if (mInstance == null) {
// mInstance = new HttpClient();
// }
// }
// }
// return mInstance;
// }
public AsyncHttpClient getAsyncHttpClient() {
return asyncHttpClient;
}
}
之后只要就可以请求到服务器的数据了
AsyncHttpRequest areaAsyncHttpRequest = new AsyncHttpRequest(Uri.parse(String.format(Constant.URL_PATIENT_AREA, hostIP)), AsyncHttpGet.METHOD);
HttpClient.getInstance().getAsyncHttpClient().executeJSONObject(areaAsyncHttpRequest, new AsyncHttpClient.JSONObjectCallback() {
@Override
public void onCompleted(Exception e, AsyncHttpResponse source, JSONObject result) {}}
注意:URL_PATIENT_AREA 代表接口名称 比如192.168.1.1:8088/test