博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实现Servlet容器一
阅读量:7038 次
发布时间:2019-06-28

本文共 13422 字,大约阅读时间需要 44 分钟。

本文是阅读《深度解析Tomcat》的笔记。

源码:http://www.brainysoftware.com/source/9780975212806.zip

├── src
│   └── pyrmont
│       ├── Constants.java
│       ├── HttpServer1.java
│       ├── HttpServer2.java
│       ├── RequestFacade.java
│       ├── Request.java
│       ├── ResponseFacade.java
│       ├── Response.java
│       ├── ServletProcessor1.java
│       ├── ServletProcessor2.java
│       └── StaticResourceProcessor.java
└── webroot
    ├── images
    │   └── logo.gif
    ├── index.html
    ├── PrimitiveServlet.class
    └── PrimitiveServlet.java

1、HttpServer1监听在8080端口,等待客户端socket连接,一旦有客户端连接,就为此客户端新建一个Request、Response,并分别传递InputStream,OutputStream。

其实就是把客户端的输入和服务器的输出封装到Request、Response。

2、HttpServer1利用Request解析url,判断客户端是要请求静态资源还是一个Servlet(目前的HttpServer1只支持这两种简单的请求)。

如果是静态资源则交给StaticResourceProcessor处理,Servlert则交给ServletProcessor1处理。

StaticResourceProcessor:调用Response处理静态文件,即利用IO读写文件。

ServletProcessor1:解析url中Servlet的Name,找到该Servlet的class文件,加载Servlet。调用xxxServlet.service((ServletRequest)request,(ServletResponse)response)

 

优化分析:

xxxServlet.service((ServletRequest)request,(ServletResponse)response),把我们web容器的request,response传给web程序,如果该程序员了解我们容器的实现,他就可以

向下转型为Request、Response。我们并不希望Request、Response的实现细节暴露给调用这,所以不能是public修饰方法,只能是默认修饰。为了更优雅的达到目的,可以用外观模式,新增外观类 RequestFacade,ResponseFacade。

xxxServlet.service((ServletRequest)request,(ServletResponse)response)里的request,response是RequestFacade,ResponseFacade。

启动HttpServer1,在项目下应该有webroot文件夹,里面有index.html ,和xxServlet.class

访问:http://127.0.0.1:8080/index.html

访问:http://127.0.0.1:8080/servlet/xxServlet

源码:

package pyrmont;import java.io.File;public class Constants {    public static final String WEB_ROOT =            System.getProperty("user.dir") + File.separator + "webroot";}

 

