手写 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/
谢谢您的赞助,我会做的更好!
相关推荐
手写 tomcat nio http://knight-black-bob.iteye.com/blog/2408450
自己手写nio和netty,不建议下载
3-5Tomcat响应请求源码与nio处理请求源码实现.mp4
tomcat默认的 HTTP connector 是阻塞的,并且每个连接对应一个线程。这会造成线程资源的浪费,因为连接本身可能不一定频繁被使用,而是仅仅被用来k
此版本在Tomcat7.0.69 的基础上...2、 启用nio 和 线程池配置 (server.xml) 3、修改了context.xml ,添加redis 支持(注意redis 连接密码) 4、在Root目录添加了test.jsp 用于查看多tomcat集群时sessionId是否一直
tomcat8.5.56_windows_X64_个人优化版+垃圾回收机制+乱码问题处理,可以直接部署,也可供参考学习
目标环境Tomcat + JDK 使用 NIO/BIO 连接器进行 SSL。 在 Tomcat 7 + Java 7 / Tomcat 8 + Java 8 上测试,但写成 Tomcat 4.1 + JDK1.4.2 兼容。注意密码列表按推荐顺序排序。 接下来 Tomcat 将支持 Tomcat 8.0.21 /...
从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式.doc
tomcat:Java使用nio模式实现tomcat
基于tomcat的NIO处理模型实现的web服务器
Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...
Tomcat 8.0版本 优化过
NIO入门.chm NIO入门.chm NIO入门.chm
java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...
Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...
java nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socket
Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...
Java NIO英文高清原版
tomcat自带还有NIO的模型,另外也可以调用APR的库来实现操作系统级别控制。 NIO模型是内置的,调用很方便,只需要将上面配置文件中protocol修改成org.apache.coyote.http11.Http11NioProtocol,重启即可生效。上面...
Java NIO系列教程(一) Java NIO 概述