Those things Apache Software Foundation's Tomcat core project

Tomcat server is a free open source Web application server, are lightweight application server, it is not widely used in many occasions small and medium systems and concurrent user access is the preferred development and debugging JSP program. Today to tell you about the details of the Tomcat.

1
Disclaimer:
1: I read this series record only Tomcat >> <<-depth analysis of some of the book's insights, deficiencies, correct message should be grateful. 2: This series of in-depth analysis of all the code reference << Tomcat >>, imperfect, message correct, be grateful.
Concept: Portal: tomcat Baidu Encyclopedia, said here a point, tomcat is lightweight javaweb server that handles servlet / jsp and other dynamic web page, although you can also handle static pages, but still a lot less in terms of comparison apache . Friends who are interested can find out otherwise nginx, iis, apache, and other more popular web server.
Used tomcat friends should know that when the java web project deployment to tomcat, in the browser address bar type: HTTP: // localhost: 8080 / resource path, you can access the project resources. In this process, tomcat role dispatch center receives the browser sends a resource request and parse, according to the analysis results to designated web project processing, then according to the results, the response to the browser. In this regard, we have to look at, tomcat how you do it .
Project structure:

MyTomcat
receiving a request (Request)
would like to receive a request initiated by the browser needs to be done to prepare a few hands, 1: listening port (8080), 2: receiving a browser connection (socket connection) 3: parsing HTTP request data. Here is the code simulation:

第一第二步: 使用httpServer模拟tomcat调度中心
/**
 * 模拟tomcat的核心类
 */public class HttpServer {
    //tomcat项目绝对路径, 所有web项目都丢在webapps目录下
    public static final String WEB_ROOT =
            System.getProperty("user.dir") + File.separator  + "webapps";
    // 模拟tomcat关闭命令
    private static final String SHUTDOWN_CMD = "/SHUTDOWN";
    private boolean shutdown = false;
    //持续监听端口
    @SuppressWarnings("resource")
    public void accept() {
        ServerSocket serverSocket = null;
        try {
            // 启动socket服务, 监听8080端口,
            serverSocket =  new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("启动myTomcat服务器失败:" + e.getMessage(), e);
        }
        // 没接收到关闭命令前一直监听
        while (!shutdown) {
            Socket socket = null;
            InputStream in = null;
            OutputStream out = null;
            try {
                // 接收请求
                socket = serverSocket.accept();
                in = socket.getInputStream();
                out = socket.getOutputStream();
                // 将浏览器发送的请求信息封装成请求对象
                Request request = new Request(in);
                request.parseRequest();
                // 将相应信息封装相应对象
                //此处简单响应一个静态资源文件
                Response response = new Response(out);
                //模拟页面跳转
                response.sendRedircet(request.getUri());
                socket.close();
                //如果是使用关闭命令,停止监听退出
                shutdown = request.getUri().equals(SHUTDOWN_CMD);
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
    }
    public static void main(String[] args) {
        new HttpServer().accept();
    }
}
第三步,使用HttpReqeust封装请求相关信息
/**
 * 请求信息封装对象
 */public class Request {
    // 浏览器socket连接的读流
    private InputStream in;
    //请求行信息信息中的uri
    private String uri;
    public Request(InputStream in) {
        this.in = in;
    }
    // 解析浏览器发起的请求
    public void parseRequest() {
        // 暂时忽略文件上传的请求,假设都字符型请求
        byte[] buff = new byte[2048];
        StringBuffer sb = new StringBuffer(2048);
        int len = 0;
        //请求内容
        try {
            len = in.read(buff);
            sb.append(new String(buff, 0, len));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.print(sb.toString());
        //解析请求行中uri信息
        uri = this.parseUri(sb.toString());
    }

    /**tomcat接收浏览器发起的请求是居于http协议的,请求内容格式:*/
    /**请求行:请求方式   请求uri 协议版本*/
    //GET /index HTTP/1.1    
    /**请求头:以key-value形式存在*/
    //Host: localhost:8080
    //Connection: keep-alive
    //Upgrade-Insecure-Requests: 1
    //User-Agent: Mozilla/5.0 .........
    //Accept: text/html,application/xhtml+xml......
    //Accept-Encoding: gzip, deflate, br
    //Accept-Language: zh-CN,zh;q=0.9
    //Cookie: .....
    /**请求体: 请求头回车格一行就是请求体,get方式请求体为空*/
    public String parseUri(String httpContent) {
        //传入的内容解析第一行的请求行即可:
        //请求行格式:  请求方式   请求uri 协议版本     3个内容以空格隔开
        int beginIndex = httpContent.indexOf(" ");
        int endIndex;
        if(beginIndex > -1) {
            endIndex = httpContent.indexOf(" ", beginIndex + 1);
            if(endIndex > beginIndex) {
                return httpContent.substring(beginIndex, endIndex).trim();
            }
        }
        return null;
    }

    public String getUri() {
        return uri;
    }
}
假设,浏览器发起请求:http://localhost:8080/hello/index.html HttpServer中socket通过输入流获取到的数据是:
GET /hello/index.html HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: Hm_lvt_aa5c701f4f646931bf78b6f40b234ef5=1516445118,1516604544,1518416964,1518497222; JSESSIONID=79367FD9A55B9B442C4ED112D10FDAC5
HttpServer 将上述的数据交于HttpRequest对象处理,该对象调用parseRequest解析,获取请求行中的uri 数据, 分析该数据, 得到上下文路径,项目名,资源名。统称资源路径。
上面数据得到: hello 项目下, index.html 资源(没有上下文路径)
响应请求
当从请求信息中获取uri后,进而获取到hello 项目, index.html资源, 响应请求就可以简单认为根据资源路径查找资源,如果找到,使用socket output流直接输出资源数据即可,如果找不到,输出404信息。

 * 处理响应请求对象
public class Response {
    // 浏览器socket连接的写流
    private OutputStream out;

    public Response(OutputStream out) {
        this.out = out;
    }
    public OutputStream getOutputStream() {
        return out;
    }
    //跳转
    public void sendRedircet(String uri) {

        File webPage = new File(HttpServer.WEB_ROOT, uri);
        FileInputStream fis = null;
        StringBuffer sb = new StringBuffer();
        try {
            //找得到页面是
            if(webPage.exists()&& webPage.isFile()) {
                String respHeader = "HTTP/1.1 200 OK\r\n" +
                  "Content-Type: text/html\r\n" +
                  "Content-Length: #{count}\r\n" +
                  "\r\n";
                fis = new FileInputStream(webPage);
                byte[] buff = new byte[2048];
                int len = 0;
                while( (len = fis.read(buff))!= -1) {
                    sb.append(new String(buff, 0, len));
                }
                respHeader=respHeader.replace("#{count}", sb.length()+"");
                System.out.println(respHeader + sb);
                out.write((respHeader + sb).getBytes());

            }else {
                 //页面找不到时
                String errorMessage = "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(errorMessage.getBytes());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Note here that, in response to the request data must follow the http protocol.
For Tomcat, there are a lot of content need to study, if you are interested, may wish to join us, to continue to explore. Follow us now, we continue in-depth exploration of Tomcat.

Guess you like

Origin blog.51cto.com/13007966/2458400