- 浏览: 64169 次
- 性别:
- 来自: 成都
文章分类
一直以来觉得容器都是一个很神秘的东西,一般开发的时候不会关心容器到底是怎么实现的。现在看了《How Tomcat Works》这本书后大概知道容器的实现,写出来自己巩固下
java 基础里面有章是关于Socket的,这个对象是通过http协议来发送消息的。tomcat既然是通过JAVA来实现他的底层也是通过Socket来实现。
首先实现一个Servlet容器。它的功能是可以加载serlvet对象以及访问静态文件。
1、Server端
代码很简单前面就是启动一个server并且接受socket 后面解释下request.getUri()这个方法后面会说,就是截取"GET /XXXX HTTP/1.1"HTTP协议的字符串,如果我们的请求是http://127.0.0.1:8080/SHUTDOWN 截取后的结果就是SHUTDOWN。
2、Request对象
自己定义的request对象 这个对象由于是基因servlet实现所以必须实现ServletRequest的方法。具体的servlet方法现在都没实现,暂时只实现一个截取uri的方法。这个方法的作用前面已经说明。
3、Response方法
也是实现servlet的接口,同时实现一个sendStaticResource()这个方法就是访问静态文件,如果不能访问就返回404错误。
4、MockServletPorcessor
这个方法就是对servlet的处理类,如果请求的后缀有/servlet那么代码就会进入这个类
这个类的基本功能有3个
(1)加载servlet类库
classpath的路径是servlet的路径(bin/com/xxx/server)
(2)加载servlet类
(3)实现service方法
5、StaticResource静态访问类
只是简单的调用response类。
6、TestServlet
一个简单的serlvet 这里保留了包的名称因为以后会说到
启动server容器 然后我们可以通过页面上
http://127.0.0.1:8080/servlet/com.xxx.server.TestServlet 这里必须使用全限定名才行
来运行servlet
通过http://127.0.0.1:8080/index.html来访问资源(当然前提是WEB_ROOT下面有这个资源)
通过http://127.0.0.1:8080/SHUTDOWN来关闭容器
java 基础里面有章是关于Socket的,这个对象是通过http协议来发送消息的。tomcat既然是通过JAVA来实现他的底层也是通过Socket来实现。
首先实现一个Servlet容器。它的功能是可以加载serlvet对象以及访问静态文件。
1、Server端
import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; public class MockServer { public static final String = System.getProperty("user.dir") + File.separator + "webroot"; private static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; private boolean shutdown = false; public static void main(final String[] args) throws Exception { MockServer server = new MockServer(); server.await(); } public void await() { ServerSocket socketServer = null; int port = 8080; try { socketServer = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1")); } catch (IOException e) { e.printStackTrace(); } while (!shutdown) { Socket socket = null; InputStream in = null; OutputStream out = null; try { socket = socketServer.accept(); in = socket.getInputStream(); out = socket.getOutputStream(); Request request = new Request(in); request.parse(); Response response = new Response(out); response.setRequest(request); socket.close(); if (request.getUri().startsWith("/servlet")) { MockServletPorcessor servlet = new MockServletPorcessor(); servlet.process(request, response); } else if (request.getUri().equals(SHUTDOWN_COMMAND)) { shutdown = true; } else { StaticResource sr = new StaticResource(); sr.process(request, response); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
代码很简单前面就是启动一个server并且接受socket 后面解释下request.getUri()这个方法后面会说,就是截取"GET /XXXX HTTP/1.1"HTTP协议的字符串,如果我们的请求是http://127.0.0.1:8080/SHUTDOWN 截取后的结果就是SHUTDOWN。
2、Request对象
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.Enumeration; import java.util.Locale; import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; public class Request implements ServletRequest { private final InputStream in; private String uri; public Request(final InputStream in) { this.in = in; } public void parse() { StringBuffer sb = new StringBuffer(2048); int i = 0; byte[] buffer = new byte[2048]; try { i = in.read(buffer); } catch (IOException e) { e.printStackTrace(); } for (int j = 0; j < i; j++) { sb.append((char) buffer[j]); } System.out.println(String.valueOf(sb)); uri = parseUri(String.valueOf(sb)); } // "GET /SHUTDOWN HTTP/1.1" private String parseUri(final String request) { int index1, index2; index1 = request.indexOf(' '); if (index1 != -1) { index2 = request.indexOf(' ', index1 + 1); if (index2 > index1) { return request.substring(index1 + 1, index2); } } return null; } public String getUri() { return uri; } @Override public Object getAttribute(final String arg0) { // TODO Auto-generated method stub return null; } @Override public Enumeration getAttributeNames() { // TODO Auto-generated method stub return null; } @Override public String getCharacterEncoding() { // TODO Auto-generated method stub return null; } @Override public int getContentLength() { // TODO Auto-generated method stub return 0; } @Override public String getContentType() { // TODO Auto-generated method stub return null; } @Override public ServletInputStream getInputStream() throws IOException { // TODO Auto-generated method stub return null; } @Override public String getLocalAddr() { // TODO Auto-generated method stub return null; } @Override public String getLocalName() { // TODO Auto-generated method stub return null; } @Override public int getLocalPort() { // TODO Auto-generated method stub return 0; } @Override public Locale getLocale() { // TODO Auto-generated method stub return null; } @Override public Enumeration getLocales() { // TODO Auto-generated method stub return null; } @Override public String getParameter(final String arg0) { // TODO Auto-generated method stub return null; } @Override public Map getParameterMap() { // TODO Auto-generated method stub return null; } @Override public Enumeration getParameterNames() { // TODO Auto-generated method stub return null; } @Override public String[] getParameterValues(final String arg0) { // TODO Auto-generated method stub return null; } @Override public String getProtocol() { // TODO Auto-generated method stub return null; } @Override public BufferedReader getReader() throws IOException { // TODO Auto-generated method stub return null; } @Override public String getRealPath(final String arg0) { // TODO Auto-generated method stub return null; } @Override public String getRemoteAddr() { // TODO Auto-generated method stub return null; } @Override public String getRemoteHost() { // TODO Auto-generated method stub return null; } @Override public int getRemotePort() { // TODO Auto-generated method stub return 0; } @Override public RequestDispatcher getRequestDispatcher(final String arg0) { // TODO Auto-generated method stub return null; } @Override public String getScheme() { // TODO Auto-generated method stub return null; } @Override public String getServerName() { // TODO Auto-generated method stub return null; } @Override public int getServerPort() { // TODO Auto-generated method stub return 0; } @Override public boolean isSecure() { // TODO Auto-generated method stub return false; } @Override public void removeAttribute(final String arg0) { // TODO Auto-generated method stub } @Override public void setAttribute(final String arg0, final Object arg1) { // TODO Auto-generated method stub } @Override public void setCharacterEncoding(final String arg0) throws UnsupportedEncodingException { // TODO Auto-generated method stub } }
自己定义的request对象 这个对象由于是基因servlet实现所以必须实现ServletRequest的方法。具体的servlet方法现在都没实现,暂时只实现一个截取uri的方法。这个方法的作用前面已经说明。
3、Response方法
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Locale; import javax.servlet.ServletOutputStream; import javax.servlet.ServletResponse; public class Response implements ServletResponse { private static final int BUFFER_SIZE = 1024; private Request request; private final OutputStream out; private PrintWriter writer; public Response(final OutputStream out) { this.out = out; } public void setRequest(final Request request) { this.request = request; } public void sendStaticResource() { byte[] bytes = new byte[BUFFER_SIZE]; FileInputStream fis = null; try { File file = new File(MockServer.WEB_ROOT, request.getUri()); if (file.exists()) { fis = new FileInputStream(file); int ch = fis.read(bytes, 0, BUFFER_SIZE); while (ch != -1) { out.write(bytes, 0, ch); ch = fis.read(bytes, 0, BUFFER_SIZE); } } else { String message = "Http/1.1 404 File Not Found\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 23\r\n" + "\r\n" + "<h1>File Not Found</h1>"; out.write(message.getBytes()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (null != fis) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public void flushBuffer() throws IOException { // TODO Auto-generated method stub } @Override public int getBufferSize() { // TODO Auto-generated method stub return 0; } @Override public String getCharacterEncoding() { // TODO Auto-generated method stub return null; } @Override public String getContentType() { // TODO Auto-generated method stub return null; } @Override public Locale getLocale() { // TODO Auto-generated method stub return null; } @Override public ServletOutputStream getOutputStream() throws IOException { // TODO Auto-generated method stub return null; } @Override public PrintWriter getWriter() throws IOException { writer = new PrintWriter(out, true); return writer; } @Override public boolean isCommitted() { // TODO Auto-generated method stub return false; } @Override public void reset() { // TODO Auto-generated method stub } @Override public void resetBuffer() { // TODO Auto-generated method stub } @Override public void setBufferSize(final int arg0) { // TODO Auto-generated method stub } @Override public void setCharacterEncoding(final String arg0) { // TODO Auto-generated method stub } @Override public void setContentLength(final int arg0) { // TODO Auto-generated method stub } @Override public void setContentType(final String arg0) { // TODO Auto-generated method stub } @Override public void setLocale(final Locale arg0) { // TODO Auto-generated method stub } }
也是实现servlet的接口,同时实现一个sendStaticResource()这个方法就是访问静态文件,如果不能访问就返回404错误。
4、MockServletPorcessor
这个方法就是对servlet的处理类,如果请求的后缀有/servlet那么代码就会进入这个类
import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.net.URLStreamHandler; import javax.servlet.Servlet; public class MockServletPorcessor { public void process(final Request request, final Response response) { String uri = request.getUri(); String servletName = uri.substring(uri.lastIndexOf("/") + 1); URLClassLoader loader = null; try { URL[] urls = new URL[1]; URLStreamHandler handler = null; File = new File("bin/com/xxx/server"); String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString(); System.out.print(repository); urls[0] = new URL(null, repository, handler); loader = new URLClassLoader(urls); Class myClass = loader.loadClass(servletName); Servlet servlet = (Servlet) myClass.newInstance(); servlet.service(request, response); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // TODO Auto-generated method stub } }
这个类的基本功能有3个
(1)加载servlet类库
classpath的路径是servlet的路径(bin/com/xxx/server)
(2)加载servlet类
(3)实现service方法
5、StaticResource静态访问类
public class StaticResource { public void process(final Request request, final Response response) { response.sendStaticResource(); } }
只是简单的调用response类。
6、TestServlet
package com.xxx.server; import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class TestServlet implements Servlet { @Override public void destroy() { // TODO Auto-generated method stub } @Override public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } @Override public String getServletInfo() { // TODO Auto-generated method stub return null; } @Override public void init(final ServletConfig arg0) throws ServletException { // TODO Auto-generated method stub } @Override public void service(final ServletRequest request, final ServletResponse response) throws ServletException, IOException { System.out.println("In Service"); } }
一个简单的serlvet 这里保留了包的名称因为以后会说到
启动server容器 然后我们可以通过页面上
http://127.0.0.1:8080/servlet/com.xxx.server.TestServlet 这里必须使用全限定名才行
来运行servlet
通过http://127.0.0.1:8080/index.html来访问资源(当然前提是WEB_ROOT下面有这个资源)
通过http://127.0.0.1:8080/SHUTDOWN来关闭容器
相关推荐
How Tomcat Works中文版
NULL 博文链接:https://asialee.iteye.com/blog/521414
How Tomcat Works【英文PDF+中文HTML+源码】 How Tomcat Works 主要是讲解Tomcat如何运行的一些核心资料。
How Tomcat Works 中文版+例程源码; 源码在src目录下
How Tomcat works(PDF),不可用于商业用途,如有版权问题,请联系删除!
How Tomcat Works》这本书的读书笔记,及主要内容感想。 作为一个世界范围广泛使用的强大框架,Tomcat必然有非常多的设计思想、设计模式,让我们学习。
tomcat的基本思想,学习完可以对理解spring的基本原理有大致了解,很值得学习
HowTomcatWorks 中文版+源码.rar HowTomcatWorks 中文版+源码.rar
how tomcat works中文版 + 英文版,深入解析了tomcat的实现机制
How Tomcat Works 全书共20章!
how tomcat works 高清版 学习tomcat必备书籍 how tomcat works
HowTomcatWorks(书和源码)
How Tomcat Works Tomcat原理的书
How Tomcat Works 深入剖析Tomcat (英文版)
tomcat工作原理深入详解——HowTomcatWorks中文版.pdf
how tomcat works( 深入剖析tomcat) 的随书源码 之前找了很久,后来从官网下载下来的
How Tomcat Works 中文版+例程源码,源码在src包下面, 祝大家学习愉快
Welcome to How Tomcat Works. This book dissects Tomcat 4.1.12 and 5.0.18 and explains the internal workings of its free, open source, and most popular servlet container code-named Catalina. Tomcat is ...