`
w7849516230
  • 浏览: 18562 次
文章分类
社区版块
存档分类
最新评论

Java处理http协议相关初步(二)——httpserver

 
阅读更多
这里的HttpServer,并不是哪里专门下载的类库了,而是在JDK1.6中自带的,在com.sun.net.httpserver包中,提供了简单的较高层次意义上的Http ServerAPI,可以构建内置的HTTP Server,支持Http和Https协议,提供了HTTP1.1的部分实现,没有被实现的那部分可以通过扩展已有的Http Server API来实现。程序员必须自己实现HttpHandler接口,HttpServer会调用HttpHandler实现类的回调方法来处理客户端请求,在这里,我们把一个Http请求和它的响应称为一个交换,包装成HttpExchange类,HttpServer负责将HttpExchange传给HttpHandler实现类的回调方法. (摘过来的,也是官方的描述说明)
通过下面使用一个简单的例子,就可以看到怎么使用它们了,详细的功能可以查看API文档。访问localhost:8086/ 和 localhost:8086/test看看

package com.test.myjava;

import java.io.IOException;  
import java.io.OutputStream; 
import java.net.InetSocketAddress; 
import java.util.Queue;
import java.util.concurrent.*;

import com.sun.net.httpserver.HttpExchange; 
import com.sun.net.httpserver.HttpHandler; 
import com.sun.net.httpserver.HttpServer; 
public class HttpServerTest { 
	public static void main(String[] args) {
		try {
			//允许最大连接数
			int backLog = 10;
			InetSocketAddress inetSock = new InetSocketAddress(8086);
			HttpServer httpServer = HttpServer.create(inetSock, backLog);
			//直接返回Hello.....
			httpServer.createContext("/", new HandlerTestA());
			//显示已经处理的请求数,采用线程池
			httpServer.createContext("/test",new HandlerTestB());
			httpServer.setExecutor(null);
			httpServer.start();
			System.out.println("HttpServer Test Start!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

//直接处理请求
class HandlerTestA implements HttpHandler{

	public void handle(HttpExchange httpExchange) throws IOException {
		// TODO Auto-generated method stub
		//针对请求的处理部分   
		//返回请求响应时,遵循HTTP协议
		String responseString = "<font color='#ff0000'>Hello! This a HttpServer!</font>";
		//设置响应头
		httpExchange.sendResponseHeaders(200, responseString.length());   
		OutputStream os = httpExchange.getResponseBody();   
		os.write(responseString.getBytes());   
		os.close(); 
	}
	
}
//线程池还不会用,简略的使用了下,意思有点差距,后面在分析
class HandlerTestB implements HttpHandler{
	private static int requestNum = 0; 
	ThreadPoolExecutor threadPoolExecutor;
	HandlerTestB(){
		//两个常在线程,最大3个
		 threadPoolExecutor = new  ThreadPoolExecutor(2,3, 30, 
				 TimeUnit.SECONDS, 
				 new ArrayBlockingQueue<Runnable>(2),  
		         new ThreadPoolExecutor.CallerRunsPolicy()
				 );
	}
	public void handle(HttpExchange he) throws IOException {
		// TODO Auto-generated method stub
		if((getQueueSize(threadPoolExecutor.getQueue()))<2){
			RequestTasks rqt = new RequestTasks(he); 
			threadPoolExecutor.execute(rqt);
		}
		else System.out.println("Please Wait!");
	}
	private synchronized int getQueueSize(Queue queue)  
    {  
        return queue.size();  
    } 
	
}

//处理请求的任务
class RequestTasks implements Runnable{

	static int processedNum = 0;
	HttpExchange httpExchange;
	RequestTasks(HttpExchange he){
		httpExchange = he;
		processedNum++;
	}
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("ProcessedNum:" +processedNum);
		String responseString = "ProcessedNum:" + processedNum + "\n";
		try{
		httpExchange.sendResponseHeaders(200, responseString.length());   
		OutputStream os = httpExchange.getResponseBody();   
		os.write(responseString.getBytes());   
		os.close();
		//去掉注释,看看只能响应两个,有些问题
		//while(true);
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	
}

看这些的时候有个小插曲,当时看不懂既然有了createContext ( )方法中的实现HttpHandler接口的类来处理请求,为什么又要有个setExecutor来设置管理线程的Executor,而且还要在start()方法之前;这时自己查看文档的时候看到createContext(),start()方法都是抽象方法(当然HttpServer也是抽象类),是怎么调用的呢?在网上找到其源码时,才发现,HttpServer的创建首先是通过create(InetSocketAddress addr, int backlog)这个静态方法创建,这里面是通过 HttpServerProvider(它也是抽象类,其子类 sun.net.httpserver.DefaultHttpServerProvider中的createHttpServer)来创建的,其后在具体创建过程中则是new了一个 HttpServerImpl类的实例(这个只是一个包装,具体实现是ServerImpl类来完成最后的HttpServer对象的生成);查看ServerImpl的实现,才知道setExecutor设置的是处理TCP链接请求的线程,而createContext 里设置的是针对具体的请求进行处理的回调方法,而且可以通过设置调用多次createContext(),设置不同路径采用不同或相同的处理方法。为什么绕了这么多,采用了什么设计模式,我是还没到那个高度,期待有人能给留言解说下;或者自己以后慢慢的体会吧!

后面再把这些东西合起来,想个大概的应用场景。

参考

实现Http Server的三种方法http://lpn520.iteye.com/blog/781273

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics