• 学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat


    学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat

                                                                                                                                 

     

                                                                                                                                                                                          2019-05-09   19:28:42 

     

     

    注:项目(MyEclipse)创建的时候选择:Web Service Project

    第一步 对Tomcat工作流程进行分析

     

    第二步 对其项目进行全局的把关

    首先看看Project(FirstTomcat)的目录结构

    |-FirstTomcat

    |——src

    |   |-org.mrzhangxd.com

    |     |-FirstRequest.java

    |     |-FirstResponse.java

    |     |-FirstServlet.java

    |     |-FirstTomcat.java

    |     |-FirstServletMapping.java

    |     |_FirstServletMappingConfig.java

    |   |-JRE System Library[JavaSE-x.y]

    |   |-JAXB x.y.z Libraries

    |   |-JavaEE x.y Generic Library

    |   |-JSTL x.y.z Library

    |   |-JAX-RS x.y Libraries(Project Jersey x.y)

    |___|_WebRoot

    第三步 代码实现

    处理请求:

      1. 创建一个request对象并填充那些有可能被所引用的Servlet使用的信息,如参数,头部、cookies、查询字符串等。
      2. 创建一个response对象,所引用的servlet使用它来给客户端发送响应。
      3. 调用servlet的service方法,并传入request和response对象。这里servlet会从request对象取值,给response写值。
      4. 根据servlet返回的response生成相应的HTTP响应报文。

    接下来一一实现

     

    请求:FirstRequest.java

     

    package org.mrzhangxd.com;

    import java.io.InputStream;

    /**

     *

     * @author mrzhangxd

     *

     */

    public class FirstRequest {

            //请求路径

            private String url;

            //请求方法

            private String method;

            public FirstRequest(InputStream inputStream)throws Exception{

                String httpRequest = "";

                byte[] httpRequestBytes = new byte[1024];

                int length = 0;

                if((length = inputStream.read(httpRequestBytes))>0){

                    httpRequest = new String(httpRequestBytes,0,length);

                }

                //HTTP请求协议:首行的内容依次为:请求方法、请求路径以及请求协议及其对应的版本号

                //GET    /index    /HTTP/1.1

                String httpHead = httpRequest.split(" ")[0];//取出HTTP协议的首行

                System.out.println(httpHead);

                method = httpHead.split("\s")[0];//按照空格进行分割,第一个请求方法

               

                url = httpHead.split("\s")[1];//按照空格进行分割,第二个是路径

                System.out.println(this.toString());

            }

           

            public String getUrl() {

                return url;

            }

            public void setUrl(String url) {

                this.url = url;

            }

            public String getMethod() {

                return method;

            }

            public void setMethod(String method) {

                this.method = method;

            }

            public String toString(){

                return "MyRequest[url = "+url+",method = "+method+"]";

               

            }

    }

     

    回应:FirstResponse.java

     

    package org.mrzhangxd.com;

    import java.io.IOException;

    import java.io.OutputStream;

    /**

     *

     * @author mrzhangxd

     *

     */

    public class FirstResponse {

        private  OutputStream outputStream;

        public FirstResponse(OutputStream outputStream){

            this.outputStream = outputStream;

        }

        //将文本转换为字节流

        public void write(String content)throws IOException{

            StringBuffer httpResponse = new StringBuffer();

            httpResponse.append("HTTP/1.1 200 OK ")

            .append("Content-Type;text/html ")

            .append(" ")

            .append("<html><link rel = "icon"href = "data:;base64,=">")

            .append(content)//将页面内容写入

            .append("</body></html>")

            .append("");

            outputStream.write(httpResponse.toString().getBytes());//将文本转换为字节码

            outputStream.close();

        }

    }

     

    Servlet请求处理基类:FirstServlet.java

     

    package org.mrzhangxd.com;

    /**

     *

     * @author mrzhangxd

     *

     */

    public abstract class FirstServlet {

        public void servlet(FirstRequest firstRequest,FirstResponse firstResponse){

            if(firstRequest.getMethod().equalsIgnoreCase("POST")){

                doPost(firstRequest,firstResponse);

            }else if(firstRequest.getMethod().equalsIgnoreCase("GET")){

                doGet(firstRequest,firstResponse);

            }

        }

        private void doGet(FirstRequest firstRequest, FirstResponse firstResponse) {

            // TODO Auto-generated method stub

        }

        private void doPost(FirstRequest firstRequest, FirstResponse firstResponse) {

            // TODO Auto-generated method stub

        }

        public void service(FirstRequest firstRequest, FirstResponse firstResponse) {

            // TODO Auto-generated method stub

        }

    }

     

    下一步servlet配置:FirstServletMapping.java

     

    package org.mrzhangxd.com;

     

    /**

     *

     * @author mrzhangxd

     *

     */

    public class FirstServletMapping {

        private String servletName;

        private String url;

        private String clazz;

       

        public FirstServletMapping(String servletName, String url, String clazz) {

            super();

            this.servletName = servletName;

            this.url = url;

            this.clazz = clazz;

        }

       

        public String getServletName() {

            return servletName;

        }

       

        public void setServeletName(String servletName) {

            this.servletName = servletName;

        }

       

        public String getUrl() {

            return url;

        }

       

        public void setUrl(String url) {

            this.url = url;

        }

       

        public String getClazz() {

            return clazz;

        }

       

        public void setClazz(String clazz) {

            this.clazz = clazz;

        }

    }

     

    其他配置:FirstServletMappingConfig.java

     

    package org.mrzhangxd.com;

    import java.util.ArrayList;

    import java.util.List;

    /**

     *

     * @author mrzhangxd

     *

     */

    public class FirstServletMappingConfig {

        public static List<FirstServletMapping> servletMappingList = new ArrayList<>();

        static {

            servletMappingList.add(new FirstServletMapping("index", "/index", "firstTomcat.test.IndexServlet"));

            servletMappingList.add(new FirstServletMapping("firstblog", "/firstblog", "firstTomcat.test.MyBlog"));

        }

    }

     

    核心处理类:FirstTomcat.java,处理流程如下:

    1)   提供Socket服务

    2)   封装请求/响应对象

    3)   将不同的请求映射到具体的Servlet处理

    这里重点说的是,要利用 ServerSocket 通过服务器上的端口通信 以及 accpt方法一直等待客户端的请求

    package org.mrzhangxd.com;

    import java.io.InputStream;

    import java.io.OutputStream;

    import java.net.ServerSocket;

    import java.net.Socket;

    import java.util.HashMap;

    import java.util.Map;

    /**

     *

     * @author mrzhangxd

     *

     */

    public class FirstTomcat {

        private Integer port = 8080;     //定义8080端口    

        private Map<String, String> urlServletMapping = new HashMap<>();    //存储url和对应的类

        public FirstTomcat(Integer port) {

            super();

            this.port = port;

        } 

        @SuppressWarnings("resource")

        public void start() {

            initServletMapping();      

            try {

                ServerSocket serverSocket = null;     //实例化一个 ServerSocket 对象,表示通过服务器上的端口通信

                serverSocket = new ServerSocket(port);  

                System.out.println("MyTomcat is starting...");

                while(true) {

                Socket socket = serverSocket.accept();     //服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口

                InputStream inputStream = socket.getInputStream();

                OutputStream outputStream = socket.getOutputStream(); 

                FirstRequest myRequest = new FirstRequest(inputStream);

                FirstResponse myResponse = new FirstResponse (outputStream);   

                dispatch(myRequest, myResponse);       

                socket.close();               

                }

            }catch(Exception e) {

                e.printStackTrace();

            }

        }

        //初始化映射

        public void initServletMapping() {

            for(FirstServletMapping servletMapping : FirstServletMappingConfig.servletMappingList) {

                urlServletMapping.put(servletMapping.getUrl(), servletMapping.getClazz());

            }

            }  

        //分发请求

        @SuppressWarnings("unchecked")

        public void dispatch(FirstRequest firstRequest, FirstResponse firstResponse) {

            String clazz = urlServletMapping.get(firstRequest.getUrl());        

            try {

                Class<FirstServlet> firstServletClass = (Class<FirstServlet>)Class.forName(clazz);

                FirstServlet firstservlet = firstServletClass.newInstance();

                firstservlet.service(firstRequest, firstResponse);

            }catch(ClassNotFoundException e) {

                e.printStackTrace();

            }catch(InstantiationException e) {

                e.printStackTrace();

            }catch(IllegalAccessException e) {

                e.printStackTrace();

            }

            }    

            public static void main(String[] args) {

                FirstTomcat myTomcat = new FirstTomcat(8080);

                myTomcat.start();

            }

    }

     

    测试类按照上面类里的注释自己解决,测试结果略。

     

    注:

    编码格式、注释都参考《代码整洁之道》

  • 相关阅读:
    深入解析 float
    解决 css 浮动后 父元素高度失效问题
    高性能 Socket 组件 HP-Socket v3.2.1-RC1 公布
    基于lucene.net 和ICTCLAS2014的站内搜索的实现1
    史上最简单的个人移动APP开发入门--jQuery Mobile版跨平台APP开发
    【OpenCV新手教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放
    栈模拟队列 队列模拟栈
    状态机的两种写法
    Hadoop-2.2.0中文文档—— MapReduce 下一代--容量调度器
    OpenGLES 与 WebGL 中顶点属性的组织格式的误解
  • 原文地址:https://www.cnblogs.com/MrZhangxd/p/10840519.html
Copyright © 2020-2023  润新知