> 文档中心 > 深度理解Tomcat底层机制

深度理解Tomcat底层机制

Tomcat

  • Tomcat
    • 概述
      • BS 与 CS 开发介绍
      • 常用服务器
      • Tomcat 目录结构
    • Web应用
    • 浏览器请求资源过程
    • IDEA 开发 JavaWeb 注意事项
    • Maven
      • 基本介绍
      • IDEA创建Maven项目说明
      • pom.xml文件说明
    • 实现Tomcat底层机制
      • 框架图
      • 实现案例
        • 题目要求
        • xml文件
        • 静态资源
        • 网络监听
        • 线程处理请求和响应
        • 请求类和响应类
        • Servlet接口实现
        • 工具类

大家好呀,我是小笙,我和大家分享下我学习Javaweb的笔记

Tomcat

概述

BS 与 CS 开发介绍

深度理解Tomcat底层机制

(1) 兼容性 , 浏览器的种类很多
(2) 安全性, 通常情况下,BS 安全性不如 CS 好控制
(3) 易用性, BS 好于 CS, 浏览器方便在线使用
(4) 扩展性, BS 相对统一,只需要写 Server

常用服务器

  1. Tomcat:由 Apache 组织提供的一种 Web 服务器,提供对 jsp 和 Servlet 的支持。它 是一种轻量级的 javaWeb 容器(服务器),也是当前应用最广的 JavaWeb 服务器(免费),Tomcat 本质就是一个 Java 程序, 但是这个 Java 程序可以处理来自浏览器的 HTTP 请求

    Tomcat下载网址

  2. Jboss:是一个遵从 JavaEE 规范的、它支持所有的 JavaEE 规范(免费)

  3. GlassFish: 由 Oracle 公司开发的一款 JavaWeb 服务器,是一款商业服务器,达到产品级质量(应用很少)

  4. Resin:是 CAUCHO 公司的产品,是一个非常流行的服务器,对 servlet 和 JSP 提供了 良好的支持, 性能也比较优良(收费)

  5. WebLogic:是 Oracle 公司的产品,支持 JavaEE 规范, 而且不断的完善以适 应新的开发要求,适合大型项目(收费,用的不多,适合大公司)

Tomcat 目录结构

深度理解Tomcat底层机制

深度理解Tomcat底层机制

Web应用

Tomcat 服务中部署 WEB 应用

概念:Web应用通常也称之为web应用程序(网站),WEB应用是多个web资源的集合

组成

深度理解Tomcat底层机制

