`
knight_black_bob
  • 浏览: 853026 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

手写 tomcat (nio)

阅读更多

手写 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/



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

  • 大小: 29.5 KB
  • 大小: 11.9 KB
  • 大小: 10.8 KB
  • 大小: 5.9 KB
1
0
分享到:
评论

相关推荐

    手写 tomcat nio

    在深入探讨手写Tomcat NIO之前,我们首先需要理解NIO(Non-blocking I/O)的概念。NIO是Java提供的一个用于替代传统I/O模型(即BIO,Blocking I/O)的库。在BIO中,每个连接都需要一个单独的线程进行处理,当并发...

    手写 tomcat IDEA工程

    在手写Tomcat时,你需要实现一个Servlet容器,管理Servlet的生命周期,包括加载、初始化、服务和销毁等阶段。 4. **静态资源与动态资源**:静态资源通常是HTML、CSS、JavaScript等文件,它们可以直接发送给客户端;...

    手写嵌入式Tomcat

    总之,手写嵌入式Tomcat是一项挑战性的任务,它要求开发者具备扎实的Java基础,对Tomcat的内部工作原理有深入了解,以及一定的系统编程能力。但通过这个过程,开发者不仅可以提升自己的技术能力,还能更好地理解和...

    简单的tomcat实现1

    本篇文章将深入解析“简单的tomcat实现1”,帮助读者理解Tomcat的核心概念、工作原理以及如何手写Tomcat的基本组件。 首先,我们要了解Tomcat的两大核心组成部分:连接器(Connector)和容器(Container)。连接器...

    2020面试说明Tomcat源码手写.rar

    【标题】"2020面试说明Tomcat源码手写.rar" 提供...通过深入学习和手写Tomcat源码,开发者可以更好地理解Web服务器的内部运作,这将有助于在面试中展示出扎实的技术功底和解决问题的能力,从而增加获得理想工作的机会。

    chenfast-simple-tomcat-master.zip

    《手写Tomcat:从传统到NIO模式的探索》 Tomcat,作为Apache软件基金会的一个开源项目,是Java Servlet和JavaServer Pages(JSP)技术的流行应用服务器,广泛应用于各类Web应用的开发和部署。本文将深入探讨如何从...

    JAVA高并发高性能高可用高扩展架构视频教程

    JavaWeb之基础(手写实现Tomcat服务器) java多线程编程 纯手写实现SpringIOC实现过程 JEE企业级开发(企业级项目开发权威指南) 网络爬虫之JAVA正则表达式 手写springMVC框架 老司机带你透析springMVC内部实现方式 打造...

    httpServer.rar

    - 多线程或异步处理:为了处理并发请求,服务器通常会采用多线程模型或者异步I/O模型,如Java的NIO(非阻塞I/O)。 - 请求队列:当服务器接收到请求时,可能会将其放入队列,按顺序处理。 - 性能优化:缓存、负载...

    my三期教程.txt

    性能优化之Tomcat性能优化 设计模式与实战操作 框架核心原理分析 SpringIOC、AOP、事物原理分析 手写Spring事物 Spring核心源码分析 手写ORM框架 Arraylist 、Set 、HasMap、、并发HasMap、linkeList 分布式通讯...

    java实现校园一卡通源码-netty4-samples:netty4-样本

    《Netty4核心原理与手写RPC框架实战》 已全面开启预售!!! 京东购买链接: 当当购买链接: 在互联网分布式系统的推动下,Netty是作为一个能够支撑高性能高并发的底层网络通信框架而存在。Netty底层是基于Java NIO...

Global site tag (gtag.js) - Google Analytics