Tomcat 学习之 Servlet

目录

1 Servlet 介绍

2 创建一个 Servlet

3 web.xml 介绍(不涉及 filter 和 listener 标签)

3.1 display-name

3.2 welcome-file-list

3.3 servlet

3.4 session-config

3.5 error-page

3.6 context-param

4 ServletContext 

5 ServletConfig

6 HttpServletRequest

7 HttpServletResponse

8 Tomcat 如何根据 URL 定位到 Servlet

9 执行 Servlet

9.1 Servlet 接口(规范)

9.2 Servlet 生命周期

9.3 执行 init 初始化方法

9.4 执行 service 方法


最近学习 Servlet 的时候,不是那么认真,认为它已经过时了,可以不用学。直到学习 SpringMVC 看到 DispatcherServlet 的时候,才发现自己错了,JavaWeb 三大组件 (Servlet、Filter、Listener)值得学习。

1 Servlet 介绍

        互联网兴起之初,当时的 Sun 公司(后来被 Oracle 收购)已然看到了这次机遇,为了使 Java 进军 Web 编程领域,推出了 Applet 支持 Web 应用,但是效果并不如预想的那般美好,Applet 并没有给业界带来多大影响。之后,Sun 公司的大佬潜心专研,推出了 Servlet(Server Applet,全称 Java Servlet)实现动态网页。Tomcat 的前身为 Catalina,Catalina 是一个轻量级的 Servlet 容器,提供了运行 Servlet 的环境和服务。

       

上图是一个粗略的 Servlet 执行过程表示图,从 Servlet 容器(Tomcat)启动到运行 Servlet 的过程非常复杂,本文只介绍 Servlet 是如何使用的。那么 Servlet 是用来干什么的呢?

Servlet 主要用来处理客户端的请求并生成响应,分为以下几点:(来自 GPT)

  1. 接收和处理客户端的 HTTP 请求:Servlet 可以接收来自客户端的各种类型的 HTTP 请求,例如 GET、POST、PUT、DELETE 等,并根据请求的类型和参数生成相应的响应。

  2. 生成动态内容:Servlet 可以根据请求的参数和服务器端的数据生成动态的 HTML 页面、XML 文档、JSON 数据等响应内容,从而实现动态网页的效果。

  3. 处理表单数据:Servlet 可以接收和处理客户端提交的表单数据,例如用户注册、登录、查询等操作。

  4. 实现会话管理:Servlet 可以通过 HTTP 会话(Session)来跟踪和管理客户端与服务器之间的会话状态,例如存储用户登录信息、购物车信息等。

  5. 实现安全控制:Servlet 可以通过验证用户身份、授权访问权限等方式实现安全控制,保护服务器和客户端的数据安全。

  6. 与其他 Web 组件交互:Servlet 可以与其他 Web 组件(如 JSP、Filter、Listener 等)进行交互,实现复杂的 Web 应用程序。

2 创建一个 Servlet

创建一个 JavaWeb 工程

        创建过程请参考:IDEA 2023.2 配置 JavaWeb 工程-CSDN博客

导入 Servlet-api.jar 包

        Maven 中通过配置 pom.xml 导入

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

        非 Maven 导入 Servlet-api.jar

点击 File,再点击 Project Structrue

选择 Libraries,点击 + 号,选择 Java

找到 Tomcat 中 lib 目录下的 servlet-api.jar,点击 OK

先点击 Apply,再点击 OK

工程目录

在 src 目录下创建一个 com.test 包,在其中创建 TestServlet 类

package com.test;import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;public class TestServlet implements Servlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {// 接口 HttpServletRequest 实现 servletRequest 接口HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;String method = httpServletRequest.getMethod();// 获得请求方法if (method.equals("GET")) {this.doGet();} else if (method.equals("POST")) {this.doPost();}}public void doGet(){System.out.println("GET 请求");}public void doPost(){System.out.println("POST 请求");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}
}

修改 web.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!-- 配置 Servlet 程序 --><servlet><!-- 设置 Servlet 程序名称 --><servlet-name>TestServlet</servlet-name><!-- 设置 Servlet 程序所在路径(位置) --><servlet-class>com.test.TestServlet</servlet-class></servlet><!-- 设置 Servlet 映射--><servlet-mapping><!-- Servlet 程序名称 --><servlet-name>TestServlet</servlet-name><url-pattern>/test</url-pattern></servlet-mapping>
</web-app>

