- 源码地址:https://github.com/yanzhenjie/AndServer/
- 文档地址:https://yanzhenjie.github.io/AndServer/
- 旧版文档:https://yanzhenjie.github.io/AndServer/1.x/
AndServer 是 Android 平台的 Web Server 和 Web Framework。 它基于编译时注解提供了类似 SpringMVC 的注解和功能,如果您熟悉 SpringMVC,则可以非常快速地掌握它。
特性
- 部署静态网站
- 动态 HTTP API,使用注解
- 全局请求拦截器,使用注解
- 全局异常处理器,使用注解
- 全局消息转换器,使用注解
依赖
添加依赖时请替换下述 {version} 字段为https://github.com/yanzhenjie/AndServer/releases上公开的最新版本号。
dependencies {
implementation 'com.yanzhenjie.andserver:api:{version}'
annotationProcessor 'com.yanzhenjie.andserver:processor:{version}'
}
架构
AndServer2.0 基于编译时注解实现了 SpringMVC 的大部分注解 API Request 的分发流程也基本和 SpringMVC 一致,与 SpringMVC 最大的不同是 SpringMVC 基于运行时注解。
看到这里读者朋友应该知道了,AndServer2.0 是使用注解开发 Web 程序的,为了有个更直观的了解,我们先看一个模拟用户登录的 HTTP API:
@RestController
public class UserController {
@PostMapping("/login")
public String login(@RequestParam("account") String account,
@RequestParam("password") String password) {
if(...) {
return "Successful";
}
return "Failed";
}
}
假设服务端的 Address 是192.168.1.11,监听的端口是8080,那么通过http://192.168.1.11:8080/login就可以访问该登录 HTTP API 了。
下文将依次介绍以下三点:
- 系统层架构
- 应用层架构
- 使用示例
1. 系统层架构
我们都知道 HTTP 是根据 HTTP 协议使用 Socket 做了连接属性、数据格式、交互逻辑方面的包装,我们来模拟一段服务端启动 Server 的代码:
public void startServer(String address, int port) {
InetAddress inetAddress = InetAddress.getByName();
ServerSocket serverSocket = new ServerSocket(8080, 512, inetAddress);
while (true) {
Socket socket = serverSocket.accept();
HttpConnection connection = HttpParser.parse(socket);
HttpThead thread = new HttpThread(connection);
thread.start();
}
}
ServerSocket监听了某个端口,当有Socket连接上来的时候去把这个Socket解析为HttpConnection,解析过程是按照 Http 协议拟定的格式,从Socket的InputStream读取一些数据后,用Request和Response包装Socket和未读取的流(比如标记下次读取流的起点),下文会再提到。
接着HttpParser用HttpConnection包装了Request和Reponse返回,可想而知,作为服务端程序,HttpConnection至少包涵了Request和Response对象:
public class HttpConnection {
private Request mRequest;
private Response mResponse;
...
}
紧接着启动了一个线程去处理当前连接,其实也就是处理当前Request,用Response写出数据,怎么处理这个Request是一个 WebFramework 的核心,作为 Http 服务端程序,应该能提供 Html 文件、JS 文件、Java Method(HTTP API)等让客户端访问,因此得有一个管理员来负责请求和资源的匹配,所以有一个叫做HttpDispatcher的类来决定这个Request应该发给哪个资源去处理:
public class HttpDispatcher {
public void dispath(Request request, Response response) {
...
}
}
在HttpThead里面,当线程被唤起时只需要负责调用HttpDispatcher#diaptch()即可,到这里就比较清晰了,只需要HttpDispatcher把当前Request派发到对应的 Html File 或者 Java Method 处理就可以了,具体的处理就属于 HttpFramework 的事,我们下文再讲。
这就是一个简单的 WebServer 的蓝图,我们根据设想画出了系统层架构图:
系统层运行时流程图:

上图中,Handler表示处理请求的操作手柄,可能是 Html File 或者 Java Method。值得高兴的一点是,在我们迭代了几个版本后,发现 Apache 组织提供了上述蓝图中的HttpParser层,因此为了稳定性和节省人力我们已经替换该层为 Apache 的实现。
2. 应用层架构
应用层就是上文中提到的 WebFramework,也就是上一个小节流程图的Framework层,包括了 Session 的处理、Cookie 的处理、Cache 的处理等。
接着上文,HttpDispatcher需要把当前Request派发到对应的 Html File 或者 Java Method 处理,而Handler代表了 Html File 或者 Java Method,因为此二者区别极大,用一个类来表示它们显然有些不合理,于是我们想到了使用Adapter模式,所以有了一个抽象类RequestHandler:
public abstract class RequestHandler {
public abstract void handle(Request request, Response response);
}
RequestHandler可以表示任何文件或者 Java Method,HttpDispatcher的作用是分发请求到各个资源,所以HttpDispatcher不应该来分析某个RequestHandler具体是什么东西,它应该直接调用RequestHandler来处理请求,因为 Html File 或者 Java Method 对应的RequestHandler在实现上显然大有不同,所以这里适用Adapter模式,于是我们用HandlerAdapter去做RequestHandler的适配:
public class HandlerAdapter {
public RequestHandler getHandler(Request request) {
...
}
...
}
HandlerAdapter除了能获取RequestHandler之外,还需要做一些描述性的工作,好让HttpDispatcher知道当前适配的RequestHandler是可以处理正要分发的这个Request的。
因为 Html File 和 Java Method 的返回值又是大相径庭,因为返回值是输出到客户端展示的,所以我们把返回值抽象为View:
public class View {
public Object output() {
...
}
...
}
如上所以,output()方法就是获取Handler输出的内容,还有其他方法是对这个输出的描述,这里不例举。
因为View是返回值,没有具体的交互了,所以不适用Adapter模式了,因此我们必须有一个处理返回值的机制,把处理返回值的机制叫做ViewResolver:
public class ViewResolver {
public void resolver(View view, Request request, Response response) {
...
}
}
在ViewResolver中根据输出内容的类型不同,处理方式也不同,最终把输出内容通过Response对象写出去,底层是使用上文中提到的被Response包装的Socket写出。
这就是一个简单的 WebFramework 的蓝图,我们根据设想画出了应用层架构图:
应用层运行时流程图:

上图中,Interceptor表示对请求的拦截器,比如可以做一些不允许没登录或者没权限的请求进入的工作。ExceptionResolver表示全局异常处理器,比如某个 Api 发生了异常,会转到ExceptionResolver中处理,而不至于当前请求不响应或者响应了不想被客户端看到的消息。
另外需要补充的是,上文中提到的都是粗略的设计,中间还有一些细节,例如 Session 的处理、Cookie 的处理、缓存的处理等都未提到,其中任何一个知识点单独拿出来都可以写一篇文章,由于篇幅关系这里不做详细介绍。
架构设计和流程到此就都介绍完了,有兴趣的开发者也可以自己实现一下。