-
Notifications
You must be signed in to change notification settings - Fork 11
Doc004.ControllerType
如前所述,controller可以分为三大类型:一般controller、默认controller、filter。
其中,默认controller可以看作是一般controller的特例,不做特殊说明。而一般controller又可以分为3种子类型:
- 普通handler:继承
HttpNormalHandler基类 - 异步handler:继承
HttpAsyncHandler基类 - 转发handler:继承
HttpTransitHandler基类
而对于filter来说,目前只有一种子类型:
- 普通filter:继承
HttpNormalFilter基类
下面分别介绍这四种controller的使用方式:
##普通handler
public class TestNormalHandler extends HttpNormalHandler {
@Override
protected void handle(FullHttpRequest request, FullHttpResponse response) {
// TODO Auto-generated method stub
String words = "hello world";
response.content().writeBytes(words.getBytes());
response.headers().set("Content-Type", "text/plain");
response.headers().set("Content-Length", response.content().readableBytes());
}
@Override
protected void atlast() {
// TODO Auto-generated method stub
}
}HttpNormalHandler要求子类实现两个方法:
-
handle:处理request,对response进行加工。函数返回后,框架会把response返回给客户端,然后关闭连接。 -
atlast:在关闭连接后,框架会调用这个函数。使用者可以在这个函数中做一些额外的异步操作,例如向MQ推送消息。
##异步handler
public class TestAsyncHandler extends HttpAsyncHandler {
@Override
protected void handle(FullHttpRequest request, final FullHttpResponse response) {
// TODO Auto-generated method stub
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
response.content().writeBytes("test async ok!".getBytes());
response.headers().set("Content-Type", "text/plain");
response.headers().set("Content-Length", response.content().readableBytes());
finish(response);
}
}.start();
}
}对于一些不能立即得到HTTP响应,需要异步返回的处理,如果使用普通handler就会把框架的业务线程阻塞住,影响整个webserver的性能。此时,我们就需要使用异步handler。
HttpAsyncHandler要求子类实现handle方法。与HttpNormalHandler不同的是,这个handle方法返回后,框架不会把response返回给客户端,也不会关闭连接。使用者可以在别的线程中调用finish函数返回指定的response,之后框架会把连接自动关闭。
##转发handler
public class TestTransitHandler extends HttpTransitHandler {
@Override
protected void incoming(FullHttpRequest request) {
// TODO Auto-generated method stub
request.headers().add("x-incoming", "1");
transit("127.0.0.1", 9080);
}
@Override
protected void outgoing(FullHttpResponse response) {
// TODO Auto-generated method stub
response.headers().add("x-outgoing", "1");
response.content().writeBytes(" - transit back".getBytes());
response.headers().set("Content-Length", response.content().readableBytes());
}
}还有另外一类场景,我们需要把接收进来的HTTP请求转发到别的webservice处理,得到HTTP响应后再返回,类似Nginx的反向代理。对于这种情况,我们可以使用转发handler。
HttpTransitHandler要求子类实现两个方法:
-
incoming:接收到的HTTP请求,可对request做一些自定义处理。通过调用transit(ip, port)函数将request转发出去。 -
outgoing:转发后得到的HTTP响应从这个方法上来,可对response做一些自定义处理。
##普通filter
public class TestIncomingFilter extends HttpNormalFilter {
@Override
protected void incoming(FullHttpRequest request) {
// TODO Auto-generated method stub
System.out.println("incoming...");
request.headers().set("x-filter-incoming", getClass().getSimpleName());
}
@Override
protected void outgoing(FullHttpResponse response) {
// TODO Auto-generated method stub
System.out.println("outgoing...");
response.headers().set("x-filter-outgoing", getClass().getSimpleName());
}
}普通filter和转发handler看起来很相似,都需要子类实现incoming方法和outgoing方法。区别在于,转发handler是将request转发到别的HTTP服务去,而filter是将request传递到controller链的下一个节点。
如上节所述,所有的controller通过HapporContext的addController接口加入controller链。但也许你会觉得设置一堆controller会很麻烦,尤其在新增的时候,容易忘记addController。幸好happor同时提供了一种自动扫描controllers的配置方式,使用更为方便。