启动 Tomcat

哈哈,404 ,这时因为没有设置“首页文件”

输入 localhost:8080/servlettest/test 啥也没有

在 IDEA 中可以看到服务器已经收到了请求并响应了

在浏览器按 F12、刷新网页、查看网络,可以看到请求的消息,至此 Servlet 学习结束了

3 web.xml 介绍(不涉及 filter 和 listener 标签)

3.1 display-name

<display-name> 元素常用于配置 servlet、过滤器或其他 Web 组件的显示名称。这个显示名称主要用于在管理界面或日志中标识该组件,以方便识别和管理

     <!-- <display-name> 元素常用于配置 servlet、过滤器或其他 Web 组件的显示名称。这个显示名称主要用于在管理界面或日志中标识该组件,以方便识别和管理。 --><!-- 标识项目名 --><display-name>ServletTest</display-name>

3.2 welcome-file-list

welcome-file-list 用来定义首页文件,也就是用户直接输入域名时跳转的页面(如http://localhost:8080/)

        在 tomact 的 conf 目录下,web.xml 使用了该标签,所以我们在 web 目录下创建的 index.jsp 文件在 Tomcat 服务器启动时会被执行。此外,成功执行了第一个首页文件,后面的首页文件不会执行,如果没有定义首页文件,则显示 404

    <!-- 定义首页文件,也就是用户直接输入域名时跳转的页面(如http://localhost:8080/)--><welcome-file-list><welcome-file>index.jsp</welcome-file><welcome-file>test.jsp</welcome-file></welcome-file-list>

3.3 servlet

    <!-- 配置 Servlet 程序 --><servlet><!-- 放在第一句不会报错 --><display-name>TestServlet</display-name><!-- 设置 Servlet 程序名称 --><servlet-name>TestServlet</servlet-name><!-- 设置 Servlet 程序所在路径(位置) --><servlet-class>com.test.TestServlet</servlet-class><!-- 设置 Servlet 初始化参数可以通过 ServletConfig.getInitParamenter(String name) 方法访问初始化参数 --><init-param><param-name>driver</param-name><param-value>com.mysql.jdbc.Driver</param-value></init-param><init-param><param-name>url</param-name><param-value>jdbc:mysql://localhost:3306/study</param-value></init-param><init-param><param-name>username</param-name><param-value>root</param-value></init-param><init-param><param-name>passwd</param-name><param-value>123456</param-value></init-param><!-- load-on-startup 指定一个 servlet 的加载顺序当值为 0 或者大于 0 时,表示容器在应用启动时就加载这个 servlet当值是一个负数时或者没有指定时,表示容器在该 servlet 被选择时才加载正数的值越小,启动该servlet的优先级越高--><load-on-startup>1</load-on-startup><!--支持异步处理--><async-supported>true</async-supported></servlet>

补充:当服务器启动时,它会根据 <load-on-startup> 元素中指定的初始化参数来加载和初始化 Servlet。如果没有设置该元素,Servlet 通常在第一次被请求时才会被加载和初始化。

其中我觉得最重要的点是 url-pattern,地址映射、地址匹配、拦截请求

参考文档:tomcat关于配置servlet的url-pattern的问题详解 - sogeisetsu - 博客园 (cnblogs.com)

精确匹配(具体的某个文件)

如通过 http://localhost:8080/servlettest/img/2.jpg 访问工程 servlettest 中的 img 目录中的 2.jpg 图片,会使用 TestServlet 处理,不会正常访问该图片

    <!-- 设置 Servlet 映射--><servlet-mapping><!-- Servlet 程序名称 --><servlet-name>TestServlet</servlet-name><!-- 如访问 img 目录中的 2.jpg 图片 --><url-pattern>/img/2.jpg</url-pattern></servlet-mapping>

模糊匹配 *

使用 * 进行模糊匹配,表示 0 ~ n 个的任意字符

如果通过 http://localhost:8080/servlettest/img/5.jpg 访问该图片不会成功。。。

    <!-- 设置 Servlet 映射--><servlet-mapping><!-- Servlet 程序名称 --><servlet-name>TestServlet</servlet-name><url-pattern>/img/*</url-pattern><url-pattern>*.jpg</url-pattern></servlet-mapping>

默认匹配 /

何为默认匹配,是该路径得不到 “其他 Servlet” 的处理 ,最终会由 <url-pattern>/</url-pattern> 的 Servlet 处理, 如默认的 “default” Servlet 无奈接手 “其他 Servlet” 不处理的请求

访问 http://localhost:8080/servlettest/  ,“其他 Servlet” 不处理,“default Servlet” 会加载首页文件,如果没有文件,显示 “404” 

    <servlet-mapping><!-- Servlet 程序名称 --><servlet-name>TestServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping>

以下代码来自 Tomcat 中的 conf 目录下的 web.xml 文件,我们可以了解到 Tomcat 自定义了许多 Servlet 处理各种访问

    <!-- The mapping for the default servlet --><servlet-mapping><servlet-name>default</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- The mappings for the JSP servlet --><servlet-mapping><servlet-name>jsp</servlet-name><url-pattern>*.jsp</url-pattern><url-pattern>*.jspx</url-pattern></servlet-mapping>

3.4 session-config

设置 Session 超时时间,单位为分钟

    <!-- 设置 Session 超时时间,单位为分钟 --><session-config><session-timeout>30</session-timeout></session-config>

3.5 error-page

设置错误页,当 404 或 500 或 发生异常时可以跳转至指定页面,有三个子标签

  • <error-code></error-code>:用来设置错误码,例如 404, 500等
  • <exception-type></exception-type>:用来设置异常类型,例如 java.lang.NullPointerException(空指针异常)
  • <location></location>:用来设置跳转的错误页
    <!-- 设置错误页 --><error-page><error-code>404</error-code><location>/error_404.html</location></error-page><error-page><exception-type>java.lang.NullPointerException</exception-type><location>/error_null.html</location></error-page>

访问不存在的页面,跳转到错误页进行显示

Tomcat 会自动解析各种 xml 文件,这个过程。。。对于现在的我而言太复杂了

InputSource contextWebXml = this.getContextWebXmlSource();

3.6 context-param

context-param 用来设置上下文参数,可以被整个 Web 应用程序使用

<!--context-param 是上下文参数 (它属于整个 web 工程)-->
<context-param><param-name>username</param-name><param-value>root</param-value>
</context-param>
<!--context-param 是上下文参数 (它属于整个 web 工程)-->
<context-param><param-name>password</param-name><param-value>123456</param-value>
</context-param>

4 ServletContext 

        ServletContext 是 Servlet 编程中的一个重要接口,它提供了与整个 Web 应用程序相关的上下文信息和功能。每个 Web 应用程序只有一个 ServletContext 对象,通过这个对象,可以在应用程序中获取资源、管理应用程序的属性。此外,它可以被所有的 Servlet 和 Filter 共享

获取 ServletContext 对象方式如下:

  • 在 Servlet 中:可以在 Servlet 初始化时,通过 ServletConfig.getServletContext() 方法获取,也可以在自定义的类中通过以下方式获取:
// 1、通过 GenericServlet 提供的 getServletContext() 获取
ServletContext context1 = getServletContext();
// 2、通过 ServletConfig 提供的 getServletContext() 获取
ServletContext context2 = getServletConfig().getServletContext();
// 3、通过 HttpServletRequest 获取
ServletContext context3 = request.getServletContext();
// 4、通过 HttpSession 获取
ServletContext context4 = request.getSession().getServletContext();
  • 在 Filter 中:可以在 Filter 初始化时,通过 FilterConfig.getServletContext() 方法获取

主要方法:

  • setAttribute() 和 getAttribute():用于设置和获取 ServletContext 的属性
  • getResource() 和 getResourceAsStream():用于获取 Web 应用程序的资源,如文件、图像等
  • getRealPath():获取资源的真实路径
  • getRequestDispatcher()用于获取请求转发器,将请求转发到其他 Servlet 或 JSP 页面
  • log():用于记录日志信息

生命周期:

        ServletContext 在 Web 应用程序启动时创建,并在 Web 应用程序关闭时销毁,可以在整个应用程序的运行期间持续存在。

web.xml 文件

<!--context-param 是上下文参数 (它属于整个 web 工程)-->
<context-param><param-name>username</param-name><param-value>root</param-value>
</context-param>
<!--context-param 是上下文参数 (它属于整个 web 工程)-->
<context-param><param-name>password</param-name><param-value>123456</param-value>
</context-param>

TestServlet 调用 ServletContext  方法

package com.test;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class TestServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {System.out.println("GET 请求");// 获取工程的 ServletContext 对象// 1、通过 GenericServlet 提供的 getServletContext() 获取ServletContext context1 = getServletContext();// 2、通过 ServletConfig 提供的 getServletContext() 获取ServletContext context2 = getServletConfig().getServletContext();// 3、通过HttpServletRequest获取ServletContext context3 = request.getServletContext();// 4、通过HttpSession获取ServletContext context4 = request.getSession().getServletContext();// 1、获取 web.xml 中配置的上下文参数 context-paramString username = context1.getInitParameter("username");System.out.println("context-param 参数 username 的值是:" + username);System.out.println("context-param 参数 password 的值是:" + context2.getInitParameter("password"));// 2、获取当前的工程路径,格式: /工程路径System.out.println( "当前工程路径:" + context3.getContextPath() );// 3、获取工程部署后在服务器硬盘上的绝对路径// 斜杠 / 被服务器解析地址为:http://ip:port/工程名/  映射到IDEA代码的web目录<br/>System.out.println("工程部署的路径是:" + context4.getRealPath("/"));System.out.println("工程下 img 目录 2.jpg 的绝对路径是:" + context4.getRealPath("/img/2.jpg"));}
}

输出结果

5 ServletConfig

        ServletConfig 是 Servlet 的配置信息类,由 Tomcat 创建。通过 ServletConfig 对象,可以获取其配置信息,例如 Servlet 的名称、初始化参数、ServletContext 对象。

ServletConfig 提供的方法:

  • getServletName():返回 Servlet 的 servlet-name
  • getInitParameter():根据初始化参数的名称获取对应的参数值
  • getInitParameterNames():返回一个枚举,包含了所有初始化参数的名称
  • getServletContext():返回 Servlet 所属的 ServletContext 对象

web.xml 文件

<!-- 配置 Servlet 程序 -->
<servlet><!-- 设置 Servlet 程序名称 --><servlet-name>TestServlet</servlet-name><!-- 设置 Servlet 程序所在路径(位置) --><servlet-class>com.test.TestServlet</servlet-class><!-- 设置 Servlet 初始化参数可以通过 ServletConfig.getInitParamenter(String name) 方法访问初始化参数 --><init-param><param-name>username</param-name><param-value>root</param-value></init-param><init-param><param-name>password</param-name><param-value>123456</param-value></init-param>
</servlet><!-- 设置 Servlet 映射-->
<servlet-mapping><!-- Servlet 程序名称 --><servlet-name>TestServlet</servlet-name><url-pattern>/test</url-pattern>
</servlet-mapping>

TestServlet 调用 ServletConfig  方法

package com.test;import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;public class TestServlet implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init 初始化方法");// 1、可以获取 Servlet 程序的别名 servlet-name 的值System.out.println("TestServlet 程序的别名是:" + servletConfig.getServletName());// 2、获取初始化参数 init-paramSystem.out.println("初始化参数 username 的值是:" + servletConfig.getInitParameter("username"));System.out.println("初始化参数 password 的值是:" + servletConfig.getInitParameter("password"));// 3、获取初始化参数名称的枚举Enumeration<String> parameterNames = servletConfig.getInitParameterNames();// 遍历枚举,获取每个参数的名称和值while (parameterNames.hasMoreElements()) {String parameterName = parameterNames.nextElement();String parameterValue = servletConfig.getInitParameter(parameterName);// 打印参数名称和值System.out.println("参数名称: " + parameterName);System.out.println("参数值: " + parameterValue);}// 4、获取 ServletContext 对象System.out.println("ServletContext 对象是:" + servletConfig.getServletContext());}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}

输出结果

6 HttpServletRequest

        HttpServletRequest 用于处理 HTTP 请求时提供的请求信息。

主要提供以下方法:

  • 获取请求头信息
    • getHeader(String name):根据请求头名称获取对应的请求头值
    • getHeaders(String name):获取所有指定请求头名称的请求头值的枚举
  • 获取请求方法
    • getMethod():获取请求的方法(如 GET、POST 等)
  • 获取请求路径
    • getRequestURI():获取请求的统一资源标识符(URI)
    • getRequestURL():获取请求的完整 URL
  • 获取请求参数
    • getParameter(String name):根据参数名称获取对应的请求参数值
    • getParameterValues(String name):获取指定参数名称的所有参数值的枚举
  • 获取请求体内容
    • getInputStream():获取请求体的输入流,用于读取请求体的内容(适用于 POST 请求)
    • getReader():获取请求体的字符输入流,用于读取请求体的内容(适用于 POST 请求)
  • 设置、获取和移除请求属性
    • setAttribute(String name, Object value):设置请求属性
    • getAttribute(String name):获取请求属性的值
    • removeAttribute(String name):移除请求属性
  • 获取请求协议和服务器名称
    • getProtocol():获取请求使用的协议(如 HTTP/1.1)
    • getServerName():获取服务器的名称
  • 获取客户端信息
    • getRemoteAddr():获取发送请求的客户端的 IP 地址
    • getRemoteHost():获取发送请求的客户端的主机名

补充:参数和属性的区别

  • 来源不同:参数 (parameter) 是由客户端中提供的;属性 (attribute) 是服务器端的组件 (JSP 或 Servlet) 利用 requst.setAttribute() 方法设置的
  • 操作不同:参数 (parameter) 的值只能读取不能修改,可使用 request.getParameter() 方法读取; 属性 (attribute) 的值既可以读取亦可以修改,读取可使用 request.getAttribute() 方法,设置可使用 request.setAttribute() 方法
  • 数据类型不同:参数 (parameter) 不管客户端传来的数据是什么类型的语义,在服务器获取时都以 String 类型看待,并且客户端的参数值只能是简单类型的值,不能是复杂类型,比如一个对象。 而属性 (attribute) 的值可以是任意一个 Object 类型

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>登录</title></head><body><form action="http://localhost:8080/servlettest/loginServlet" method="get">用户名: <input type="text" name="username"/> <br>密 码: <input type="password" name="password"/> <br><input type="submit" /></form></body>
</html>

LoginServlet 类

package com.test;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;// 通过 @WebServlet 标签配置 Servlet
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {// 1、获得请求头信息String header = req.getHeader("User-Agent");System.out.println("请求头信息:" + header);// 2、获得请求方法String method = req.getMethod();System.out.println("请求方法:" + method);// 3、获得请求路径String uri = req.getRequestURI();String url = req.getRequestURL().toString();System.out.println("请求路径:" + uri);System.out.println("请求完整路径:" + url);// 4、获得请求参数String username = req.getParameter("username");String password = req.getParameter("password");System.out.println("请求参数 username:" + username);System.out.println("请求参数 password:" + password);// 5、设置、获取和移除请求属性req.setAttribute("test","test");Object str = req.getAttribute("test");System.out.println("请求属性:" + str);// 6、获得请求协议和服务器名称String protocol = req.getProtocol();String serverName = req.getServerName();System.out.println("请求协议:" + protocol);System.out.println("服务器名称:" + serverName);// 7、获得客户端信息String addr = req.getRemoteAddr();String host = req.getRemoteHost();System.out.println("客户端 IP:" + addr);System.out.println("客户端主机名:" + host);}
}

输出结果

7 HttpServletResponse

        HttpServletResponse 定义了服务器在处理 HTTP 请求时如何向客户端发送响应的方法。

主要方法有:

  • setStatus(int statusCode):设置响应的状态码。状态码是一个整数,表示请求处理的结果
    • 200 OK:表示请求成功,服务器已成功处理并返回了所请求的资源
    • 301 Moved Permanently:表示请求的资源已永久移动到新的 URL,客户端应该使用新的 URL 进行后续请求
    • 302 Found:表示请求的资源临时移动到新的 URL,客户端应该使用新的 URL 进行后续请求
    • 400 Bad Request:表示请求有错误,例如请求的语法错误或参数不正确
    • 401 Unauthorized:表示请求需要身份验证,客户端需要提供有效的凭证进行身份验证
    • 403 Forbidden:表示服务器拒绝了请求,可能是由于客户端没有权限访问请求的资源
    • 404 Not Found:表示服务器找不到请求的资源
    • 500 Internal Server Error:表示服务器内部发生了错误,无法处理请求
  • getStatus():获取响应的状态码
  • setContentType(String contentType):设置响应的内容类型。内容类型是一个字符串,例如 text/html 表示 HTML 文档,application/json 表示 JSON 数据等
  • getContentType():获取响应的内容类型
  • getOutputStream():获取响应的输出流,可以用于向客户端发送二进制数据,例如图像、文件等
  • getWriter():获取响应的字符输出流,可以用于向客户端发送文本数据,例如 HTML、XML 等
  • sendRedirect(String url):发送重定向响应,将客户端重定向到指定的 URL
  • addHeader(String name, String value):添加响应头信息。头信息是一个键值对,表示响应的元数据,例如 Content-Type、Content-Length 等

Tomcat 如何根据 URL 定位到 Servlet

参考自:java - Tomcat 架构原理解析到架构设计借鉴 - 个人文章 - SegmentFault 思否

以 http://user.shopping.com:8080/order/buy 为例,其中 http 为访问协议、user.shopping.com 为主机名、order 可认为是一个工程名、一个 Servlet 对应一个 Wrapper,buy 可认为是一个 Servlet 程序名称

  1. 首先根据协议和端口号确定 Service 和 Engine。Tomcat 默认的 HTTP 连接器监听 8080 端口、默认的 AJP 连接器监听 8009 端口。上面例子中的 URL 访问的是 8080 端口,因此这个请求会被 HTTP 连接器接收,而一个连接器是属于一个 Service 组件的,这样 Service 组件就确定了。我们还知道一个 Service 组件里除了有多个连接器,还有一个容器组件,具体来说就是一个 Engine 容器,因此 Service 确定了也就意味着 Engine 也确定了
  2. 根据域名选定 Host。 Service 和 Engine 确定后,Mapper 组件通过 URL 中的域名去查找相应的 Host 容器,比如例子中的 URL 访问的域名是 user.shopping.com,因此 Mapper 会找到 Host2 这个容器
  3. 根据 URL 路径找到 Context 组件。 Host 确定以后,Mapper 根据 URL 的路径来匹配相应的 Web 应用的路径,比如例子中访问的是 /order,因此找到了 Context4 这个 Context 容器
  4. 根据 URL 路径找到 Wrapper(Servlet)。 Context 确定后,Mapper 再根据 web.xml 中配置的 Servlet 映射路径来找到具体的 Wrapper 和 Servlet

补充,也可以是请求访问 http://user.shopping.com:8080/order/buy.html

9 执行 Servlet

参考文档:

透过现象看本质——什么是servlet_servlet go-CSDN博客

Java servlet执行的完整流程(图解含源码分析)_请简述 servlet 的工作流程?-CSDN博客Tomcat如何创建Servlet? Servlet的执行流程_tomcat先创建servlet还是先创建servletcontext-CSDN博客Java servlet执行的完整流程(图解含源码分析)_请简述 servlet 的工作流程?-CSDN博客

9.1 Servlet 接口(规范)

所有实现 Servlet 接口的类必须实现 init()、Service()、getServletConfig()、getServletInfo()、destroy() 方法

9.2 Servlet 生命周期

  • 执行 Servlet 构造器方法,创建 Servlet 时调用,只调用一次
  • 执行 init 初始化方法,创建 Servlet 时调用,只调用一次
  • 执行 service 方法,每次访问都会调用
  • 执行 destory 方法,JavaWeb 工程停止的时候调用

        服务器找到全类名后,会在缓存中查看是否存在该对象,不存在则通过反射创建对象,同时也创建了 ServletConfig 类,里面存放了一些初始化信息(注意服务器只会创建一次 Servlet 对象,所以 ServletConfig 也只有一个)

9.3 执行 init 初始化方法

原文的解释有点问题,通过代码来说明,根据多态动态绑定,执行 Servlet 子类重写的方法

// 反射创建 Servlet 对象
Servlet obj = Class.forName("全类名").newInstance();// ServletConfig config
//调用 init 方法初始化
obj.init(config);// ServletRequest req, ServletResponse resp
// 调用 Service 方法
obj.Service(req, resp);

9.4 执行 service 方法

        仓促抄完,大概就抄这么点,用的时候继承 HttpServlet ,重写 doGet 和 doPost 就好了,也可以通过注解 @WebServlet("/Servlet名称") 配置 Servlet 了,写了注解 @WebServlet,就不要在 web.xml 配置 Servlet,好像会冲突。。。

希望大佬多多指正!!!问题。。。我暂时还找不出来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/263756.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前后端分离vue.js+nodejs学生考勤请假系统 _fbo36

此系统设计主要采用的是nodejs语言来进行开发&#xff0c;采用vue框架技术&#xff0c;框架分为三层&#xff0c;分别是控制层Controller&#xff0c;业务处理层Service&#xff0c;持久层dao&#xff0c;能够采用多层次管理开发&#xff0c;对于各个模块设计制作有一定的安全性…

解决easyExcel模板填充时转义字符\{xxx\}失效

正常我们在使用easyExcel进行模板填充时&#xff0c;定义的变量会填充好对应的实际数据&#xff0c;未定义的变量会被清空&#xff0c;但是如果这个未定义的变量其实是模板的一部分&#xff0c;那么清空了就出错了。 在这张图里&#xff0c;上面的是模板填充后导出的文件&…

探索无限维度的奥秘:Hilbert空间

当我们提到空间&#xff0c;你可能会立即想到周遭的环境——三维世界&#xff0c;其中事物可以向上或向下、左或右、前或后移动。然而&#xff0c;在数学和物理学的世界里&#xff0c;有一种抽象的空间概念&#xff0c;它不仅覆盖了我们的三维空间&#xff0c;还包括了更复杂的…

【Java程序设计】【C00313】基于Springboot的物业管理系统(有论文)

基于Springboot的物业管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的物业管理系统&#xff0c;本系统有管理员、物业、业主以及维修员四种角色权限&#xff1b; 管理员进入主页面&#xff0c;主要功能包…

MATLAB 导出可编辑的eps格式图像

任务描述&#xff1a;部分期刊要求提交可编辑的eps格式图像&#xff0c;方便美工编辑对图像进行美化 我试了直接print或者在figure窗口导出&#xff0c;发现导出的文件放到Adobe AI中并不能编辑&#xff0c;经Google找到解决办法&#xff1a; %EPS exportgraphics(gcf,myVect…

jQuery瀑布流画廊,瀑布流动态加载

jQuery瀑布流画廊&#xff0c;瀑布流动态加载 效果展示 手机布局 jQuery瀑布流动态加载 HTML代码片段 <!-- mediabanner --><div class"mediabanner"><img src"img/mediabanner.jpg" class"bg"/><div class"text&qu…

【数据结构】图——最短路径

最短路径问题&#xff1a;从在带权有向图G中的某一顶点出发&#xff0c;找出一条通往另一顶点的最短路径&#xff0c;最短也就是沿路径各边的权值总和达到最小。 最短路径分为图中单源路径和多源路径。 本文会介绍Dijkstra和Bellman-Ford解决单源路径的问题 Floyd-Warshall解…

iMazing2024Windows和Mac的iOS设备管理软件(可以替代iTunes进行数据备份和管理)

iMazing2024是一款兼容 Windows 和 Mac 的 iOS 设备管理软件&#xff0c;可以替代 iTunes 进行数据备份和管理。以下是一些 iMazing 的主要功能和优点&#xff1a; 数据备份和恢复&#xff1a;iMazing 提供了强大的数据备份和恢复功能&#xff0c;可以备份 iOS 设备上的各种数据…

基于EasyCVR视频汇聚系统的公安网视频联网共享视频云平台建设思路分析(一)

随着社会的发展和科技的进步&#xff0c;视频监控系统在各个领域的应用越来越广泛&#xff0c;视频云平台建设已经成为了行业数字化转型的重要一环。公安网视频汇聚联网共享云的建设需要充分考虑技术、架构、安全、存储、计算等多方面因素&#xff0c;以确保平台的稳定性和可用…

[面试] 什么是死锁? 如何解决死锁?

什么是死锁 死锁&#xff0c;简单来说就是两个或者多个的线程在执行的过程中&#xff0c;争夺同一个共享资源造成的相互等待的现象。如果没有外部干预线程会一直阻塞下去. 导致死锁的原因 互斥条件&#xff0c;共享资源 X 和 Y 只能被一个线程占用; 请求和保持条件&#xf…

从Unity到Three.js(outline 模型描边功能)

指定模型高亮功能&#xff0c;附带设置背景颜色&#xff0c;获取随机数方法。 百度查看说是gltf格式的模型可以携带PBR材质信息&#xff0c;如果可以这样&#xff0c;那就完全可以在blender中配置好材质导出了&#xff0c;也就不需要像在unity中调整参数了。 import * as THRE…

说一下 JVM 有哪些垃圾回收算法?

一、标记-清除算法 标记无用对象&#xff0c;然后进行清除回收。 标记-清除算法&#xff08;Mark-Sweep&#xff09;是一种常见的基础垃圾收集算法&#xff0c;它将垃圾收集分为两个阶段&#xff1a; 标记阶段&#xff1a;标记出可以回收的对象。清除阶段&#xff1a;回收被标…

9.5K Star,又一款超棒开源轻量自动化运维平台

Hi&#xff0c;骚年&#xff0c;我是大 G&#xff0c;公众号「GitHub指北」会推荐 GitHub 上有趣有用的项目&#xff0c;一分钟 get 一个优秀的开源项目&#xff0c;挖掘开源的价值&#xff0c;欢迎关注。 一个好的运维平台就变得非常重要了&#xff0c;可以节省大量的人力和物…

网络原理 HTTP _ HTTPS

回顾 我们前面介绍了HTTP协议的请求和响应的基本结构 请求报文是由首行请求头空行正文来组成的 响应报文是由首行形影头空行响应正文组成的 我们也介绍了一定的请求头之中的键值对的属性 Host,Content-type,Content-length,User-agent,Referer,Cookie HTTP协议中的状态码 我们先…

流式存储音频/视频

目录 流式存储音频/视频 1.1 具有元文件的万维网服务器 1.2 媒体服务器 1.3 实时流式协议 RTSP 使用 RTSP 的媒体服务器的工作过程 流式存储音频/视频 “存储”音频/视频文件不是实时产生的&#xff0c;而是已经录制好的&#xff0c;通常存储在光盘或硬盘中。 传统浏览器…

以程序员的视角,看前后端分离的是否必要?

Hello&#xff0c;我是贝格前端工场&#xff0c;本篇分享一个老生常谈的话题&#xff0c;前后端分离是必然趋势&#xff0c;但也是要区分具体的场景&#xff0c;欢迎探讨&#xff0c;关注&#xff0c;有前端开发需求可以私信我&#xff0c;上车了。 一、什么是前后端分离和不分…

C# OpenCvSharp DNN Image Retouching

目录 介绍 模型 项目 效果 代码 下载 C# OpenCvSharp DNN Image Retouching 介绍 github地址&#xff1a;https://github.com/hejingwenhejingwen/CSRNet (ECCV 2020) Conditional Sequential Modulation for Efficient Global Image Retouching 模型 Model Properti…

css中选择器的优先级

CSS 的优先级是由选择器的特指度&#xff08;Specificity&#xff09;和重要性&#xff08;Importance&#xff09;决定的&#xff0c;以下是优先级规则&#xff1a; 特指度&#xff1a; ID 选择器 (#id): 每个ID选择器计为100。 类选择器 (.class)、属性选择器 ([attr]) 和伪…

C语言每日一题(61)盛最多水的容器

题目链接 力扣 11 盛最多水的容器 题目描述 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水…

jenkins远程触发构建报:Error 403 No valid crumb was included in the request

最近在跨jenkins触发构建的时候发现不能触发相应的项目&#xff0c;报如下图错误 解决方案&#xff1a; 1、安装Build Authorization Token Root Plugin插件 安装完成后去配置API Token&#xff0c;用户列表&#xff0c;配置用户的API Token&#xff0c;生成后记得保存 2、项…