精华内容
下载资源
问答
  • 手写tomcat

    2018-06-03 02:47:32
    手写tomcat服务,模拟tomcat运行。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  • 手写Tomcat

    2019-05-12 15:15:58
    上一篇博文写了一个项目内嵌tomcat,想了想这次就手写一个简约的Tomcat。 本质其实就是socket通信技术以及io流。 一、Request url:请求路径 method:请求类型 paramMap:请求参数 public class Request { ...

    引言:

    上一篇博文写了一个项目内嵌tomcat,想了想这次就手写一个简约的Tomcat。

    本质其实就是socket通信技术以及io流。

    一、Request

    url:请求路径

    method:请求类型

    paramMap:请求参数

    public class Request {
    
        private String url;
    
        private String method;
    
        private Map<String, String> paramMap = new HashMap<String, String>();
    
        public Request(InputStream inputStream) throws IOException {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String[] methodAndUrl = bufferedReader.readLine().split(" ");
            this.method = methodAndUrl[0];
            int indexOf = methodAndUrl[1].indexOf("?");
            if (indexOf != -1) {
                this.url = methodAndUrl[1].substring(0, indexOf);
                ResoveParams(methodAndUrl[1].substring(indexOf + 1));
            } else {
                this.url = methodAndUrl[1];
            }
        }
    
        public String getRequestParam(String key) {
            return paramMap.get(key);
        }
    
        private void ResoveParams(String str) {
            String[] params = str.split("&");
            for (String p : params) {
                String[] split = p.split("=");
                if (split[0] != null) {
                    paramMap.put(split[0], split[1]);
                }
            }
        }
    
        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;
        }
    
    }

    二、Responce

    public class Response {
        private OutputStream outputStream;
    
        public Response(OutputStream outputStream) {
            this.outputStream = outputStream;
        }
    
        public void write(String content) throws IOException {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append("HTTP/1.1 200 OK\n").append("Content-Type: text/html\n").append("\r\n")
                    .append("<html><body>").append(content).append("</body></html>");
            this.outputStream.write(stringBuffer.toString().getBytes());
            this.outputStream.flush();
            this.outputStream.close();
        }
    
    }

    三、Servlet

    可以自行拓展Delete、Put等请求类型

    public abstract class ExtServlet {
        protected abstract void doGet(Request request, Response response) throws IOException;
    
        protected abstract void doPost(Request request, Response response) throws IOException;
    
        public void service(Request request, Response response) throws IOException {
            String method = request.getMethod();
            if ("get".equalsIgnoreCase(method)) {
                doGet(request, response);
            } else if ("post".equalsIgnoreCase(method)) {
                doPost(request, response);
            } else {
                throw new IllegalArgumentException("request method is null");
            }
        }
    
    }

    四、添加一个servlet(DemoServlet)

     重写doGet、doPost方法

    public class DemoServlet extends ExtServlet {
    
        @Override
        protected void doGet(Request request, Response response) throws IOException {
            doPost(request, response);
    
        }
    
        @Override
        protected void doPost(Request request, Response response) throws IOException {
            String id = request.getRequestParam("id");
            response.write("Hello World! id is:" + id);
        }
    
    }

    五、tomcat服务(创建一个ServerSocket)

    ServerSocket循化监听端口连接,

    我这里直接指定DemoServlet处理请求,可以自行拓展(根据request中url来映射对应的servlet)

    public class HttpServer {
        private int port;
    
        public HttpServer(int port) {
            this.port = port;
        }
    
        public void start() {
            ServerSocket serverSocket = null;
            try {
                System.out.println("服务启动中,端口:" + port);
                serverSocket = new ServerSocket(port);
                while (true) {
                    Socket accept = serverSocket.accept();
                    Request request = new Request(accept.getInputStream());
                    Response response = new Response(accept.getOutputStream());
                    new DemoServlet().service(request, response);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (serverSocket != null) {
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    六、启动服务

    public class App {
        public static void main(String[] args) {
            new HttpServer(8765).start();
        }
    }

    七、测试验证

     Tomcat的简约版就这样了,希望对您有所微薄的帮助,欢迎大家相互交流!

     

                                                                           向上的路并不拥挤,而大多数人选择了安逸——IT疯子也

    展开全文
  • 手写Tomcat全家桶

    2021-04-08 08:32:44
    手写Tomcat
  • 手写TomCat服务器

    2021-04-16 12:42:49
    我们很多时候都想知道Web容器Tomcat是如何工作的?... 通过手写Tomcat服务器,让学员了解服务器的底层代码,方便学员后期的深入学习,而不是停留在表面API的调用层面。   课程讲义截图:  
  • 《Netty核心原理》第二篇 2.手写Tomcat

    万次阅读 2020-09-11 21:33:39
    基于传统I/O手写Tomcat 基于Netty手写Tomcat

    基于传统I/O手写Tomcat
    基于Netty手写Tomcat

    展开全文
  • 手写 tomcat nio

    2018-01-22 17:11:01
    手写 tomcat nio http://knight-black-bob.iteye.com/blog/2408450
  • 手写 tomcat IDEA工程

    2020-11-07 18:58:36
    手写tomcat,最简单的示例,实现了接收http请求和资源获取两个功能,资源分为静态资源和动态资源,模拟了url匹配servlet
  • dubber-netty-tomcat 基于 netty 手写tomcat实例
  • 基于netty手写Tomcat

    2020-09-26 14:43:04
    基于传统I/O手写Tomcat3.基于netty手写Tomcat netty 简介 Netty一个基于NIO的客户、服务器端的编程框架 1.环境准备 RequestMethodEnum 请求方式 public enum RequestMethodEnum { GET("GET"), POST("POST"); ...

    netty 简介

    Netty一个基于NIO的客户、服务器端的编程框架

    1.环境准备

    maven依赖

      <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.1.42.Final</version>
      </dependency>
    

    RequestMethodEnum 请求方式

    public enum RequestMethodEnum {
      GET("GET"),
      POST("POST");
      public String code;
      RequestMethodEnum(String code) {
        this.code=code;
      }
    }
    

    ParentServlet 父类servlet

    public abstract class ParentServlet {
    
      public void service(ParentRequest request, ParentResponse response) throws Exception {
        //service 方法决定调用doGet、doPost;
        if (RequestMethodEnum.GET.code.equalsIgnoreCase(request.getMethod())) {
          doGet(request, response);
        } else {
          doPost(request, response);
        }
      }
    
      protected abstract void doPost(ParentRequest request, ParentResponse response) throws Exception;
    
      protected abstract void doGet(ParentRequest request, ParentResponse response) throws Exception;
    }
    
    
    1. FirstServlet
    public class FirstServlet extends ParentServlet {
      @Override
      protected void doPost(ParentRequest request, ParentResponse response) throws Exception {
        response.write("This is the first");
      }
    
      @Override
      protected void doGet(ParentRequest request, ParentResponse response) throws Exception {
        this.doPost(request,response);
      }
    }
    
    1. SecondServlet
    public class SecondServlet extends ParentServlet {
      @Override
      protected void doPost(ParentRequest request, ParentResponse response) throws Exception {
        response.write("this is the second");
      }
    
      @Override
      protected void doGet(ParentRequest request, ParentResponse response) throws Exception {
        this.doPost(request,response);
      }
    }
    
    1. ParentRequest
    public class ParentRequest {
      private String method;
      private String url;
    
      public String getUrl() {
        return url;
      }
    
      public String getMethod() {
        return method;
      }
    
    }
    
    
    1. ParentResponse
    public class ParentResponse {
      private OutputStream out;
      public ParentResponse (OutputStream out) {
        this.out = out;
      }
    
      public void write(String s) throws Exception{
        //输出也要遵循HTTP
        //状态码为200
        StringBuilder sb = new StringBuilder();
        sb.append("HTTP/1.1 200 OK \n")
          .append("Content-Type: text/html;\n")
          .append("\r\n")
          .append(s);
        out.write(sb.toString().getBytes());
      }
    }
    
    1. web.properties
    servlet.first.url=/first
    servlet.first.className=com.aiden.servlet.FirstServlet
    servlet.second.url=/second
    servlet.second.className=com.aiden.servlet.SecondServlet
    

    2.基于传统I/O手写Tomcat

    1. 修改ParentRequest
    public class ParentRequest {
      private String method;
      private String url;
    
      public ParentRequest(InputStream in) {
        try {
          String content = "";
          byte[] buff = new byte[1024];
          int len = 0;
          if ((len = in.read(buff)) > 0) {
            content = new String(buff,0,len);
          }
          String line = content.split("\\n")[0];
          String [] arr = line.split("\\s");
          this.method = arr[0];
          System.out.println(method);
          this.url = arr[1].split("\\?")[0];
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    
      public String getUrl() {
        return url;
      }
    
      public String getMethod() {
        return method;
      }
    
    }
    
    1. 编写tomcatStart类
    public class TomcatStart {
      private int port = 8080;
      private ServerSocket server;
      private Map<String, ParentServlet> servletMapping = new HashMap<String, ParentServlet>();
      private Properties webProperties = new Properties();
    
      private void init() {
        try {
          String WEB_INF = this.getClass().getResource("/").getPath();
          FileInputStream fis = new FileInputStream(WEB_INF + "web.properties");
          webProperties.load(fis);
          for (Object k : webProperties.keySet()) {
            String key = k.toString();
            if (key.endsWith(".url")) {
              String servletName = key.replaceAll("\\.url$", "");
              String url = webProperties.getProperty(key);
              String className = webProperties.getProperty(servletName + ".className");
              //单实例  多线程
              ParentServlet obj = (ParentServlet) Class.forName(className).newInstance();
              servletMapping.put(url, obj);
            }
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    
      public void start() {
        //1.加载配置类,初始化servletMapping
        init();
    
        try {
          //2.绑定端口启动
          server = new ServerSocket(this.port);
          System.out.println("Tomcat 已启动,监听端口是:" + this.port);
          //3.等待用户请求,用一个死循环
          while (true) {
            Socket client = server.accept();
            //4.http 请求
            process(client);
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    
      private void process(Socket client) throws IOException {
        InputStream is = null;
        OutputStream os = null;
        try {
          is = client.getInputStream();
          os = client.getOutputStream();
          //5.Request(inputstream) Response (outputstream)
          ParentRequest request = new ParentRequest(is);
          ParentResponse response = new ParentResponse(os);
          //6.从协议内容中获取url 映射相应的servlet
          String url = request.getUrl();
          if (servletMapping.containsKey(url)) {
            //7.调用实例化对象的service方法
            servletMapping.get(url).service(request, response);
          } else {
            response.write("404 - Not Found");
          }
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          if (os != null) {
            os.flush();
            os.close();
          }
          if (is != null) {
            is.close();
          }
          client.close();
        }
      }
    
      public static void main(String[] args) {
        //启动
        new TomcatStart().start();
      }
    }
    

    3.基于netty手写Tomcat

    1. 修改ParentRequest
    public class ParentRequest {
      private ChannelHandlerContext ctx;
    
      private HttpRequest req;
    
      public ParentRequest(ChannelHandlerContext ctx, HttpRequest req) {
        this.ctx = ctx;
        this.req = req;
      }
    
      public String getUrl() {
        return req.uri();
      }
    
      public String getMethod() {
        return req.method().name();
      }
    
      public Map<String, List<String>> getParameters() {
        QueryStringDecoder decoder = new QueryStringDecoder(req.uri());
        return decoder.parameters();
      }
    
      public String getParameter(String name) {
        Map<String, List<String>> params = getParameters();
        List<String> param = params.get(name);
        if (null == param) {
          return null;
        } else {
          return param.get(0);
        }
      }
    }
    
    1. 修改ParentResponse
    public class ParentResponse {
      //SocketChannel的封装
      private ChannelHandlerContext ctx;
    
      private HttpRequest req;
    
      public ParentResponse(ChannelHandlerContext ctx, HttpRequest req) {
        this.ctx = ctx;
        this.req = req;
      }
    
      public void write(String out) throws Exception {
        try {
          if (out == null || out.length() == 0) {
            return;
          }
          // 设置 http协议及请求头信息
          FullHttpResponse response = new DefaultFullHttpResponse(
            // 设置http版本为1.1
            HttpVersion.HTTP_1_1,
            // 设置响应状态码
            HttpResponseStatus.OK,
            // 将输出值写出 编码为UTF-8
            Unpooled.wrappedBuffer(out.getBytes("UTF-8")));
    
          response.headers().set("Content-Type", "text/html;");
    
          ctx.write(response);
        } finally {
          ctx.flush();
          ctx.close();
        }
      }
    }
    
    1. 修改TomcatStart
    public class TomcatStart {
      private int port = 8080;
      private Map<String, ParentServlet> servletMapping = new HashMap<String, ParentServlet>();
      private Properties webProperties = new Properties();
    
      private void init() {
        try {
          String WEB_INF = this.getClass().getResource("/").getPath();
          FileInputStream fis = new FileInputStream(WEB_INF + "web.properties");
          webProperties.load(fis);
          for (Object k : webProperties.keySet()) {
            String key = k.toString();
            if (key.endsWith(".url")) {
              String servletName = key.replaceAll("\\.url$", "");
              String url = webProperties.getProperty(key);
              String className = webProperties.getProperty(servletName + ".className");
              //单实例  多线程
              ParentServlet obj = (ParentServlet) Class.forName(className).newInstance();
              servletMapping.put(url, obj);
            }
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    
      public void start() {
        //1.加载配置类,初始化servletMapping
        init();
        // Netty  NIO Reactor模型 Boss Worker
        //Boss 线程
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //Work线程
        EventLoopGroup workGroup = new NioEventLoopGroup();
        ServerBootstrap server = null;
    
        try {
          //创建对象
          server = new ServerBootstrap();
          //配置参数
          //链式编程
          server.group(bossGroup, workGroup)
            //主线程处理类,
            .channel(NioServerSocketChannel.class)
            //子线程处理类
            .childHandler(new ChannelInitializer<SocketChannel>() {
              @Override
              protected void initChannel(SocketChannel client) throws Exception {
                //无锁化串行编程
                //netty对http的封装 对顺序有要求
                //httpResponseEncoder 编码器
                client.pipeline().addLast(new HttpResponseEncoder());
                //httprequestDecoder 解码器
                client.pipeline().addLast(new HttpRequestDecoder());
                //业务处理器
                client.pipeline().addLast(new TomcatHandler());
              }
            })
            //主线程 线程最大数量128
            .option(ChannelOption.SO_BACKLOG, 128)
            //子线程配置 保存长连接
            .childOption(ChannelOption.SO_KEEPALIVE, true);
          ChannelFuture f = server.bind(port).sync();
          System.out.println("Tomcat 已启动,监听端口是:" + this.port);
          f.channel().closeFuture().sync();
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          bossGroup.shutdownGracefully();
          workGroup.shutdownGracefully();
        }
      }
    
      public class TomcatHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
          if (msg instanceof HttpRequest) {
            System.out.println("hello request");
            HttpRequest req = (HttpRequest) msg;
            ParentRequest request = new ParentRequest(ctx, req);
            ParentResponse response = new ParentResponse(ctx, req);
            String url = request.getUrl();
            if (servletMapping.containsKey(url)) {
              //7.调用实例化对象的service方法
              servletMapping.get(url).service(request, response);
            } else {
              response.write("404 - Not Found");
            }
          }
        }
      }
    
      public static void main(String[] args) {
        //启动
        new TomcatStart().start();
      }
    }
    
    

    4.访问

    http://localhost:8080/first
    在这里插入图片描述

    http://localhost:8080/second

    展开全文
  • tomcat学习笔记(二)手写tomcat手写实现迷你版tomcatBootstrapHttpProtocolUtilServletHttpServletLagouServletRequestRequestProcessorResponseStaticResourceUtil 手写实现迷你版tomcat 名称:Minicat Minicat:...

    手写实现迷你版tomcat

    名称:Minicat
    Minicat:作为服务器软件提供服务,我们通过浏览器客户端发送HTTP请求,Minicat可以接受请求进行处理,处理之后的结果可以返回浏览器客户端。
    1、提供服务,接受请求(socket通信)
    2、请求信息封装成request/response对象
    3、客户端请求资源,资源分为静态资源(html)和动态资源(servlet)
    4、资源返回给客户端浏览器

    Bootstrap

    迷你tomcta启动类。

    public class Bootstrap {
        /**
         * 定义socket监听端口号
         */
        private int port=8080;
    
        public int getPort() {
            return port;
        }
    
        public void setPort(int port) {
            this.port = port;
        }
        /**
         *Minicat启动需要初始化展开的一些操作
         */
        public void start() throws Exception {
            //加载解析配置文件web.xml
            loadServlet();
            //定义线程池
            //初始大小
            int corePoolSize=10;
            //最大大小
            int maximumPoolSize=50;
            //存活时长
            long keepAliveTime=100L;
            //时长单位
            TimeUnit unit= TimeUnit.SECONDS;
            //请求队列
            BlockingQueue<Runnable> workQueue=new ArrayBlockingQueue<>(50);
            //线程工厂
            ThreadFactory threadFactory=Executors.defaultThreadFactory();
            //拒绝策略
            RejectedExecutionHandler handler=new ThreadPoolExecutor.AbortPolicy();
            ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler);
    
    
    
            /**
             * 1.0
             * 完成minicat1.0版本(浏览器请求localhost:8080,返回固定的字符串到页面"hellow Minicat!")
             */
            ServerSocket serverSocket=new ServerSocket(port);
            System.out.println("Minicat start on port:"+port);
    //        while (true) {
    //            Socket socket = serverSocket.accept();
    //            //有了socket以后,接收到请求,获取输出流
    //            OutputStream outputStream = socket.getOutputStream();
    //            String data="Hello Minicat!";
    //            String responseText=HttpProtocolUtil.getHttpHeader200(data.getBytes().length)+data;
    //            outputStream.write(responseText.getBytes());
    //            socket.close();
    //        }
            /**
             * 2.0
             * 完成minicat2.0版本
             * 封装Request和Response对象,返回html静态资源文件
             */
    //        while (true) {
    //            Socket socket = serverSocket.accept();
    //            InputStream inputStream = socket.getInputStream();
    //            //封装request/response对象
    //            Request request=new Request(inputStream);
    //            Response response=new Response(socket.getOutputStream());
    //            response.outPutHtml(request.getUrl());
    //            socket.close();
    //        }
    
            /**
             * 3.0
             * 请求动态资源servlet
             */
    //        while (true) {
    //            Socket socket = serverSocket.accept();
    //            InputStream inputStream = socket.getInputStream();
    //            //封装request/response对象
    //            Request request=new Request(inputStream);
    //            Response response=new Response(socket.getOutputStream());
    //            if(servletMap.get(request.getUrl())==null){
    //                response.outPutHtml(request.getUrl());
    //            }else {
    //                HttpServlet httpServlet = servletMap.get(request.getUrl());
    //                httpServlet.service(request,response);
    //            }
    //            socket.close();
    //        }
    
    
            /**
             * 不适用线程池
             * 多线程改造
             */
    //        while (true) {
    //            Socket socket = serverSocket.accept();
    //            RequestProcessor requestProcessor=new RequestProcessor(socket,servletMap);
    //            requestProcessor.start();
    //        }
    
            System.out.println("使用线程池进行多线程改造");
            /**
             * 使用线程池
             * 多线程改造
             */
            while (true) {
                Socket socket = serverSocket.accept();
                RequestProcessor requestProcessor=new RequestProcessor(socket,servletMap);
                threadPoolExecutor.execute(requestProcessor);
            }
        }
        private Map<String,HttpServlet> servletMap=new HashMap<>();
        //加载解析web.xml初始化servlet
        private void loadServlet() {
            InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
            SAXReader saxReader=new SAXReader();
            try {
                Document document = saxReader.read(resourceAsStream);
                Element rootElement = document.getRootElement();
                List<Element> list = rootElement.selectNodes("//servlet");
                for (int i = 0; i < list.size(); i++) {
                    Element element = list.get(i);
                    Element servletNameElement = (Element) element.selectSingleNode("servlet-name");
                    //servlet-name>lagouServlet</servlet-name>
                    String servletName=servletNameElement.getStringValue();
                    Element servletClassElement = (Element) element.selectSingleNode("servlet-class");
                    //<servlet-class>server.LagouServlet</servlet-class>
                    String servletClass=servletClassElement.getStringValue();
    
    
                    //根据servletName的值找到url-pattern
                    Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                    //<url-pattern>/lagou</url-pattern>
                    String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                    try {
                        servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Minicat启动入口
         * @param args
         */
        public static void main(String[] args) {
            Bootstrap bootstrap=new Bootstrap();
            try {
                //启动Minicat
                bootstrap.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    HttpProtocolUtil

    http协议工具类,

    
    /**
     * http协议工具类,主要是提供响应头信息,这里我们提供200和404的情况
     */
    public class HttpProtocolUtil {
        /**
         * 为响应码200提供请求头信息
         * @return
         */
        public static String getHttpHeader200(long contentLength){
            return "HTTP/1.1 200 OK \n" +
                    "Content-Type: text/html;charset=utf-8 \n" +
                    "Content-Length: " +contentLength+" \n" +
                    "\r\n";
        }
    
        /**
         * 为响应码404提供请求头信息(此处也包含了数据内容)
         * @return
         */
        public static String getHttpHeader404(){
            String str="<h1>404 not found</h1>";
            return "HTTP/1.1 404 NOT Found \n" +
                    "Content-Type: text/html;charset=utf-8 \n" +
                    "Content-Length: " +str.getBytes().length+" \n" +
                    "\r\n" + str;
        }
    
    }
    

    Servlet

    servlet接口,定义servlet规范

    public interface Servlet {
        void init() throws Exception;
        void destroy() throws Exception;
        void service(Request request,Response response) throws Exception;
    }
    
    

    HttpServlet

    处理请求的httpservlet

    public abstract class HttpServlet implements Servlet{
        public abstract void doGet(Response response,Request request);
        public abstract void doPost(Request request,Response response);
        @Override
        public void service(Request request, Response response) throws Exception {
            if("GET".equals(request.getMethod())){
                doGet(response,request);
            }else {
                doPost(request,response);
            }
        }
    }
    

    LagouServlet

    自定义servlet

    public class LagouServlet extends HttpServlet{
        @Override
        public void doGet(Response response, Request request) {
            try {
                Thread.sleep(200000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String string="<h1>LagouServlet get</h1>";
            try {
                response.outPut(HttpProtocolUtil.getHttpHeader200(string.getBytes().length)+string);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void doPost(Request request, Response response) {
            String string="<h1>LagouServlet post</h1>";
            try {
                response.outPut(HttpProtocolUtil.getHttpHeader200(string.getBytes().length)+string);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void init() throws Exception {
    
        }
    
        @Override
        public void destroy() throws Exception {
    
        }
    }
    

    Request

    请求信息封装类

    /**
     * 把请求信息封装为Request对象(根据inputStream封装)
     */
    public class Request {
        //请求方式get/post
        private String method;
        //url
        private String url;
        //输入流,其他属性从输入流解析出来
        private InputStream inputStream;
    
        public Request() {
        }
        //构造器,输入流传入,解析出url和method
        public Request(InputStream inputStream) throws IOException {
            this.inputStream = inputStream;
            int count=0;
            while (count==0){
                count=inputStream.available();
            }
            byte[] bytes=new byte[count];
            inputStream.read(bytes);
            System.out.println("请求信息:"+new String(bytes));
            String string=new String(bytes);
            //获取第一行请求头信息 GET / HTTP/1.1
            String firstLine=string.split("\\n")[0];
            String[] s = firstLine.split(" ");
            this.method=s[0];
            this.url=s[1];
    
            System.out.println("method:"+this.method);
            System.out.println("url:"+this.url);
        }
    
        public String getMethod() {
            return method;
        }
    
        public void setMethod(String method) {
            this.method = method;
        }
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public InputStream getInputStream() {
            return inputStream;
        }
    
        public void setInputStream(InputStream inputStream) {
            this.inputStream = inputStream;
        }
    }
    
    

    RequestProcessor

    请求处理器

    public class RequestProcessor extends Thread{
        private Socket socket;
        private Map<String,HttpServlet> servletMap;
    
        public RequestProcessor() {
        }
    
        public RequestProcessor(Socket socket, Map<String, HttpServlet> servletMap) {
            this.socket = socket;
            this.servletMap = servletMap;
        }
    
        @Override
        public void run() {
            try {
                InputStream inputStream = socket.getInputStream();
                //封装request/response对象
                Request request=new Request(inputStream);
                Response response=new Response(socket.getOutputStream());
                if(servletMap.get(request.getUrl())==null){
                    response.outPutHtml(request.getUrl());
                }else {
                    HttpServlet httpServlet = servletMap.get(request.getUrl());
                    httpServlet.service(request,response);
                }
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    Response

    返回信息封装类

    /**
     * 把相应信息封装为Response对象(根据outputStream封装)
     * 该对象需要提供核心对象,输出静态资源(html)
     */
    public class Response {
        private OutputStream outputStream;
    
        public Response() {
        }
    
        public Response(OutputStream outputStream) {
    
            this.outputStream = outputStream;
        }
        //使用输出流输出指定字符串
        public void outPut(String content) throws IOException {
            this.outputStream.write(content.getBytes());
        }
        /**
         *
         * @param path url ,根据url获取到静态资源的绝对路径,根据绝对路径,进一步读取该静态文件,最终通过输出流输出
         */
        public void outPutHtml(String path) throws IOException {
            //获取静态资源的绝对路径
            String absoluteResourcePath=StaticResourceUtil.getAbsolutePath(path);
            //输出静态资源
            File file=new File(absoluteResourcePath);
            if(file.exists()&& file.isFile()){
                //读取静态资源文件,输出静态资源
                StaticResourceUtil.outputStaticResource(new FileInputStream(file),outputStream);
            }else {
                //输出404
                outPut(HttpProtocolUtil.getHttpHeader404());
            }
        }
    }
    

    StaticResourceUtil

    静态资源工具类

    public class StaticResourceUtil {
        /**
         * 获取静态资源的绝对路径
         * @param path
         * @return
         */
        public static String getAbsolutePath(String path){
            String absolutePath=StaticResourceUtil.class.getResource("/").getPath();
            return absolutePath.replaceAll("\\\\","/")+path;
        }
    
        /**
         * 读取静态资源文件输入流,通过输出流输出
         * @param inputStream
         * @param outputStream
         */
        public static void outputStaticResource(InputStream inputStream, OutputStream outputStream) throws IOException {
            int count=0;
            while (count==0){
                count = inputStream.available();
            }
            int resourceSize=count;
            //http请求头输出,然后输出具体内容
            outputStream.write(HttpProtocolUtil.getHttpHeader200(resourceSize).getBytes());
            //读取输出内容
            long written=0;//已经读取的内容长度
            int byteSize=1024;//计划每次缓冲长度
            byte[] bytes=new byte[byteSize];
            while (written<resourceSize){
                if(written+byteSize>resourceSize){//剩余未读取大小不足1024,那就按照真实长度处理
                    byteSize= (int) (resourceSize-written);
                    bytes=new byte[byteSize];
                }
                inputStream.read(bytes);
                outputStream.write(bytes);
                outputStream.flush();
                written+=byteSize;
            }
        }
    }
    
    展开全文
  • 手写Tomcat框架

    2019-11-25 22:20:30
    实现了一个简单的Tomcat框架,模拟了Tomcat框架中处理浏览器请求Servlet最基础的功能。
  • 手写tomcat主要分为3个步骤 提供socket服务 把请求和响应封装为request/response 根据请求进行转发 Maven依赖 request解析参数时使用到了json工具类帮助解析json字符串 <!--JSON依赖--> <...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,822
精华内容 3,128
关键字:

手写tomcat