package pyrmont;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 HttpServer1 {    /**     * WEB_ROOT is the directory where our HTML and other files reside.     * For this package, WEB_ROOT is the "webroot" directory under the working     * directory.     * The working directory is the location in the file system     * from where the java command was invoked.     */    // shutdown command    private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";    // the shutdown command received    private boolean shutdown = false;    public static void main(String[] args) {        HttpServer1 server = new HttpServer1();        server.await();    }    public void await() {        ServerSocket serverSocket = null;        int port = 8080;        try {            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));        } catch (IOException e) {            e.printStackTrace();            System.exit(1);        }        // Loop waiting for a request        while (!shutdown) {            Socket socket = null;            InputStream input = null;            OutputStream output = null;            try {                socket = serverSocket.accept();                input = socket.getInputStream();                output = socket.getOutputStream();                // create Request object and parse                Request request = new Request(input);                request.parse();                // create Response object                Response response = new Response(output);                response.setRequest(request);                // check if this is a request for a servlet or a static resource                // a request for a servlet begins with "/servlet/"                if (request.getUri().startsWith("/servlet/")) {                    ServletProcessor1 processor = new ServletProcessor1();                    processor.process(request, response);                } else {                    StaticResourceProcessor processor = new StaticResourceProcessor();                    processor.process(request, response);                }                // Close the socket                socket.close();                //check if the previous URI is a shutdown command                shutdown = request.getUri().equals(SHUTDOWN_COMMAND);            } catch (Exception e) {                e.printStackTrace();                System.exit(1);            }        }    }}

 

package pyrmont;import java.io.IOException;public class StaticResourceProcessor {    public void process(Request request, Response response) {        try {            response.sendStaticResource();        } catch (IOException e) {            e.printStackTrace();        }    }}

 

package pyrmont;import javax.servlet.Servlet;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.File;import java.io.IOException;import java.net.URL;import java.net.URLClassLoader;import java.net.URLStreamHandler;public class ServletProcessor1 {  public void process(Request request, Response response) {    String uri = request.getUri();    String servletName = uri.substring(uri.lastIndexOf("/") + 1);    URLClassLoader loader = null;    try {      // create a URLClassLoader      URL[] urls = new URL[1];      URLStreamHandler streamHandler = null;      File classPath = new File(Constants.WEB_ROOT);      // the forming of repository is taken from the createClassLoader method in      // org.apache.catalina.startup.ClassLoaderFactory      String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;      // the code for forming the URL is taken from the addRepository method in      // org.apache.catalina.loader.StandardClassLoader class.      urls[0] = new URL(null, repository, streamHandler);      loader = new URLClassLoader(urls);    }    catch (IOException e) {      System.out.println(e.toString() );    }    Class myClass = null;    try {      myClass = loader.loadClass(servletName);    }    catch (ClassNotFoundException e) {      System.out.println(e.toString());    }    Servlet servlet = null;    try {      servlet = (Servlet) myClass.newInstance();      servlet.service((ServletRequest) request, (ServletResponse) response);    }    catch (Exception e) {      System.out.println(e.toString());    }    catch (Throwable e) {      System.out.println(e.toString());    }  }}

 

 

package pyrmont;import javax.servlet.*;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;public class Request implements ServletRequest {  private InputStream input;  private String uri;  public Request(InputStream input) {    this.input = input;  }  public String getUri() {    return uri;  }  private String parseUri(String requestString) {    int index1, index2;    index1 = requestString.indexOf(' ');    if (index1 != -1) {      index2 = requestString.indexOf(' ', index1 + 1);      if (index2 > index1)        return requestString.substring(index1 + 1, index2);    }    return null;  }  public void parse() {    // Read a set of characters from the socket    StringBuffer request = new StringBuffer(2048);    int i;    byte[] buffer = new byte[2048];    try {      i = input.read(buffer);    }    catch (IOException e) {      e.printStackTrace();      i = -1;    }    for (int j=0; j

 

package pyrmont;import javax.servlet.ServletOutputStream;import javax.servlet.ServletResponse;import java.io.*;import java.util.Locale;public class Response implements ServletResponse {  private static final int BUFFER_SIZE = 1024;  Request request;  OutputStream output;  PrintWriter writer;  public Response(OutputStream output) {    this.output = output;  }  public void setRequest(Request request) {    this.request = request;  }  /* This method is used to serve a static page */  public void sendStaticResource() throws IOException {    byte[] bytes = new byte[BUFFER_SIZE];    FileInputStream fis = null;    try {      /* request.getUri has been replaced by request.getRequestURI */      File file = new File(Constants.WEB_ROOT, request.getUri());      fis = new FileInputStream(file);      /*         HTTP Response = Status-Line           *(( general-header | response-header | entity-header ) CRLF)           CRLF           [ message-body ]         Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF      */      int ch = fis.read(bytes, 0, BUFFER_SIZE);      while (ch!=-1) {        output.write(bytes, 0, ch);        ch = fis.read(bytes, 0, BUFFER_SIZE);      }    }    catch (FileNotFoundException e) {      String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +        "Content-Type: text/html\r\n" +        "Content-Length: 23\r\n" +        "\r\n" +        "

File Not Found

"; output.write(errorMessage.getBytes()); } finally { if (fis!=null) fis.close(); } } public PrintWriter getWriter() throws IOException { // autoflush is true, println() will flush, // but print() will not. writer = new PrintWriter(output, true); return writer; }...}

 

优化:

package pyrmont;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 HttpServer2 {  // shutdown command  private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";  // the shutdown command received  private boolean shutdown = false;  public static void main(String[] args) {    HttpServer2 server = new HttpServer2();    server.await();  }  public void await() {    ServerSocket serverSocket = null;    int port = 8080;    try {      serverSocket =  new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));    }    catch (IOException e) {      e.printStackTrace();      System.exit(1);    }    // Loop waiting for a request    while (!shutdown) {      Socket socket = null;      InputStream input = null;      OutputStream output = null;      try {        socket = serverSocket.accept();        input = socket.getInputStream();        output = socket.getOutputStream();        // create Request object and parse        Request request = new Request(input);        request.parse();        // create Response object        Response response = new Response(output);        response.setRequest(request);        //check if this is a request for a servlet or a static resource        //a request for a servlet begins with "/servlet/"        if (request.getUri().startsWith("/servlet/")) {          ServletProcessor2 processor = new ServletProcessor2();          processor.process(request, response);        }        else {          StaticResourceProcessor processor = new StaticResourceProcessor();          processor.process(request, response);        }        // Close the socket        socket.close();        //check if the previous URI is a shutdown command        shutdown = request.getUri().equals(SHUTDOWN_COMMAND);      }      catch (Exception e) {        e.printStackTrace();        System.exit(1);      }    }  }}

 

package pyrmont;import javax.servlet.Servlet;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.File;import java.io.IOException;import java.net.URL;import java.net.URLClassLoader;import java.net.URLStreamHandler;public class ServletProcessor2 {  public void process(Request request, Response response) {    String uri = request.getUri();    String servletName = uri.substring(uri.lastIndexOf("/") + 1);    URLClassLoader loader = null;    try {      // create a URLClassLoader      URL[] urls = new URL[1];      URLStreamHandler streamHandler = null;      File classPath = new File(Constants.WEB_ROOT);      // the forming of repository is taken from the createClassLoader method in      // org.apache.catalina.startup.ClassLoaderFactory      String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;      // the code for forming the URL is taken from the addRepository method in      // org.apache.catalina.loader.StandardClassLoader class.      urls[0] = new URL(null, repository, streamHandler);      loader = new URLClassLoader(urls);    }    catch (IOException e) {      System.out.println(e.toString() );    }    Class myClass = null;    try {      myClass = loader.loadClass(servletName);    }    catch (ClassNotFoundException e) {      System.out.println(e.toString());    }    Servlet servlet = null;    RequestFacade requestFacade = new RequestFacade(request);    ResponseFacade responseFacade = new ResponseFacade(response);    try {      servlet = (Servlet) myClass.newInstance();      servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade);    }    catch (Exception e) {      System.out.println(e.toString());    }    catch (Throwable e) {      System.out.println(e.toString());    }  }}

 

package pyrmont;import javax.servlet.*;import java.io.BufferedReader;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.util.Enumeration;import java.util.Locale;import java.util.Map;public class RequestFacade implements ServletRequest {  private ServletRequest request = null;  public RequestFacade(Request request) {    this.request = request;  }...}

 

package pyrmont;import javax.servlet.ServletOutputStream;import javax.servlet.ServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.Locale;public class ResponseFacade implements ServletResponse {  private ServletResponse response;  public ResponseFacade(Response response) {    this.response = response;  }...}

 

转载于:https://www.cnblogs.com/lanqie/p/7988049.html

你可能感兴趣的文章
SQL Server 表变量和临时表的区别
查看>>
(十一) 整合spring cloud云架构 - SSO单点登录之OAuth2.0登录流程(2)
查看>>
Laravel框架数据库CURD操作、连贯操作总结
查看>>
给area标签添加红色边框
查看>>
公司列表
查看>>
C# DataTable使用方法详解--删除表数据
查看>>
CentOS7 通过YUM安装MySQL5.7
查看>>
Web of Science数据库中文献相关信息下载与保存
查看>>
移动端 竖屏 (转)
查看>>
Hadoop生态圈-Oozie实战之逻辑调度执行多个Job
查看>>
【CentOS-7+ Ambari 2.7.0 + HDP 3.0+HAWQ2.3.00】遭遇问题及解决记录
查看>>
Java 8 函数式接口
查看>>
ionic3报Please provide a valid ISO 8601 datetime format的错误
查看>>
Difference between HttpContext.Request and Request
查看>>
Oracle查看用户密码过期,修改永不过期
查看>>
php 中使用cURL发送get/post请求,上传图片,批处理
查看>>
基于Python37配置图片文字识别
查看>>
LOJ#2552. 「CTSC2018」假面(期望 背包)
查看>>
STRING使用EQUALS方法和==分别比较的是什么?
查看>>
window10下TensorFlow-gpu环境搭建
查看>>