在Tomcat 下的 conf 目录\Catalina\localhost\ 下,配置文件,比如XXX.xml(提醒:通过Tomcat配置,可以把一个web应用,映射到指定的目录,可以解决磁盘空间分配问题

浏览器请求资源过程

深度理解Tomcat底层机制

注意:http://localhost , 默 认 是 访 问 80 端 口 , 即 http://localhost 等 价 http://localhost:80

IDEA 开发 JavaWeb 注意事项

1.热加载选项说明

深度理解Tomcat底层机制

2.修改端口,只会影响当前的项目,但是不会去修改tomcat文件中server.xml文件的端口

3.当tomcat启动时,会生成out目录,该目录就是原项目资源的映射,我们浏览器访问的资源是 out 目录

Maven

基本介绍

概述:一个项目管理工具,可以对 Java 项目进行构建、依赖管理

深度理解Tomcat底层机制

IDEA创建Maven项目说明

深度理解Tomcat底层机制

深度理解Tomcat底层机制

pom.xml文件说明

深度理解Tomcat底层机制

<dependencies>        <dependency>      <groupId>javax.servlet</groupId>      <artifactId>javax.servlet-api</artifactId>      <version>3.1.0</version>      <scope>provided</scope>    </dependency>  </dependencies>

实现Tomcat底层机制

框架图

深度理解Tomcat底层机制

实现案例

题目要求

  • 可以访问静态资源addSum.html

    深度理解Tomcat底层机制

  • 可以通过提交按钮,跳转到求和解结果

    深度理解Tomcat底层机制

文件目录说明

深度理解Tomcat底层机制

xml文件

<myTomcat>  <myServlet>    <Servlet-name>myTomcat</Servlet-name>    <Servlet-class>com.al_tair.myTomcat.myServlet.CalServlet</Servlet-class>  </myServlet>  <myServlet-mapping>    <Servlet-name>myTomcat</Servlet-name>    <url-pattern>/myTomcat</url-pattern>  </myServlet-mapping></myTomcat>

静态资源

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body><form action="http://localhost:9999/myTomcat" method="get">    <h1>求和</h1>    第一个数字:<input type="text" name="firstNum"><br>    第二个数字:<input type="text" name="secondName"><br>    <button type="submit">提交</button></form></body></html>

网络监听

public class Connector {    // 存放    public static final ConcurrentHashMap<String, MyHttpServlet>     nameToServlet = new ConcurrentHashMap<>();    // 存放    public static final ConcurrentHashMap<String, String>     urlToName = new ConcurrentHashMap<>();    public static void main(String[] args) throws IOException, InterruptedException { // 在端口9999监听 ServerSocket serverSocket = new ServerSocket(9999); while(!serverSocket.isClosed()){     init();     // 创建套接字 socket     System.out.println("listening...");     Socket socket = serverSocket.accept();     RequestHandler rh = new RequestHandler(socket);     new Thread(rh).start(); }    } public static void init(){ String path = Connector.class.getResource("/").getPath(); SAXReader saxReader = new SAXReader(); try {     Document document = saxReader.read(new File(path + "web.xml"));     // 得到根元素     Element rootElement = document.getRootElement();     // 得到根元素下的所有元素     List<Element> myServlet = rootElement.elements();     for (Element element: myServlet   ) {  if("myServlet".equalsIgnoreCase(element.getName())){      Element element1 = element.element("Servlet-name");      Element element2 = element.element("Servlet-class");      nameToServlet.put(element1.getText(),(MyHttpServlet)Class.forName(element2.getText()).newInstance());  }else if("myServlet-mapping".equalsIgnoreCase(element.getName())){      Element element1 = element.element("Servlet-name");      Element element2 = element.element("url-pattern");      urlToName.put(element2.getText(),element1.getText());  }     } } catch (Exception e) {     e.printStackTrace(); }    }}

线程处理请求和响应

public class RequestHandler implements Runnable{    private Socket socket = null;    public RequestHandler(Socket socket) { this.socket = socket;    }    @Override    public void run() { MyHttpRequest Request = null; MyHttpResponse Response = null; try {     Request = new MyHttpRequest(socket.getInputStream());     Response = new MyHttpResponse(socket.getOutputStream());     String uri = Request.getUri();     System.out.println(uri);     String path = RequestHandler.class.getResource("/").getPath();     if(Connector.urlToName.containsKey(uri)){  String name = Connector.urlToName.get(uri);  if(Connector.nameToServlet.containsKey(name)){      MyHttpServlet myHttpServlet = Connector.nameToServlet.get(name);      try {   myHttpServlet.service(Request,Response);      } catch (Exception e) {   e.printStackTrace();      }  }else{      OutputStream outputStream = Response.getOutputStream();      int index = uri.indexOf(".");      if(uri.substring(index+1).equalsIgnoreCase("html")){   try {FileReader fileReader = new FileReader(path + "/static" + uri);BufferedReader br = new BufferedReader(fileReader);String str = "";outputStream.write(Response.getResponseHeader().getBytes());while((str = br.readLine()) != null){    outputStream.write(str.getBytes());}outputStream.flush();outputStream.close();   } catch (Exception e) {e.printStackTrace();   }      }else{   outputStream.write((Response.responseHeader + "

404,没有找到该资源

"
).getBytes()); outputStream.flush(); outputStream.close(); } } }else{ OutputStream outputStream = Response.getOutputStream(); int index = uri.indexOf("."); if(uri.substring(index+1).equalsIgnoreCase("html")){ try { FileReader fileReader = new FileReader(path + "/static" + uri); BufferedReader br = new BufferedReader(fileReader); String str = ""; outputStream.write(Response.getResponseHeader().getBytes()); while((str = br.readLine()) != null){outputStream.write(str.getBytes()); } outputStream.flush(); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } }else{ outputStream.write((Response.responseHeader + "

404,没有找到该资源

"
).getBytes()); outputStream.flush(); outputStream.close(); } } socket.close(); } catch (IOException e) { throw new RuntimeException(); } }}

请求类和响应类

/** * 封装http请求数据简化 */public class MyHttpRequest {    private String uri;    private String method;    private HashMap<String,String> parameters = new HashMap<>();    private InputStream inputStream = null;    public MyHttpRequest(InputStream inputStream) {this.inputStream = inputStream;init();    }    public String getUri() { return uri;    }    public String getMethod() { return method;    }    public void init(){ try {     // 将字节流转换成字符流,方便读取数据     BufferedReader bufferedReader =      new BufferedReader(new InputStreamReader(inputStream, "utf-8"));     String request = bufferedReader.readLine();     String[] requestLine = request.split(" ");     // GET /servlet?name=18 HTTP/1.1     method = requestLine[0];     int index = requestLine[1].indexOf("?");     if(index == -1){  // uri后面没有数据  uri = requestLine[1];     }else{  uri = requestLine[1].substring(0,index);  String parameter = requestLine[1].substring(index+1);  String[] params = parameter.split("&");  if(parameter != null && !params.equals("")){      for (String param:params      ) {   String[] split = param.split("=");   if(split.length == 2){parameters.put(split[0],split[1]);   }      }  }     } }catch (IOException e){     throw new RuntimeException(); }    }    public String Parameter(String name){ if(parameters.containsKey(name)){     return parameters.get(name); }else{     return null; }    }}/** * http响应头封装简化 */public class MyHttpResponse {    private OutputStream outputStream = null;    public String responseHeader = "HTTP/1.1 200OK\r\n" +     "Content-Type:text/html;charset=utf-8\r\n\r\n";    public MyHttpResponse(OutputStream outputStream) { this.outputStream = outputStream;    }    public OutputStream getOutputStream() { return outputStream;    }    public String getResponseHeader() { return responseHeader;    }}

Servlet接口实现

// Servlet接口public interface MyServlet {    void init() throws Exception;    void service(MyHttpRequest var1, MyHttpResponse var2) throws Exception;    void destroy();}// 抽象类public abstract class MyHttpServlet implements MyServlet{    @Override    public void service(MyHttpRequest request, MyHttpResponse response) throws Exception { if("GET".equals(request.getMethod())){     this.doGet(request,response); }else if("POST".equals(request.getMethod())){     this.doPost(request,response); }    }    @Override    public void init() throws Exception {    }    @Override    public void destroy() {    }    public abstract void doGet(MyHttpRequest request, MyHttpResponse response);    public abstract void doPost(MyHttpRequest request, MyHttpResponse response);}// Servlet资源public class CalServlet extends MyHttpServlet{    @Override    public void doGet(MyHttpRequest request, MyHttpResponse response) { String num1 = request.Parameter("firstNum"); String num2 = request.Parameter("secondName"); int sum = Utils.StringToInteger(num1, num2); OutputStream outputStream = response.getOutputStream(); try {     outputStream.write((response.responseHeader  + "

求和: " + sum + "

"
).getBytes()); outputStream.flush(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public void doPost(MyHttpRequest request, MyHttpResponse response) { doPost(request,response); }}

工具类

public class Utils {    /**     * 字符串转成整数求和     */    public static int StringToInteger(String var1,String var2){ try{     return Integer.parseInt(var1) + Integer.parseInt(var2); }catch (Exception e){     System.out.println("格式输入错误"); } return 0;    }}

注意细节

  • 如果想要分割点号必须转义 split(“\\.”)

588库千库资源网