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

手写 tomcat (nio)

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

手写 tomcat (nio)

 

下载 :demo

 

 

测试:


手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
 

手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
 
 
手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
 

 

 

项目结构:
手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
 

 

 

 

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/


手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
 
 
 谢谢您的赞助,我会做的更好!

  • 手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
  • 大小: 29.5 KB
  • 手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
  • 大小: 11.9 KB
  • 手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
  • 大小: 10.8 KB
  • 手写 tomcat (nio)
            
    
    博客分类: javatomcat 手写tomcatjava 
  • 大小: 5.9 KB