虽然标题是有点浮夸,但的确实现了部分功能
有时候要用android当服务器去进行数据传输,如局域网的文件传输功能,这些用http服务去做是比较好的选择.
既然要用到http服务,那使用NanoHttpd是最好的选择之一,只有一个文件但可以完成很多http服务的功能.
但使用NanoHttpd的时候会有很多的不便,例如我们每次都要对uri进行分析,这样就使得代码臃肿,请求的方法过多的话,那看上去就会一脸懵,大大的降低代码可读性.
对于使用NanoHttpd的各种不便,然后就二次封装了下,就出了我个人认为是android界的spring-boot的http服务框架(有点傻的想法).
DEMO代码
是不是有点像spring的风格,代码瞬间就简洁了.整个人瞬间愉悦起来.
框架原理
是根据NanoHttpd二次开发,主要使用了注解反射来实现url的映射,代码也不多,轻量级,以下是关键代码
/**
* 解析注解文件
*
* @param session
* @param file_name
* @return
*/
private Response responseData(IHTTPSession session, String file_name) {
Response response;
Object[] objects = null;
try {
Map methods = FHttpManager.getFHttpManager().getMethods();
java.lang.reflect.Method method = methods.get(file_name);
if (method != null) {
method.setAccessible(true); //允许修改反射属性
Class cla = method.getDeclaringClass();//获取该方法所在的类
Object obj = cla.newInstance();//实例化类
Class>[] parameterTypes = method.getParameterTypes(); //获得方法所有参数的类型
if (parameterTypes.length > 0) {
objects = new Object[parameterTypes.length];
Map sessionMap = session.getParms();//获取请求参数
Annotation[][] parameterAnnotations = method.getParameterAnnotations();//获取方法参数里的注解
for (int i = 0; i < parameterAnnotations.length; i++) {
if (parameterTypes[i] == IHTTPSession.class) {
objects[i] = session;
} else if (parameterTypes[i] == Map.class) {
objects[i] = sessionMap;
} else {
Annotation parameterAnnotation = parameterAnnotations[i][0];//获取参数中的第一个注解。所以每个参数只能只有一个注解
if (parameterAnnotation.annotationType() == RequestBody.class) {//返回对象
byte[] buf = new byte[(int) ((HTTPSession) session).getBodySize()];
session.getInputStream().read(buf, 0, buf.length);
objects[i] = new Gson().fromJson(new String(buf), parameterTypes[I]);
} else if (parameterAnnotation.annotationType() == RequestParam.class) {//返回指定param
objects[i] = dataConversion(parameterTypes[i], sessionMap, (RequestParam) parameterAnnotation);
}
}
}
}
response = responseBody(method.getReturnType(), method.invoke(obj, objects), method.isAnnotationPresent(ResponseBody.class));
} else {
response = newFixedLengthResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, file_name + " Not Found");
}
} catch (Exception e) {
response = newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, e.getMessage());
}
return response;
}
框架功能及使用
1. 框架功能介绍
这是根据NanoHttpd二次开发的一个轻量级,使用简单,功能比较强大的一个http服务框架.
可以实现:
- 支持get请求
- 支持post请求
- 支持文件上传
- 支持文件下载
- 支持自定义端口号
- 支持自定义静态资源目录(默认assets的根目录,也可以指定sd卡的自定义目录)
- 支持静态资源文件过滤(由于指定的是assets根目录,会有很多系统自带的xml文件,就做了这个)
- 支持注解的使用(这框架不用注解还真没法用)
- 支持以对象来响应
- 支持请求以对象接收
- ...
基本满足http服务的正常使用需求(硬是瞎编了那么多功能...)
2.框架里的几个注解
注解 | 含义 |
---|---|
@RequestBody | 方法里的属性注解,使用该注解可指定以对象返回 主要用于处理json请求 |
@RequestParam("") | 方法里的属性注解,使用该注解可指定param值返回 主要用于处理get,post的请求 |
@RequestMapping("") | 方法注解, 使用该注解是映射url ,把url 指定到对应的方法中处理数据 |
@ResponseBody | 方法注解,使用该方法可以对象返回经过处理吐出json数据返回给客户端 |
以上注解的使用可看前面的图片
3. 框架使用
- gradle添加
compile 'cn.hotapk:fhttpserver:0.2.0'
- manifest添加权限
- 初始化
fHttpManager = FHttpManager.init(this, UserController.class);
fHttpManager.setPort(9999);
...
UserController.class 是进行url映射的类, 可添加多个这样的类
public class UserController {
@RequestMapping("userls")
public NanoHTTPD.Response getUserLs() {
return setResponse("user列表");
}
@ResponseBody
@RequestMapping("getuser")
public UserBean getUser() {
return new UserBean("admin", "admin");
}
...
- 开启http服务
fHttpManager.startServer();
- 文件下载
NanoHTTPD.Response response = NanoHTTPD.newChunkedResponse(NanoHTTPD.Response.Status.OK, "application/octet-stream", inputStream);//这代表任意的二进制数据传输。
response.addHeader("Accept-Ranges", "bytes");
response.addHeader("Content-Disposition", "attachment; filename="+"test.java")//可以这里返回文件名称
- 文件上传
/**
* 文件上传
*
* @param session
* @param fileDir 保存文件的目录
* @param parm 上传文件的参数
* @return
*/
public static boolean uploadFile(NanoHTTPD.IHTTPSession session, String fileDir, String parm) {
Map files = new HashMap<>();
try {
session.parseBody(files);
Map parms = session.getParms();
return FFileUtils.copyFileTo(files.get(parm), fileDir + "/" + parms.get(parm));
} catch (IOException e) {
e.printStackTrace();
} catch (NanoHTTPD.ResponseException e) {
e.printStackTrace();
}
return false;
}
- index.html 文件冲突
该框架默认打开index.html文件,如果不希望用这文件名可如下修改
fHttpManager.setIndexName(" ")
4. 框架使用demo
这块就不出详细demo了
可以到我另外一个项目查看
这是一个android调试数据库的神器
5.框架代码讲解
这方面就不讲了,主要使用注解反射实现,其它也没什么的了
6.框架名称
FHttpServer
以上是FHttpServer框架的全部内容,谢谢观看,欢迎使用.
同时希望各位在使用中遇到什么问题或建议可以用以下联系方式进行反馈
个人博客
github地址(感兴趣的话,不妨点赞支持下)