欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用内嵌的HTTP服务器构建Java WEB应用【转】

程序员文章站 2022-05-08 22:54:16
...

通常我们会在众多的J2EE标准的基础上来构建自己的Java WEB应用,比如最常见的Servlet。这样写出来的程序可以在所有符合J2EE标准的WEB服务器上运行,比如Tomcat,JBoss等等。事实上大多数Java WEB项目也正是采用这种架构,这么做有很多很多好处。但是这么做也有一些问题,J2EE标准和J2EE服务器隐藏了大部分的HTTP底层消息处理细节,如果你的应用不需要利用的众多J2EE特性,或者需要一个严苛的性能要求,又或者希望可以自己处理一些HTTP底层,那么可以考虑采用内嵌的JAVA HTTP服务器,这些Embedded Java Http Server主要包括了:

  • Netty,采用NIO,它来自JBoss,部分实现了zero-copy,而且文档和例子充足;
  • Grizzly,GlassFish V3的内核。
  • AsyncWeb,基于Apache Mina作为底层的NIO框架,性能不错,但是好像不更新了。

Apache Mina找不到打包好的代码,你似乎只能通过SVN来获得了,svn checkout http://svn.apache.org/repos/asf/mina/asyncweb/trunk。

所有这些内嵌服务器都可以方便的嵌入到你的Java应用中,并且体积小巧,可以通过编程的方法详细的控制从Http消息的全部生存周期。更加优秀的是它们的新能,采用NIO或者Temp Selector(Grizzly),它们的处理速度已经比tomcat这种“庞然大物”高出许多,在应用中你了解并且可以控制所有底层到高层的细节,这让后期的优化更加容易。当然,代价是你必须放弃J2EE带来的许多方便的特性,比如Servlet,数据源等等。如果你用过Playframework的话,就会了解到Servlet并不是最好的Java WEB架构(最起码不是“唯一”),而且体会到摆脱那些既有的J2EE标准的好处,现在playframework采用了Netty作为它的底层HTTP服务器。

Netty

Netty比其它两个更加“易于入门”,因为它有很多的文档和充足的例子,并且经过简单的代码,你就可以立即获得一个HTTP服务器。Playframework采用了Netty作为它的底层HTTP服务器。

JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class NettyServer {
 
	public static int httpPort;
	public static int httpsPort;
 
	public static void main(String[] args) throws Exception {
    	       new NettyServer(args);//new 操作即是启动服务器的方法
        }
 
	public NettyServer(String[] args) {
		System.setProperty("file.encoding", "utf-8");
		httpPort = 8000;
		ServerBootstrap bootstrap = new ServerBootstrap(
				new NioServerSocketChannelFactory(
						Executors.newCachedThreadPool(),
						Executors.newCachedThreadPool()));
		try {
			bootstrap.setPipelineFactory(new HttpChannelPipelineFactory());//应用的业务逻辑接入点
			bootstrap.bind(new InetSocketAddress(httpPort));
 
		} catch (ChannelException e) {
			Logger.error("Could not bind on port " + httpPort, e);
			System.exit(-1);
		}
 
	}
}

Grizzly

Grizzly宣称自己的框架性能最好,它也是GlassFish的Http引擎(不过GlassFish我用着到不怎么好…)。
下面这个是Playframework grizzly module的一个例子

JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Server {
    final GrizzlyWebServer ws;
    public Server(File applicationDir) {
        Properties p = Play.configuration;
        int httpPort = 80;     
        httpPort = Integer.parseInt(System.getProperty("http.port"));
        ws = new GrizzlyWebServer(httpPort);
        ws.useAsynchronousWrite(true);
        ws.addGrizzlyAdapter(new PlayGrizzlyAdapter());//PlayGrizzlyAdapter是应用业务逻辑接口
        try {
            ws.start();//启动服务器,监听Http请求
        } catch (IOException e) {
            Logger.error("Could not bind on port " + httpPort, e);
            ws.stop();
            System.exit(-1);
        }
    }
 
    public static void main(String[] args) throws Exception {
        File root = new File(System.getProperty("application.path"));
        new Server(root, System.getProperty("play.id", ""));
    }
 
}

AsyncWeb

这个项目好长时间不更新了,原来playframework是用AsyncWeb作为HTTP服务器的,但是最近改成了Netty。AsyncWeb和其它两个框架最不同的地方就是它可以采用Tomcat Native APR驱动底层socket接收框架,由于APR是一种本地库,可能更加有性能优势吧(没测试)。AsyncWeb是基于著名的Java NIO框架Apache Mina的,虽然AsyncWeb的文档很少,但是Mina的文档却很充足,如果你对Mina熟悉的话,AsyncWeb那300多KB的代码很容易阅读,或者定制。

JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
    public static void main(String[] args) throws Exception {
        SocketAcceptor acceptor = new NioSocketAcceptor();//可以选择别的acceptor,比如APR
 
        acceptor.getFilterChain().addLast("codec",
                new ProtocolCodecFilter(new HttpCodecFactory()));
        acceptor.setReuseAddress(true);
        acceptor.getSessionConfig().setReuseAddress(true);
        acceptor.getSessionConfig().setReceiveBufferSize(1024);
        acceptor.getSessionConfig().setSendBufferSize(1024);
        acceptor.getSessionConfig().setTcpNoDelay(true);
 
        acceptor.setHandler(new HttpProtocolHandler());//实现自己的HTTP处理类,应用的接入点
 
        acceptor.bind(new InetSocketAddress(9012));//启动服务器,监听Http请求
    }
}
--EOF--

上一篇: 典型递归问题

下一篇: 函数递归