Skip to content

Doc004.ControllerType

Ping.X edited this page Feb 1, 2016 · 1 revision

如前所述,controller可以分为三大类型:一般controller默认controllerfilter

其中,默认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通过HapporContextaddController接口加入controller链。但也许你会觉得设置一堆controller会很麻烦,尤其在新增的时候,容易忘记addController。幸好happor同时提供了一种自动扫描controllers的配置方式,使用更为方便。

Clone this wiki locally