手写 tomcat (nio)

简介: 手写 tomcat (nio)   下载 :demo     测试:          项目结构:        public class NIOSocketServerForTomcat { private String host = "127.

手写 tomcat (nio)

 

下载 :demo

 

 

测试:



 


 
 

 

 

 

项目结构:

 

 

 

 

public class NIOSocketServerForTomcat {
	 
	 private String host = "127.0.0.1";
	 private int port = 8080;
	 
	 //private ExecutorService exec = Executors.newFixedThreadPool(60);
	private ExecutorService exec =   new ThreadPoolExecutor(60, 60, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(2000));
	private ServerSocketChannel  serverSocketChannel; 
	private Selector selector;
	private  NIOSocketServerForTomcat init(){
		this.host = "127.0.0.1";
		this.port = 8080;
		return this;
	}

	private void start()  {
		
		try {
			serverSocketChannel= ServerSocketChannel.open();
			serverSocketChannel.configureBlocking(false);
			serverSocketChannel.bind(new InetSocketAddress(8080));
			
			
			selector = Selector.open();
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
			
			while (true) {
				
				selector.select(1000);
				
				Set<SelectionKey> selectedKeys = selector.selectedKeys();
				
				 
				Iterator<SelectionKey> iterator = selectedKeys.iterator();
				while (iterator.hasNext()) {
					SelectionKey key = iterator.next();
					iterator.remove();
					 if(key.isAcceptable()){
						SocketChannel channel = serverSocketChannel.accept();
						channel.configureBlocking(false); 
						channel.register(selector,SelectionKey.OP_READ   );
						
					} else if(key.isReadable()) {
						SocketChannel channel = (SocketChannel) key.channel();
						channel.configureBlocking(false); 
						exec.submit(new NIOServerHanddler(channel));
						key.cancel();
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	public static void main(String[] args) {
		new NIOSocketServerForTomcat().init().start() ;
		
	}
	
	
}

 

public class NIOServerHanddler implements Runnable {

	private SocketChannel channel;
	
	
	public NIOServerHanddler(SocketChannel channel) {
		this.channel = channel;
	}


	@Override
	public void run() { 
		try {
			ByteBuffer bb = ByteBuffer.allocate(1024);
			channel.read(bb); 
			bb.flip(); 
			byte[] array = bb.array();
			bb.clear();  
			System.out.println(new String(array));
			HttpServletRequest req = new HttpServletRequest(new String (array));
			System.out.println(FastJsonUtils.toJSONString(req));
			HttpServletResponse resp = new HttpServletResponse(channel);
			Map<String, XmlServletEntity> handdlerMapping = HttpServletContext.getInstace().getHanddlerMapping(); 
			
			XmlServletEntity target = null;
			for (XmlServletEntity entity : handdlerMapping.values()) {
				if (!"".equals(req.getUrl()) &&!"/".equals(req.getUrl()) &&  req.getUrl().startsWith(entity.getServletpattern())) {
					target = entity;
				}
			}
			if (null == target) {
				RespEntity respEntity = new RespEntity();
				respEntity.setCode(RespEnums.RESP_ERROR_NOT_FOUND.getCode());
				respEntity.setMsg(RespEnums.RESP_ERROR_NOT_FOUND.getDesc());
				resp.write(FastJsonUtils.toJSONString(respEntity));
			}else{
				try {
					Class<?> clazz = Class.forName(target.getServletClass());
					HttpServlet httpServlet =(HttpServlet) clazz.newInstance();
					httpServlet.service(req, resp);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				} catch (InstantiationException e) { 
					e.printStackTrace();
				} catch (IllegalAccessException e) { 
					e.printStackTrace();
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if (channel != null) {
					channel.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

 

public  class HttpServlet {

   public void service(HttpServletRequest reqest,HttpServletResponse response){
	   String method =  reqest.getMethod();
	   if ("GET".equalsIgnoreCase(method)){
			 this.doGet(reqest, response);
	   } else  if ("POST".equalsIgnoreCase(method)) {
			this.doPost(reqest, response);
	   }  
   }
	 
   public void doGet(HttpServletRequest reqest,HttpServletResponse response){
	   
   }
	
   public void doPost(HttpServletRequest reqest,HttpServletResponse response){
	   
   }
}

 

public class HttpServletRequest {
	
	private String CHAR_ENTER = "\r\n";
	private String CHAR_SPACE = " ";
	private String CHAR_GET = "GET";
	private String CHAR_POST = "POST"; 
	private String CHAR_URL_SPLIT = "?"; 
	private String CHAR_PARAMS_SPLIT = "&"; 
	private String CHAR_PARAMS_KEY_VALUE_SPLIT = "="; 
	private String CHAR_HEADS_KEY_VALUE_SPLIT = ": "; 

	private String method;
	private String url;
	private String host;
	private Map<String,Object> parameters =   new HashMap<String, Object>();
	private Map<String,Object> headers =  new HashMap<String, Object>();

	
//	GET /web/users/user?userName=baoyou&pwd=123456 HTTP/1.1
//	Host: localhost:8080
//	Connection: keep-alive
//	Upgrade-Insecure-Requests: 1
//	User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
//	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
//	Accept-Encoding: gzip, deflate, sdch, br
//	Accept-Language: zh-CN,zh;q=0.8
//	Cookie: __guid=111872281.3385020722635865000.1513231215978.7585
			
//	POST /web/users/user HTTP/1.1
//	Host: localhost:8080
//	Connection: keep-alive
//	Content-Length: 26
//	Cache-Control: max-age=0
//	Origin: null
//	Upgrade-Insecure-Requests: 1
//	User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
//	Content-Type: application/x-www-form-urlencoded
//	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*;q=0.8
//	Accept-Encoding: gzip, deflate, br
//	Accept-Language: zh-CN,zh;q=0.8
//	Cookie: __guid=111872281.3385020722635865000.1513231215978.7585
//	
//	userName=111&password=1111

	
	public HttpServletRequest(String requestString) {
 
		String[] arr = requestString.split(CHAR_ENTER);
		String[] firstArr = arr[0].split(CHAR_SPACE);
		this.method = firstArr[0];
		try {
			this.host = arr[1].split(CHAR_HEADS_KEY_VALUE_SPLIT)[1];
			if (CHAR_GET.equals(this.method)) {
				 String urlAndParams = firstArr[1];
				 if (urlAndParams.contains(CHAR_URL_SPLIT)) {
					this.url = firstArr[1].split(CHAR_URL_SPLIT)[0];
					String params = firstArr[1].split(CHAR_URL_SPLIT)[1];
					String[] paramsArr = params.split(CHAR_PARAMS_SPLIT);
					for (String param : paramsArr) {
						String[] paramsKeyValue = param.split(CHAR_PARAMS_KEY_VALUE_SPLIT);
						this.parameters.put(paramsKeyValue[0], paramsKeyValue.length == 2 ?paramsKeyValue[1] : "");
					}
					for (int i = 1; i< arr.length &&  !"".equals(arr[i]) ;i++) {
						String headerKeyValue  = arr[i];
						String[] headerKeyValues = headerKeyValue.split(CHAR_HEADS_KEY_VALUE_SPLIT);
						this.parameters.put(headerKeyValues[0], headerKeyValues.length == 2 ?headerKeyValues[1] : "");
					}
					
				}else{
					this.url = firstArr[1]; 
				}  
			}else if(CHAR_POST.equals(this.method)){
				String[] postArr = requestString.split(CHAR_ENTER+CHAR_ENTER);
				if (postArr.length == 2 ) {
					String[] paramsArr =postArr[1].split(CHAR_PARAMS_SPLIT);
					for (String param : paramsArr) {
						String[] paramsKeyValue = param.split(CHAR_PARAMS_KEY_VALUE_SPLIT);
						this.parameters.put(paramsKeyValue[0], paramsKeyValue.length == 2 ?paramsKeyValue[1] : "");
					}
				}
				for (int i = 1; i< postArr.length &&  !"".equals(postArr[i]) ;i++) {
					String headerKeyValue  = postArr[i];
					String[] headerKeyValues = headerKeyValue.split(CHAR_HEADS_KEY_VALUE_SPLIT);
					this.parameters.put(headerKeyValues[0], headerKeyValues.length == 2 ?headerKeyValues[1] : "");
				}
				
				
			}
		} catch (Exception e) { 
			e.printStackTrace();
		}
	}
	
	 
	

	public String getMethod() {
		return method;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public Map<String,Object> getParameters() {
		return parameters;
	}

	public void setParameters(Map<String,Object> parameters) {
		this.parameters = parameters;
	}
	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}
	public Map<String, Object> getHeaders() {
		return headers;
	}

	public void setHeaders(Map<String, Object> headers) {
		this.headers = headers;
	}
}

 

 

public class HttpServletResponse {

	private SocketChannel channel;
    private String CHAR = "UTF-8";
    
    private static final String ENTER = "\r\n";
    private static final String SPACE = " ";
    
	
	public HttpServletResponse(SocketChannel channel) {
		this.channel = channel;
		this.CHAR = "UTF-8";
	}

	private String  bulidHeader(String s){
		
		 StringBuilder contextText = new StringBuilder();
        contextText.append(s);
		
		StringBuilder sb = new StringBuilder();
        /*通用头域begin*/
        sb.append("HTTP/1.1").append(SPACE).append("200").append(SPACE).append("OK").append(ENTER);
        sb.append("Server:myServer").append(SPACE).append("0.0.1v").append(ENTER);
        sb.append("Date:Sat,"+SPACE).append(new Date()).append(ENTER);
        sb.append("Content-Type:text/html;charset=UTF-8").append(ENTER);
        sb.append("Content-Length:").append(contextText.toString().getBytes().length).append(ENTER);
        /*通用头域end*/
        sb.append(ENTER);//空一行   
        sb.append(contextText);//正文部分
        System.out.println(sb.toString());
		return sb.toString(); 
	}
	
	
	public void write(String s) {
		
		try {
			ByteBuffer bb2 = ByteBuffer.allocate(1024);
			bb2.put((bulidHeader(s)).getBytes(CHAR));
			bb2.flip();
			channel.write(bb2); 
			bb2.clear();
		    channel.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		} 
	}

}

 

public class HttpServletContext {

	 
	private static Map<String,XmlServletEntity> haddlerMapping ;
	
	private HttpServletContext (){
		haddlerMapping = new SaxXMLUtil().init().getHaddlerMapping();
	}
	private static HttpServletContext instance;
	public  static HttpServletContext getInstace(){
		if (instance == null) {
			synchronized (HttpServletContext.class) {
				if (instance == null) {
					instance = new HttpServletContext();
				}	
			}
		}
		return instance;
	}
	
	public   Map<String,XmlServletEntity> getHanddlerMapping(){
		return haddlerMapping ;
	}

}

 

 

public class SaxXMLUtil extends DefaultHandler{

 
	//private Map<String,XmlServletEntity> map;
	private List<ServletEntity> listServlet;
	private List<ServletMappingEntity> listMapping;
	private String tagName; 
	ServletEntity entityServlet;
	ServletMappingEntity entityServletMapping;
	
	private int flag = 0;
	
	
	public SaxXMLUtil init(){
		SAXParser parser = null;   
        try {
			parser = SAXParserFactory.newInstance().newSAXParser();
			
			InputStream stream=SaxXMLUtil.class.getClassLoader().getResourceAsStream("web.xml");  
            //调用parse()方法  
            parser.parse(stream, this); 
            
		} catch (ParserConfigurationException e) { 
			e.printStackTrace();
		} catch (SAXException e) { 
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
        return this;
	}
	
    public Map<String,XmlServletEntity> getHaddlerMapping()  {
        Map<String,XmlServletEntity> map = new HashMap<String, XmlServletEntity>();
    	for (ServletEntity servlet : listServlet) {
    		XmlServletEntity entity =new  XmlServletEntity();
    		entity.setServletName(servlet.getServletName());
    		entity.setServletClass(servlet.getServletClass());
	    	  String servletName = servlet.getServletName();
			  for (ServletMappingEntity mapping : listMapping) {
				  if (servletName.equals(mapping.getServletName())) {
					  entity.setServletpattern(mapping.getServletpattern());
					  map.put(entity.getServletName(), entity);
					  break;
				  }
				
			  }	
		}
    	
		return map;
    }


	@Override
	public void startDocument() throws SAXException {
		super.startDocument(); 
		listServlet 	= new ArrayList<ServletEntity>();
		listMapping 	= new ArrayList<ServletMappingEntity>();
	}
	
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		//super.startElement(uri, localName, qName, attributes);
		
		if(qName.equals("servlet")){
			
			entityServlet = new ServletEntity();
			this.flag = 1;
		}
		if(qName.equals("servlet-mapping")){
			entityServletMapping = new ServletMappingEntity();
			this.flag = 2;
		}
		this.tagName = qName;
	}
	
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException { 
		//super.endElement(uri, localName, qName);
		if(qName.equals("servlet")){
			listServlet.add( entityServlet);
			
			flag = 0;
		}
		if(qName.equals("servlet-mapping")){
			listMapping.add( entityServletMapping);
			
			flag = 0;
		}
		this.tagName = null;
	}
	
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException { 
		//super.characters(ch, start, length);
		 if(this.tagName!=null){  
			 if(this.flag == 1){
				 String data=new String(ch,start,length);
				 if(this.tagName.equals("servlet-name")){  
					 this.entityServlet.setServletName(data);  
				 }  
				 if(this.tagName.equals("servlet-class")){  
					 this.entityServlet.setServletClass(data);  
				 } 
			 }else if (this.flag == 2) {
				 String data=new String(ch,start,length);
				 if(this.tagName.equals("servlet-name")){  
					 this.entityServletMapping.setServletName(data);  
				 }  
				 if(this.tagName.equals("url-pattern")){  
					 this.entityServletMapping.setServletpattern(data);  
				 } 
				
			}
		 }
		
	}
	
	@Override
	public void endDocument() throws SAXException { 
		super.endDocument();
	} 
	
	public static void main(String[] args) {
		SaxXMLUtil util = new SaxXMLUtil();
		Map<String, XmlServletEntity> map = util.init().getHaddlerMapping();
		for (XmlServletEntity entity : map.values()) {
			System.out.println(entity.getServletName() +"\r\t" + entity.getServletClass() +"\r\t" + entity.getServletpattern());
		}
		/*
		secondServlet
		com.curiousby.baoyou.cn.showandshare.customized.tomcat.demo.SecondServlet
		/secondServlet
		firstServlet
		com.curiousby.baoyou.cn.showandshare.customized.tomcat.demo.FirstServlet
		/firstServlet
		*/
	}

}

 

public class FirstServlet extends HttpServlet{

	@Override
	public void doGet(HttpServletRequest reqest, HttpServletResponse response) {
		super.doGet(reqest, response);
		doPost(reqest, response);
	}

	 
	@Override
	public void doPost(HttpServletRequest reqest, HttpServletResponse response) {
		super.doPost(reqest, response);
		Map<String, Object> parameters = reqest.getParameters();
		response.write("{\"name\":\"baoyou\"}");
	}
	 
}

 

public class SecondServlet extends HttpServlet{

	@Override
	public void doGet(HttpServletRequest reqest, HttpServletResponse response) {
		super.doGet(reqest, response);
		doPost(reqest, response);
	}

	 
	@Override
	public void doPost(HttpServletRequest reqest, HttpServletResponse response) {
		super.doPost(reqest, response);
		response.write("SecondServlet");
		
	}
	 
}

 

 

<web-app>

  <!-- ===========================firstServlet======================  -->
    <servlet>
        <servlet-name>firstServlet</servlet-name>
        <servlet-class>com.curiousby.baoyou.cn.showandshare.customized.tomcat.demo.FirstServlet</servlet-class> 
    </servlet>
    <servlet-mapping>
        <servlet-name>firstServlet</servlet-name>
        <url-pattern>/firstServlet</url-pattern>
   </servlet-mapping> 
   <!-- ===========================firstServlet======================  -->
   
   
   <!-- ===========================secondServlet======================  -->
    <servlet>
        <servlet-name>secondServlet</servlet-name>
        <servlet-class>com.curiousby.baoyou.cn.showandshare.customized.tomcat.demo.SecondServlet</servlet-class> 
    </servlet>
    <servlet-mapping>
        <servlet-name>secondServlet</servlet-name>
        <url-pattern>/secondServlet.do</url-pattern>
   </servlet-mapping> 
  <!-- ===========================secondServlet======================  -->
   
</web-app>

 

 

 

 

 

 

 

 

 

 

 

捐助开发者 

在兴趣的驱动下,写一个免费的东西,有欣喜,也还有汗水,希望你喜欢我的作品,同时也能支持一下。 当然,有钱捧个钱场(支持支付宝和微信 以及扣扣群),没钱捧个人场,谢谢各位。

 

个人主页http://knight-black-bob.iteye.com/



 
 
 谢谢您的赞助,我会做的更好!

目录
相关文章
|
应用服务中间件
99分布式电商项目 - Tomcat性能优化(NIO配置)
99分布式电商项目 - Tomcat性能优化(NIO配置)
47 0
|
缓存 中间件 Java
Web中间件——Tomcat中的BIO、NIO、APR模式
Tomcat在我们日常开发B/S项目时常常进行使用,当然在Spring全家桶中我们现在也是使用的内置tomcat,但是很多人可能不会对于tomcat进行深入性研究,其实在我们的产品进行性能提升时,web中间件的优化也是占有很大一部分,而tomcat中采用不同的模式对应的使用场景下性能也是不一样的,因此本篇文章将对于这几个模式进行简单讲解,后续我们会对于不同的模式进行配置方式讲解。
156 6
Web中间件——Tomcat中的BIO、NIO、APR模式
|
前端开发 Java 应用服务中间件
手写一个迷你版的 Tomcat 猫
前言 Tomcat,这只3脚猫,大学的时候就认识了,直到现在工作中,也常会和它打交道。这是一只神奇的猫,今天让我来抽象你,实现你!
手写一个迷你版的 Tomcat 猫
|
前端开发 Java 应用服务中间件
从0开始手写一个Tomcat,7步搞定!
从0开始手写一个Tomcat,7步搞定!
182 0
从0开始手写一个Tomcat,7步搞定!
|
前端开发 Java 应用服务中间件
从 0 开始手写一个Tomcat,7 步搞定!
Tomcat,这只3脚猫,大学的时候就认识了,直到现在工作中,也常会和它打交道。这是一只神奇的猫,今天让我来抽象你,实现你!
164 0
从 0 开始手写一个Tomcat,7 步搞定!
|
Java 应用服务中间件 容器
|
移动开发 应用服务中间件 容器
手写一个简化版Tomcat
Tomcat作为Web服务器深受市场欢迎,有必要对其进行深入的研究。那么Tomcat是如何工作的?
2455 0
|
Java 应用服务中间件
|
Java 应用服务中间件 关系型数据库
Java 手写Tomcat
1). 创建Java项目Tomcat 2). 创建Servlet接口 public interface IServlet { public void service(); } 3).
857 0
|
Java 应用服务中间件
Tomcat架构解析之3 Connector NIO
上文简单记录了默认的Connector的内部构造及消息流,同时此Connector也是基于BIO的实现。 除BIO,也可以通过配置快速部署NIO的connector。
1258 0