zoukankan      html  css  js  c++  java
  • 《How Tomcat Works》读书笔记(二)

    《How Tomcat Works》读书笔记(二)

    这是《How Tomcat Works》第一二章的读书笔记。第一张主要写了一个静态资源处理的web服务器,第二章加了对servlet的处理。

    1. 概述


    1.1 架构
    图来自原书

    • HttpServer:表示Http服务器,与客户端通信,处理Http请求。
    • StaticResourceProcessor:对静态资源请求进行处理。
    • ServletProcessor:对Servlet资源请求进行处理。
    • Request:表示Http请求,实现了ServletRequest接口。
    • Response:表示Http响应,实现了ServletResponse接口。
    • RequestFacade/ResponseFacade:Request/Response的门面类。
    • PrimitiveServlet:表示一个Servlet类。

    处理流程:

    1.2 一些代码
    HttpServer处理逻辑:

     1 // check if this is a request for a servlet or
     2 // a static resource
     3 // a request for a servlet begins with "/servlet/"
     4 if (request.getUri().startsWith("/servlet/")) {
     5     ServletProcessor1 processor = new ServletProcessor1();
     6     processor.process(request, response);
     7 }
     8 else {
     9     StaticResoureProcessor processor = new StaticResourceProcessor();
    10     processor.process(request, response);
    11 }

    ServletProcessor中通过类加载器把.class文件动态的加载为Servlet对象:

     1 public void process(Request request, Response response) {
     2     String uri = request.getUri();
     3     String servletName = uri.substring(uri.lastIndexOf("/") + 1);
     4     URLClassLoader loader = null;
     5     try {
     6         // create a URLClassLoader
     7         URL[] urls = new URL[1];
     8         URLStreamHandler streamHandler = null;
     9         File classPath = new File(Constants.WEB_ROOT);
    10         // the forming of repository is taken from the
    11         // createClassLoader method in
    12         // org.apache.catalina.startup.ClassLoaderFactory
    13         String repository =(new URL("file", null, 
    14               classPath.getCanonicalPath() + File.separator)).toString() ;
    15         // the code for forming the URL is taken from
    16         // the addRepository method in
    17         // org.apache.catalina.loader.StandardClassLoader.
    18         urls[0] = new URL(null, repository, streamHandler);
    19         loader = new URLClassLoader(urls);
    20     } catch (IOException e) {
    21     }
    22     Class myClass = null;
    23     try {
    24         myClass = loader.loadClass(servletName);
    25     } catch (ClassNotFoundException e) {
    26     }
    27     Servlet servlet = null;
    28     try {
    29         servlet = (Servlet) myClass.newInstance();
    30         // 使用门面设计模式
    31         RequestFacade rquestFacade = new RequestFacade(request);
    32         ResponseFacade responseFacade = new RespondeFacade(response);
    33         // 交由Servlet进行处理
    34         servlet.service(requestFacade, responseFacade);
    35     }
    36 }

    1.3 设计模式
    在这里使用了门面的设计模式,目的是安全性。在StaticResourceProcessor.processor()方法中会把Request、Response对象传给Servelt进行处理,在后面程序猿处理Servlet请求时就可以把ServletRequest向下转型为Request对象,然后使用不该在此使用的方法,如:parse()方法。所以,在这里使用了门面设计模式。

    ResponseFacade类:

     1 public class ResponseFacade implements ServletResponse {
     2     private ServletResponse servletResponse = null;
     3 
     4     // 通过构造方法传入真正的Response,然后向上转型为ServletResponse
     5     public ResponseFacade(Response response) {
     6         this.servletResponse = response;
     7     }
     8     /**
     9      * 后面都是实现ServlerResponse接口要实现的方法,就不写完了。
    10      */ 
    11     @Override
    12     public String getCharacterEncoding() {
    13         return servletResponse.getCharacterEncoding();
    14     }
    15     @Override
    16     public String getContentType() {
    17         return servletResponse.getContentType();
    18     }

    2. 注意


    2.1 HTTP协议
    HTTP协议是应用层协议,它基于TCP/IP协议进行传输数据。在客户端与web服务器解析数据时,必须有相关的头部数据。所以web服务器给客户端发出响应,该响应必须加入头部数据。自己在写该代码时,就忘了加头部数据,出个bug,解决了一段时间才发现。
    PrimitiveServlet的service()方法:

     1 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
     2     String header = "HTTP/1.1 200 OK
    "
     3             + "Content-Type: text/html;charset=UTF-8
    "
     4             + "
    ";
     5     String content = "<html>
    "
     6             + "<head>" 
     7             + "</head>"
     8             + "<body>" 
     9             + "Primitive Servlet" 
    10             + "</body>" 
    11             + "</html>";
    12     PrintWriter writer = res.getWriter();
    13     writer.write(header);
    14     writer.write(content);
    15     writer.flush();
    16     writer.close();
    17 }

    我们平时使用Servlet开发时,直接继承HttpServlet,容器会自动的加上HTTP Response相关信息。

    2.2 MIME类型
    HTTP Respose header中有一个ContentType字段,它要求告诉客户端该Response正文的内容MIME类型,我们可以通过下面的API获得某一个文件的MIME类型。

    String mimeType = URLConnection.getFileNameMap().getContentTypeFor(fileName)
    

    2.2 .class文件
    该系统使用到了URLClassLoader加载Class对象,ClassLoader把字节码(.class文件)加载为Class对象,所以需要编译好的.class文件。在Idea中Project中有个out目录,其中放的就是编译好的.class文件(只要你使用Idea运行过的.java文件)。

    3. 代码


    与原书逻辑基本一致,由于自己加入了多线程技术,所以新增了Servlet容器(使用了Map),并且该容器一开始就加载所有的Servlet。

    HttpServer:

     1 package note1;
     2 
     3 import java.io.IOException;
     4 import java.net.ServerSocket;
     5 import java.net.Socket;
     6 import java.util.concurrent.ExecutorService;
     7 import java.util.concurrent.Executors;
     8 
     9 /**
    10  * Created by kanyuxia on 2017/4/24.
    11  * HttpServer是模拟HTTP服务器:接受HTTP请求,响应静态资源或者Servlet资源
    12  */
    13 public class HttpServer {
    14     /**
    15      * HttpServer端口号
    16      */
    17     public static final int PORT = 10086;
    18     /**
    19      * Http静态文件根目录
    20      */
    21     public static final String STATIC_RESOURCE_ROOT = "E:/java/HttpServer/staticresource";
    22     /**
    23      * Http中Servlet文件根目录
    24      */
    25     public static final String SERVLET_ROOT = "E:/java/HttpServer/servlet";
    26     /**
    27      * 线程池
    28      */
    29     private ExecutorService executorService;
    30     /**
    31      * 线程池大小
    32      */
    33     public static final int THREAD_POOL_SIZE = 50;
    34 
    35     HttpServer() {
    36         executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
    37     }
    38 
    39     /**
    40      * 启动HttpServer服务器
    41      * 使用了try-with-resource: since jdk1.7
    42      */
    43     public void start() {
    44         // 创建ServerSocket
    45         try (ServerSocket serverSocket = new ServerSocket(PORT)) {
    46             while (true) {
    47                 // 客户端连接
    48                 Socket socket = serverSocket.accept();
    49                 // 使用线程池处理该socket
    50                 ServerHandle serverHandle = new ServerHandle(socket);
    51                 executorService.execute(serverHandle);
    52             }
    53         } catch (IOException e) {
    54             System.out.println(e);
    55         }
    56     }
    57 }
    View Code

    Request:

      1 package note1;
      2 
      3 import javax.servlet.*;
      4 import java.io.*;
      5 import java.util.Enumeration;
      6 import java.util.Locale;
      7 import java.util.Map;
      8 
      9 /**
     10  * Created by kanyuxia on 2017/4/24
     11  * Request类:实现了ServletRequest接口,如果HTTP请求是Servlet,则服务器创建ServletRequest和ServletResponse对象,
     12  * 并传入Servlet的service()方法
     13  */
     14 public class Request implements ServletRequest {
     15     private final InputStream inputStream;
     16 
     17     private String url;
     18 
     19     public Request(InputStream inputStream) {
     20         this.inputStream = inputStream;
     21     }
     22 
     23     public String getUrl() {
     24         return url;
     25     }
     26 
     27     /**
     28      * 解析请求URL
     29      */
     30     public void parse() {
     31         BufferedInputStream in = new BufferedInputStream(inputStream);
     32         StringBuilder result = new StringBuilder(1024);
     33         byte[] buffer = new byte[1024];
     34         int readNum = 0;
     35         try {
     36             readNum = in.read(buffer);
     37         } catch (IOException e) {
     38             e.printStackTrace();
     39         }
     40         for (int i = 0; i < readNum; i++) {
     41             result.append((char) buffer[i]);
     42         }
     43         // 解析URL
     44         int start = result.toString().indexOf(" ") + 1;
     45         int end = result.toString().indexOf(" ", start);
     46         this.url = result.toString().substring(start, end);
     47     }
     48 
     49 
     50     @Override
     51     public Object getAttribute(String name) {
     52         return null;
     53     }
     54 
     55     @Override
     56     public Enumeration<String> getAttributeNames() {
     57         return null;
     58     }
     59 
     60     @Override
     61     public String getCharacterEncoding() {
     62         return null;
     63     }
     64 
     65     @Override
     66     public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
     67 
     68     }
     69 
     70     @Override
     71     public int getContentLength() {
     72         return 0;
     73     }
     74 
     75     @Override
     76     public long getContentLengthLong() {
     77         return 0;
     78     }
     79 
     80     @Override
     81     public String getContentType() {
     82         return null;
     83     }
     84 
     85     @Override
     86     public ServletInputStream getInputStream() throws IOException {
     87         return null;
     88     }
     89 
     90     @Override
     91     public String getParameter(String name) {
     92         return null;
     93     }
     94 
     95     @Override
     96     public Enumeration<String> getParameterNames() {
     97         return null;
     98     }
     99 
    100     @Override
    101     public String[] getParameterValues(String name) {
    102         return new String[0];
    103     }
    104 
    105     @Override
    106     public Map<String, String[]> getParameterMap() {
    107         return null;
    108     }
    109 
    110     @Override
    111     public String getProtocol() {
    112         return null;
    113     }
    114 
    115     @Override
    116     public String getScheme() {
    117         return null;
    118     }
    119 
    120     @Override
    121     public String getServerName() {
    122         return null;
    123     }
    124 
    125     @Override
    126     public int getServerPort() {
    127         return 0;
    128     }
    129 
    130     @Override
    131     public BufferedReader getReader() throws IOException {
    132         return null;
    133     }
    134 
    135     @Override
    136     public String getRemoteAddr() {
    137         return null;
    138     }
    139 
    140     @Override
    141     public String getRemoteHost() {
    142         return null;
    143     }
    144 
    145     @Override
    146     public void setAttribute(String name, Object o) {
    147 
    148     }
    149 
    150     @Override
    151     public void removeAttribute(String name) {
    152 
    153     }
    154 
    155     @Override
    156     public Locale getLocale() {
    157         return null;
    158     }
    159 
    160     @Override
    161     public Enumeration<Locale> getLocales() {
    162         return null;
    163     }
    164 
    165     @Override
    166     public boolean isSecure() {
    167         return false;
    168     }
    169 
    170     @Override
    171     public RequestDispatcher getRequestDispatcher(String path) {
    172         return null;
    173     }
    174 
    175     @Override
    176     public String getRealPath(String path) {
    177         return null;
    178     }
    179 
    180     @Override
    181     public int getRemotePort() {
    182         return 0;
    183     }
    184 
    185     @Override
    186     public String getLocalName() {
    187         return null;
    188     }
    189 
    190     @Override
    191     public String getLocalAddr() {
    192         return null;
    193     }
    194 
    195     @Override
    196     public int getLocalPort() {
    197         return 0;
    198     }
    199 
    200     @Override
    201     public ServletContext getServletContext() {
    202         return null;
    203     }
    204 
    205     @Override
    206     public AsyncContext startAsync() throws IllegalStateException {
    207         return null;
    208     }
    209 
    210     @Override
    211     public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException {
    212         return null;
    213     }
    214 
    215     @Override
    216     public boolean isAsyncStarted() {
    217         return false;
    218     }
    219 
    220     @Override
    221     public boolean isAsyncSupported() {
    222         return false;
    223     }
    224 
    225     @Override
    226     public AsyncContext getAsyncContext() {
    227         return null;
    228     }
    229 
    230     @Override
    231     public DispatcherType getDispatcherType() {
    232         return null;
    233     }
    234 }
    View Code

    Response:

      1 package note1;
      2 
      3 import javax.servlet.ServletOutputStream;
      4 import javax.servlet.ServletResponse;
      5 import java.io.*;
      6 import java.net.URLConnection;
      7 import java.util.Locale;
      8 
      9 /**
     10  * Created by kanyuxia on 2017/4/24.
     11  */
     12 public class Response implements ServletResponse {
     13     private final Request request;
     14 
     15     private final OutputStream outputStream;
     16 
     17     public Response(Request request, OutputStream outputStream) {
     18         this.request = request;
     19         this.outputStream = outputStream;
     20     }
     21 
     22     /**
     23      * 发送静态资源方法
     24      * @throws IOException
     25      */
     26     public void sendStaticResource() throws IOException {
     27         BufferedOutputStream out = new BufferedOutputStream(outputStream);
     28         //请求的本地静态文件地址
     29         File file = new File(HttpServer.STATIC_RESOURCE_ROOT + request.getUrl());
     30         // 文件存在
     31         if (file.exists()) {
     32             String mimeType = URLConnection.getFileNameMap().getContentTypeFor(file.getName());
     33             String header = "HTTP/1.1 200 OK
    "
     34                     + "Content-Length: " + file.length() + "
    "
     35                     + "Content-Type: " + mimeType + "; charset=UTF-8
    "
     36                     + "
    ";
     37             // 发送header
     38             out.write(header.getBytes());
     39             out.flush();
     40             // 发送content
     41             byte[] buffer = new byte[1024];
     42             try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
     43                 for (int b = in.read(buffer); b != -1; b = in.read(buffer)) {
     44                     out.write(buffer, 0, b);
     45                     out.flush();
     46                 }
     47             } catch (IOException e) {
     48                 System.out.println();
     49             }
     50             // 关闭流
     51             try {
     52                 out.close();
     53             } catch (IOException e) {
     54                 System.out.println();
     55             }
     56             return;
     57         }
     58         // 文件不存在
     59         sendNotFound();
     60     }
     61 
     62     public void sendNotFound() {
     63         BufferedOutputStream out = new BufferedOutputStream(outputStream);
     64         // 文件不存在
     65         String header = "HTTP/1.1 404 NOT FOUND
    "
     66                 + "
    ";
     67         String content = "<html>
    " +
     68                 "<head>" +
     69                 "</head>" +
     70                 "<body>" +
     71                 "File Not Found" +
     72                 "</body>" +
     73                 "</html>";
     74         // 发送数据
     75         try {
     76             out.write(header.getBytes());
     77             out.write(content.getBytes());
     78             out.flush();
     79         } catch (IOException e) {
     80             System.out.println(e);
     81         } finally {
     82             // 关闭流
     83             try {
     84                 out.close();
     85             } catch (IOException e) {
     86                 System.out.println(e);
     87             }
     88         }
     89     }
     90 
     91     @Override
     92     public String getCharacterEncoding() {
     93         return null;
     94     }
     95 
     96     @Override
     97     public String getContentType() {
     98         return null;
     99     }
    100 
    101     @Override
    102     public ServletOutputStream getOutputStream() throws IOException {
    103         return null;
    104     }
    105 
    106     @Override
    107     public PrintWriter getWriter() throws IOException {
    108         return new PrintWriter(outputStream);
    109     }
    110 
    111     @Override
    112     public void setCharacterEncoding(String charset) {
    113 
    114     }
    115 
    116     @Override
    117     public void setContentLength(int len) {
    118 
    119     }
    120 
    121     @Override
    122     public void setContentLengthLong(long len) {
    123 
    124     }
    125 
    126     @Override
    127     public void setContentType(String type) {
    128 
    129     }
    130 
    131     @Override
    132     public void setBufferSize(int size) {
    133 
    134     }
    135 
    136     @Override
    137     public int getBufferSize() {
    138         return 0;
    139     }
    140 
    141     @Override
    142     public void flushBuffer() throws IOException {
    143 
    144     }
    145 
    146     @Override
    147     public void resetBuffer() {
    148 
    149     }
    150 
    151     @Override
    152     public boolean isCommitted() {
    153         return false;
    154     }
    155 
    156     @Override
    157     public void reset() {
    158 
    159     }
    160 
    161     @Override
    162     public void setLocale(Locale loc) {
    163 
    164     }
    165 
    166     @Override
    167     public Locale getLocale() {
    168         return null;
    169     }
    170 }
    View Code

    RequestFacade与ResponseFacade:

      1 package note1;
      2 
      3 import javax.servlet.*;
      4 import java.io.BufferedReader;
      5 import java.io.IOException;
      6 import java.io.UnsupportedEncodingException;
      7 import java.util.Enumeration;
      8 import java.util.Locale;
      9 import java.util.Map;
     10 
     11 /**
     12  * Created by kanyuxia on 2017/4/24.
     13  */
     14 public class RequestFacade implements ServletRequest {
     15     private final ServletRequest servletRequest;
     16 
     17     RequestFacade(Request request) {
     18         this.servletRequest = request;
     19     }
     20     @Override
     21     public Object getAttribute(String name) {
     22         return servletRequest.getAttribute(name);
     23     }
     24 
     25     @Override
     26     public Enumeration<String> getAttributeNames() {
     27         return servletRequest.getAttributeNames();
     28     }
     29 
     30     @Override
     31     public String getCharacterEncoding() {
     32         return servletRequest.getCharacterEncoding();
     33     }
     34 
     35     @Override
     36     public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
     37         servletRequest.setCharacterEncoding(env);
     38     }
     39 
     40     @Override
     41     public int getContentLength() {
     42         return servletRequest.getContentLength();
     43     }
     44 
     45     @Override
     46     public long getContentLengthLong() {
     47         return servletRequest.getContentLengthLong();
     48     }
     49 
     50     @Override
     51     public String getContentType() {
     52         return servletRequest.getContentType();
     53     }
     54 
     55     @Override
     56     public ServletInputStream getInputStream() throws IOException {
     57         return servletRequest.getInputStream();
     58     }
     59 
     60     @Override
     61     public String getParameter(String name) {
     62         return servletRequest.getParameter(name);
     63     }
     64 
     65     @Override
     66     public Enumeration<String> getParameterNames() {
     67         return servletRequest.getParameterNames();
     68     }
     69 
     70     @Override
     71     public String[] getParameterValues(String name) {
     72         return servletRequest.getParameterValues(name);
     73     }
     74 
     75     @Override
     76     public Map<String, String[]> getParameterMap() {
     77         return servletRequest.getParameterMap();
     78     }
     79 
     80     @Override
     81     public String getProtocol() {
     82         return servletRequest.getProtocol();
     83     }
     84 
     85     @Override
     86     public String getScheme() {
     87         return servletRequest.getScheme();
     88     }
     89 
     90     @Override
     91     public String getServerName() {
     92         return servletRequest.getServerName();
     93     }
     94 
     95     @Override
     96     public int getServerPort() {
     97         return servletRequest.getServerPort();
     98     }
     99 
    100     @Override
    101     public BufferedReader getReader() throws IOException {
    102         return servletRequest.getReader();
    103     }
    104 
    105     @Override
    106     public String getRemoteAddr() {
    107         return servletRequest.getRemoteAddr();
    108     }
    109 
    110     @Override
    111     public String getRemoteHost() {
    112         return servletRequest.getRemoteHost();
    113     }
    114 
    115     @Override
    116     public void setAttribute(String name, Object o) {
    117         servletRequest.setAttribute(name, o);
    118     }
    119 
    120     @Override
    121     public void removeAttribute(String name) {
    122         servletRequest.removeAttribute(name);
    123     }
    124 
    125     @Override
    126     public Locale getLocale() {
    127         return servletRequest.getLocale();
    128     }
    129 
    130     @Override
    131     public Enumeration<Locale> getLocales() {
    132         return servletRequest.getLocales();
    133     }
    134 
    135     @Override
    136     public boolean isSecure() {
    137         return servletRequest.isSecure();
    138     }
    139 
    140     @Override
    141     public RequestDispatcher getRequestDispatcher(String path) {
    142         return servletRequest.getRequestDispatcher(path);
    143     }
    144 
    145     @Override
    146     public String getRealPath(String path) {
    147         return servletRequest.getRealPath(path);
    148     }
    149 
    150     @Override
    151     public int getRemotePort() {
    152         return servletRequest.getRemotePort();
    153     }
    154 
    155     @Override
    156     public String getLocalName() {
    157         return servletRequest.getLocalName();
    158     }
    159 
    160     @Override
    161     public String getLocalAddr() {
    162         return servletRequest.getLocalAddr();
    163     }
    164 
    165     @Override
    166     public int getLocalPort() {
    167         return servletRequest.getLocalPort();
    168     }
    169 
    170     @Override
    171     public ServletContext getServletContext() {
    172         return servletRequest.getServletContext();
    173     }
    174 
    175     @Override
    176     public AsyncContext startAsync() throws IllegalStateException {
    177         return servletRequest.startAsync();
    178     }
    179 
    180     @Override
    181     public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException {
    182         return servletRequest.startAsync(servletRequest, servletResponse);
    183     }
    184 
    185     @Override
    186     public boolean isAsyncStarted() {
    187         return servletRequest.isAsyncStarted();
    188     }
    189 
    190     @Override
    191     public boolean isAsyncSupported() {
    192         return servletRequest.isAsyncSupported();
    193     }
    194 
    195     @Override
    196     public AsyncContext getAsyncContext() {
    197         return servletRequest.getAsyncContext();
    198     }
    199 
    200     @Override
    201     public DispatcherType getDispatcherType() {
    202         return servletRequest.getDispatcherType();
    203     }
    204 }
    205 
    206 package note1;
    207 
    208 import javax.servlet.ServletOutputStream;
    209 import javax.servlet.ServletResponse;
    210 import java.io.IOException;
    211 import java.io.PrintWriter;
    212 import java.util.Locale;
    213 
    214 /**
    215  * Created by kanyuxia on 2017/4/24.
    216  */
    217 public class ResponseFacade implements ServletResponse {
    218     private final ServletResponse servletResponse;
    219 
    220     ResponseFacade(Response response) {
    221         this.servletResponse = response;
    222     }
    223 
    224     @Override
    225     public String getCharacterEncoding() {
    226         return servletResponse.getCharacterEncoding();
    227     }
    228 
    229     @Override
    230     public String getContentType() {
    231         return servletResponse.getContentType();
    232     }
    233 
    234     @Override
    235     public ServletOutputStream getOutputStream() throws IOException {
    236         return servletResponse.getOutputStream();
    237     }
    238 
    239     @Override
    240     public PrintWriter getWriter() throws IOException {
    241         return servletResponse.getWriter();
    242     }
    243 
    244     @Override
    245     public void setCharacterEncoding(String charset) {
    246         servletResponse.setCharacterEncoding(charset);
    247     }
    248 
    249     @Override
    250     public void setContentLength(int len) {
    251         servletResponse.setContentLength(len);
    252     }
    253 
    254     @Override
    255     public void setContentLengthLong(long len) {
    256         servletResponse.setContentLengthLong(len);
    257     }
    258 
    259     @Override
    260     public void setContentType(String type) {
    261         servletResponse.setContentType(type);
    262     }
    263 
    264     @Override
    265     public void setBufferSize(int size) {
    266         servletResponse.setBufferSize(size);
    267     }
    268 
    269     @Override
    270     public int getBufferSize() {
    271         return servletResponse.getBufferSize();
    272     }
    273 
    274     @Override
    275     public void flushBuffer() throws IOException {
    276         servletResponse.flushBuffer();
    277     }
    278 
    279     @Override
    280     public void resetBuffer() {
    281         servletResponse.resetBuffer();
    282     }
    283 
    284     @Override
    285     public boolean isCommitted() {
    286         return servletResponse.isCommitted();
    287     }
    288 
    289     @Override
    290     public void reset() {
    291         servletResponse.reset();
    292     }
    293 
    294     @Override
    295     public void setLocale(Locale loc) {
    296         servletResponse.setLocale(loc);
    297     }
    298 
    299     @Override
    300     public Locale getLocale() {
    301         return servletResponse.getLocale();
    302     }
    303 }
    View Code

    StaticResourceProcessor:

     1 package chapter2;
     2 
     3 import java.io.IOException;
     4 
     5 /**
     6  * Created by kanyuxia on 2017/4/19.
     7  * HttpServer静态资源处理类
     8  */
     9 public class StaticResourceProcessor {
    10     /**
    11      * 静态资源处理方法
    12      * @param request 请求对象
    13      * @param response 响应对象
    14      */
    15     public void process(Request request, Response response) {
    16         try {
    17             response.sendStaticResource();
    18         } catch (IOException e) {
    19             e.printStackTrace();
    20         }
    21     }
    22 }
    View Code

    ServletProcessor:

     1 package note1;
     2 
     3 import javax.servlet.Servlet;
     4 import javax.servlet.ServletException;
     5 import java.io.IOException;
     6 
     7 /**
     8  * Created by kanyuxia on 2017/4/24.
     9  * HttpServer Servelt请求处理类
    10  */
    11 public class ServletProcessor {
    12     /**
    13      * 处理Servlet请求方法
    14      * @param request 请求对象
    15      * @param response 响应对象
    16      */
    17     public void process(Request request, Response response) {
    18         String url = request.getUrl();
    19         String servletName = url.substring(url.lastIndexOf("/") + 1);
    20         // 从容器中拿到该Servlet
    21         Servlet servlet = ServletContainer.container.get(servletName);
    22         if (servlet != null) {
    23             // 使用门面模式
    24             RequestFacade requestFacade = new RequestFacade(request);
    25             ResponseFacade responseFacade = new ResponseFacade(response);
    26             try {
    27                 servlet.service(requestFacade, responseFacade);
    28             } catch (ServletException e) {
    29                 e.printStackTrace();
    30             } catch (IOException e) {
    31                 e.printStackTrace();
    32             }
    33             return;
    34         }
    35         // Servlet不存在
    36         response.sendNotFound();
    37     }
    38 }
    View Code

    PrimitiveServlet:

     1 package note1;
     2 
     3 import javax.servlet.*;
     4 import java.io.IOException;
     5 import java.io.PrintWriter;
     6 
     7 
     8 /**
     9  * Created by kanyuxia on 2017/4/19.
    10  */
    11 public class PrimitiveServlet implements Servlet {
    12     @Override
    13     public void init(ServletConfig config) throws ServletException {
    14         System.out.println("Primitive.init()");
    15     }
    16 
    17     @Override
    18     public ServletConfig getServletConfig() {
    19         return null;
    20     }
    21 
    22     @Override
    23     public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    24         String header = "HTTP/1.1 200 OK
    "
    25                 + "Content-Type: text/html;charset=UTF-8
    "
    26                 + "
    ";
    27         String content = "<html>
    " +
    28                 "<head>" +
    29                 "</head>" +
    30                 "<body>" +
    31                 "Primitive Servlet" +
    32                 "</body>" +
    33                 "</html>";
    34         PrintWriter writer = res.getWriter();
    35         writer.write(header);
    36         writer.write(content);
    37         writer.flush();
    38         writer.close();
    39     }
    40 
    41     @Override
    42     public String getServletInfo() {
    43         return null;
    44     }
    45 
    46     @Override
    47     public void destroy() {
    48         System.out.println("Primitive.destory()");
    49     }
    50 }
    View Code

    ServletContainer:

     1 package note1;
     2 
     3 import javax.servlet.Servlet;
     4 import java.io.File;
     5 import java.io.FileFilter;
     6 import java.io.IOException;
     7 import java.net.URL;
     8 import java.net.URLClassLoader;
     9 import java.net.URLStreamHandler;
    10 import java.util.HashMap;
    11 import java.util.Map;
    12 
    13 /**
    14  * Created by kanyuxia on 2017/4/24.
    15  * Servlet容器:管理Servlet.
    16  */
    17 public class ServletContainer {
    18     /**
    19      * 存放Servlet
    20      */
    21     public static Map<String, Servlet> container = new HashMap<>();
    22 
    23     /**
    24      * 初始化所有的Servlet
    25      */
    26     @SuppressWarnings("unchecked")
    27     public void init() {
    28         // 创建URLClassLoader
    29         URLClassLoader classLoader = null;
    30         try {
    31             // 创建URL
    32             URL[] urls = new URL[1];
    33             File classPath = new File(HttpServer.SERVLET_ROOT);
    34             String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
    35             URLStreamHandler streamHandler = null;
    36             urls[0] = new URL(null, repository, streamHandler);
    37             classLoader = new URLClassLoader(urls);
    38         } catch (IOException e) {
    39             System.out.println();
    40         }
    41         // 获得指定目录下的所有.class文件
    42         File path = new File(HttpServer.SERVLET_ROOT);
    43         File[] files = path.listFiles(new FileFilter() {
    44             @Override
    45             public boolean accept(File pathname) {
    46                 return pathname.toString().endsWith(".class");
    47             }
    48         });
    49         // 加载所有的.class文件
    50         for (File file : files) {
    51             String servletName = file.getName().substring(0, file.getName().indexOf("."));
    52             Class<Servlet> servletClass = null;
    53             try {
    54                 servletClass = (Class<Servlet>) classLoader.loadClass(servletName);
    55             } catch (ClassNotFoundException e) {
    56                 e.printStackTrace();
    57             }
    58             Servlet servlet = null;
    59             try {
    60                  servlet = servletClass.newInstance();
    61             } catch (InstantiationException e) {
    62                 e.printStackTrace();
    63             } catch (IllegalAccessException e) {
    64                 e.printStackTrace();
    65             }
    66             ServletContainer.container.put(servletName, servlet);
    67         }
    68     }
    69 }
    View Code

    Test:

     1 package note1;
     2 
     3 /**
     4  * Created by kanyuxia on 2017/4/24.
     5  */
     6 public class Test {
     7     public static void main(String[] args) {
     8         // 加载Servlet
     9         ServletContainer servletContainer = new ServletContainer();
    10         servletContainer.init();
    11         // 启动HttpServer
    12         HttpServer httpServer = new HttpServer();
    13         httpServer.start();
    14     }
    15 }
    View Code
  • 相关阅读:
    UV有问题?
    利用GPU实现翻页效果(分享自知乎网)
    Directx 9 VS2015环境搭建
    DirectX 读书笔记(14) Cube mapping之SkyBox[转]
    vertex shader must minimally write all four components of POSITION
    unity shader 内置变量
    Real-Time Rendering (2)
    矩阵变换:沿任意轴旋转及其推导
    Python爬虫教程-33-scrapy shell 的使用
    Python爬虫教程-32-Scrapy 爬虫框架项目 Settings.py 介绍
  • 原文地址:https://www.cnblogs.com/maying3010/p/6759597.html
Copyright © 2011-2022 走看看