三天急速通关JavaWeb基础知识:Day 1 后端基础知识
- 0 文章说明
- 1 Http
- 1.1 介绍
- 1.2 通信过程
- 1.3 报文 Message
- 1.3.1 请求报文 Request Message
- 1.3.2 响应报文 Response Message
- 2 XML
- 2.1 介绍
- 2.2 利用Java解析XML
- 3 Tomcat
- 3.1 介绍
- 3.2 Tomcat的安装与配置
- 3.3 Tomcat的项目目录介绍
- 3.4 Tomcat的JavaWeb项目的标准结构
- 3.5 部署Web项目的三种方式
- 3.5 Tomcat关联IDEA
- 4 Servlet
- 4.1 介绍
- 4.2 Servelet的生命周期
- 4.2 Servelet的继承结构
- 4.3 自定义Servelet
- 4.4 ServletConfig
- 4.5 ServletContext
- 4.6 HttpServletRequest
- 4.6 HttpServletResponse
- 4.7 请求转发
- 4.8 响应重定向
- 5 Cookie 和Session
- 5.1 Cookie
- 5.2 Session
- 6 Filter
- 6.1 介绍
- 6.2 Filter生命周期
- 6.3 Tomcat对Filter接口的实现
- 7 Listener
- 6.1 介绍
- 6.2 监听器分类
- 6.3 监听器实现原理
0 文章说明
学习完Java基础知识,有一定前端基础,三天急速通关尚硅谷的JavaWeb教程,整理知识体系框架,并用Kimi,DeepSeek,Copliot辅助学习,第一天整理后端相关概念。本文所提供的信息和内容仅供参考,作者和发布者不保证其准确性和完整性。
1 Http
1.1 介绍
超文本传输协议(HyperText Transfer Protocol
,HTTP
)是一个于应用层面向对象的协议,详细规定了浏览器和万维网服务器之间的通信规则,下面是不同Http
版本的对比。
版本号 | 发布时间 | 主要特点 | 支持的连接方式 | 典型应用场景 |
---|---|---|---|---|
HTTP/0.9 | 1991年 | 最简单的请求/响应模型,仅支持GET 方法 | 简单的请求/响应 | 静态网页浏览 |
HTTP/1.0 | 1996年 | 引入了请求方法的扩展,如POST 、HEAD 等 | 每次请求建立新连接 | 动态网页、表单提交 |
HTTP/1.1 | 1997年 | 支持持久连接、管道化请求、内容编码等 | 持久连接、管道化 | 复杂网页、多媒体内容 |
HTTP/2 | 2015年 | 二进制分帧、头部压缩、多路复用等 | 多路复用、头部压缩 | 高性能网页、移动应用 |
HTTP/3 | 2020年 | 基于QUIC 协议,进一步优化性能 | QUIC 协议、更低延迟 | 实时通信、游戏、视频流 |
1.2 通信过程
客户端和服务器之间的通信:客户端建立连接,通过TCP/IP协议
与服务器建立连接。默认情况下,HTTP
使用端口80,HTTPS
使用端口443。客户端发送请求,发送Http
请求报文,服务器响应请求,处理完客户端发来的请求报文之后生成响应报文发送给客户端,服务器关闭连接,HTTP/1.0
,每次请求/响应完成后,连接会自动关闭,HTTP/1.1
,支持持久连接(Keep-Alive
),可以在多个请求/响应之间复用同一个连接。
1.3 报文 Message
HTTP报文是HTTP协议中用于客户端和服务器之间通信的数据格式,一般分为:报文首部,空行,报文主体三个部分,其中报文首部分为报文行和报文头。
1.3.1 请求报文 Request Message
HTTP
的请求报文一般分为:请求行,请求头,空行,请求体:
部分 | 内容 | 示例 |
---|---|---|
请求行 | 请求方法、请求的URL 和HTTP 版本 | GET /index.html HTTP/1.1 |
请求头 | 包含一些元数据,用于描述请求的附加信息 | Host: www.example.com User-Agent: Mozilla/5.0 Accept: text/html |
空行 | 请求头和请求体之间的一个空行,表示请求头的结束 | CR 回车符 + LR 换行符 |
请求体(有些请求,如POST 才有) | 包含要发送给服务器的数据,如表单数据、文件内容等 | name=John&age=30 |
1.3.2 响应报文 Response Message
HTTP
的响应报文一般分为:响应行,响应头,空行,响应体:
部分 | 内容 | 示例 |
---|---|---|
响应行 | HTTP 版本、状态码和状态消息 | HTTP/1.1 200 OK |
响应头 | 描述响应的元数据 | Content-Type: text/html Content-Length: 1234 |
空行 | 响应头和响应体之间的分隔 | CR 回车符 + LR 换行符 |
响应体 | 服务器返回的数据 | <html><body><h1>Hello, World!</h1></body></html> |
2 XML
2.1 介绍
可扩展标记语言(eXtensible Markup Language
,XML
),是一种用于标记电子文档的简单、灵活的文本格式,广泛应用于数据交换、配置文件、文档存储等领域。后续的学习中一般用作配置文件。
- 示例
<?xml version="1.0" encoding="UTF-8"?> <library><book id="1"><title>XML for Beginners</title><author>John Doe</author><year>2022</year><price>29.99</price></book> </library>
- 其他类型的配置文件
类型 | 扩展名 | 格式 | 示例 | 说明 |
---|---|---|---|---|
INI | .ini | 键值对 | [section1] key1=value1 key2=value2 | 键值对格式,常用于Windows应用程序的配置文件。 |
JSON | .json | JSON对象 | { "key1": "value1", "key2": "value2" } | 轻量级的数据交换格式,易于阅读和编写,也易于机器解析和生成。 |
XML | .xml | XML元素 | <root> <element1>value1</element1> <element2>value2</element2> </root> | 结构化数据,常用于配置文件和数据交换。 |
YAML | .yaml | 键值对 | key1: value1 key2: value2 | 人类可读的数据序列化格式,常用于配置文件和数据交换,SpringBoot |
properties | .properties | 键值对 | key1=value1 key2=value2 | 键值对格式,常用于Java应用程序的配置文件。 |
2.2 利用Java解析XML
Java
中目前有以下几种方式解析XML
:
方式 | 简要介绍 | 适用场景 |
---|---|---|
DOM解析 | 将整个XML 文档加载到内存中,形成一个树状的文档对象模型,便于随机访问和修改。 | 适合小型XML 文件,需要随机访问和修改的场景。 |
SAX解析 | 事件驱动的解析方式,逐行读取XML 文件。 | 适合大型XML 文件,内存占用小,逐行处理的场景。 |
JAXB | 将XML 文档映射到Java 对象。 | 适合将XML 映射到Java 对象,便于操作和处理的场景。 |
StAX | 基于流的解析方式,逐个读取XML 文档的事件。 | 适合处理大型XML 文件,基于流的解析方式。 |
DOM4J | 结合了DOM 和SAX 的优点,便于操作和处理XML 文档。 | 适合需要结合DOM 和SAX 优点的场景,便于操作和处理XML 文档。 |
利用DOM4J
解析XML
示例:
<?xml version="1.0" encoding="UTF-8"?>
<library><book id="1"><title>XML for Beginners</title><author>John Doe</author><year>2022</year><price>29.99</price></book><book id="2"><title>Advanced XML Techniques</title><author>Jane Smith</author><year>2023</year><price>39.99</price></book>
</library>
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import java.util.List;public class DOM4JExample {public static void main(String[] args) {try {// 创建SAXReader对象SAXReader reader = new SAXReader();// 读取XML文件Document document = reader.read("example.xml");// 获取根元素Element root = document.getRootElement();// 遍历所有book元素for (Element book : (List<Element>) root.elements("book")) {// 获取book元素的属性String id = book.attributeValue("id");// 获取book元素的子元素String title = book.elementText("title");String author = book.elementText("author");String year = book.elementText("year");String price = book.elementText("price");// 打印信息System.out.println("Book ID: " + id);System.out.println("Title: " + title);System.out.println("Author: " + author);System.out.println("Year: " + year);System.out.println("Price: " + price);System.out.println();}} catch (DocumentException e) {e.printStackTrace();}}
}
3 Tomcat
3.1 介绍
Apache Tomcat
是一个开源的Java Servlet
容器,提供了运行Java Web
应用程序所需的环境。也可以作为独立的Web
服务器使用,支持HTTP/1.1
、HTTP/2
、WebSocket
等多种协议。Tomcat
的定位:客户端的硬件机器上运行着操作系统(如Windows
),其中的应用程序(如浏览器)发送请求给服务端,服务端的硬件机器上运行的操作系统(如Linux
),其中的服务器软件(如Tomcat
)运行的各种App
处理请求并响应。
3.2 Tomcat的安装与配置
- 下载
Tomcat10.1.x
的64位Windows
版(JDK1.8
得切换到更高版本,我用的JDK17
与Tomcat10.1.34
) - 检查好
JAVA_HOME
环境变量 - 启动
bin/startup.bat
- 访问
http://localhost:8080/
3.3 Tomcat的项目目录介绍
bin
目录:包含启动和停止Tomcat的脚本文件。startup.sh
和startup.bat
:启动Tomcat的脚本。shutdown.sh
和shutdown.bat
:停止Tomcat的脚本。catalina.sh
和catalina.bat
:Tomcat的核心启动脚本,其他脚本通常会调用这个脚本。
conf
目录:包含Tomcat的配置文件。server.xml
:Tomcat的主要配置文件,定义了服务器的全局设置,如端口号、连接器、服务等。web.xml
:定义了Web应用程序的全局设置,如Servlet映射、过滤器等。context.xml
:定义了上下文的配置,如资源链接、初始化参数等。logging.properties
:定义了日志记录的配置。
lib
目录:包含Tomcat运行所需的JAR文件。- 各种支持Tomcat运行的库文件,如
catalina.jar
、servlet-api.jar
等。
- 各种支持Tomcat运行的库文件,如
logs
目录:包含Tomcat运行时生成的日志文件。catalina.out
:Tomcat的标准输出和标准错误日志。localhost.[date].log
:每个Web应用程序的日志文件。manager.[date].log
和host-manager.[date].log
:管理器和主机管理器的日志文件。
webapps
目录:包含部署的Web应用程序。
每个Web应用程序都有一个独立的目录。work
目录:包含Tomcat编译后的JSP文件和临时文件。- 编译后的JSP文件和临时文件,通常在Tomcat启动时自动生成。
temp
目录:包含Tomcat运行时的临时文件。- 各种临时文件,通常在Tomcat停止时被清理。
3.4 Tomcat的JavaWeb项目的标准结构
app
:本应用根目录static
:非必要目录,存放静态资源(css, js, img)WEB-INF
:必要目录,受保护的资源目录,不可通过URL直接访问classes
:必要目录,存放编译后的Java源码和配置文件lib
:必要目录,存放项目依赖的JAR文件web.xml
:必要文件,Web项目的基本配置文件
index.html
:非必要文件,作为默认欢迎页
3.5 部署Web项目的三种方式
- 直接将编译好的项目放到
webapps
目录下 war
包放到webapps
目录下tomcat
的conf
下创建Catalina/localhost/
创建一个app.xml
<!--path: 项目的访问路径,也是项目的上下文路径,就是在浏览器中,输入的项目名称 docBase: 项目在磁盘中的实际路径 --> <Context path="/app" docBase="D:/mywebapps/app" />
3.5 Tomcat关联IDEA
- 关联IDEA
需要IntelliJ IDEA Ultimate
版本,社区版不支持直接应用服务器
File
->Settings
->Build, Execution, Deployment
->Application Servers
->点击+
按钮,选择Tomcat Server
-> 指定Tomcat
的安装路径。 - 创建Web工程
创建Empty Project
-> 添加模块 -> 右键模块,选择Open Module Settings
-> 点击Project Settings
的Modules
-> 右键刚刚创建的模块 -> 选择Add
,再选择Web
-> 替换index.jsp
为index.html
。 - 部署运行
点击同创建Web工程Project Settings
的Artifacts
,检查发布结构是为Web
项目,即模块名
:war exploded
-> 点击运行按钮的下三角符号,在下拉框中选择Edit Configurations
-> 添加Tomcat
的Local
-> 右侧界面点击Deployment
-> 添加Artifacts
-> 确定并回到主界面点击运行。
- 资源路径和Jar包路径的设置
注意新版没有Add as Dependency
选项,得进入到模块管理手动添加。
4 Servlet
4.1 介绍
Servlet
(Serve Applet
) 是一种运行在服务器端的 Java
程序。在Web
应用中,Servlet
主要负接收、处理请求、协同调度功能以及响应数据,即控制器Controller
,是Java
中专门设计的一套接口来处理客户端请求。
- 通过
pom.xml
配置路径映射:
继承HttpServlet类并重写service方法(参数是带Http前缀的),在pom.xml配置请求的映射路径之后就能访问。package com.cut.basic;import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/*** description: Servlet基本逻辑* author: tang* package: com.cut.basic* 2025/1/28 11:41*/ public class ServletBasicDemo extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String flag = req.getParameter("pleaseCallMe");resp.getWriter().print("<h1>" + flag + "</h1>");} }
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"version="6.0"><servlet><servlet-name>servletBasicDemo</servlet-name><servlet-class>com.cut.basic.ServletBasicDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletBasicDemo</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping> </web-app>
- 通过
Servlet
的@WebServlet
注解配置路径映射:
注意这里如果Servlet
和XML
同名的话会被覆盖,同时,这里的InitParams
属于这个Servlet
而不是req
。注解的具体用法看源码即可,自己写一遍就会了。package com.cut.basic;import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebInitParam; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/*** description: Servlet基本逻辑* author: tang* package: com.cut.basic* 2025/1/28 11:41*/ @WebServlet(name = "servletBasicDemo",urlPatterns = {"/hello_annotation"},initParams = {@WebInitParam(name = "initParams", value = "It belongs to servelet, not req")} ) public class ServletBasicDemo extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String flag = getServletConfig().getInitParameter("initParams");resp.getWriter().print("<h1>" + flag + "</h1>");} }
4.2 Servelet的生命周期
生命周期就是对象在容器中从开始到销毁的过程,Servlet
对象是Servlet
容器创建的,生命周期方法是由容器(目前是Tomcat
)调用。
阶段 | 方法 | 描述 |
---|---|---|
加载和实例化 | - | Servlet容器加载Servlet类并创建其实例。默认情况下,第一次请求时创建实例,可通过loadOnStartup 配置在服务器启动时创建。 |
初始化 | init() | 容器调用init() 方法初始化Servlet,执行一次,用于加载配置文件、创建连接等初始化工作。 |
请求处理 | service() | 每次请求时,容器调用service() 方法处理请求,根据请求类型调用doGet() 或doPost() 等方法。 |
服务终止 | destroy() | 容器关闭或释放资源时,调用destroy() 方法清理资源,如关闭数据库连接等。 |
package com.cut.basic;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/*** description: Servlet容器声明周期自动调用时机测试* author: tang* package: com.cut.basic* 2025/1/28 11:41*/
@WebServlet(name = "servletLifeCycleDemo",urlPatterns = {"/hello"},// 配置的是正整数则表示容器在启动时就要实例化Servlet, 数字表示的是 实例化的顺序loadOnStartup = 6
)
public class ServletLifeCycleDemo extends HttpServlet {public static int time = 0;public ServletLifeCycleDemo() {System.out.printf("time: %d\tconstructor method\n".formatted(time++));}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.printf("time: %d\tservice method\n".formatted(time++));}@Overridepublic void destroy() {System.out.printf("time: %d\tdestroy method\n".formatted(time++));}@Overridepublic void init() throws ServletException {System.out.printf("time: %d\tinit method\n".formatted(time++));}
}
- 注意事项:
Servlet
对象是单例;每个请求都会在容器中开启一个线程,所以除了特殊目的,不要像上面的代码一样定义个time
;loadOnStartup
的数字1-5
被容器占用,尽量不要占用。
4.2 Servelet的继承结构
-
Servlet 规范接口,所有的Servlet必须实现
void init(ServletConfig config) throws ServletException;
- 初始化方法,容器在构造
Servlet
对象后自动调用,容器实例化一个ServletConfig
对象,并在调用该方法时传入,ServletConfig
对象可以为Servlet
提供初始化参数。
- 初始化方法,容器在构造
ServletConfig getServletConfig();
- 获取
ServletConfig
对象,可以通过该对象获取Servlet
初始化参数。
- 获取
void service(ServletRequest req, ServletResponse res);
- 处理请求并做出响应的服务方法,每次请求产生时由容器调用。
- 容器创建一个
ServletRequest
对象和ServletResponse
对象,容器在调用service
方法时,传入这两个对象。
String getServletInfo();
- 获取
ServletInfo
信息的方法。
- 获取
void destroy();
Servlet
实例在销毁之前调用的方法。
-
GenericServlet抽象类对Servlet接口一些固定功能的粗糙实现,以及对service方法的再次抽象声明,并定义了一些其他相关功能方法。
方法签名 描述 transient ServletConfig config;
初始化配置对象作为属性。 GenericServlet()
构造器 void destroy()
销毁方法的平庸实现。 String getInitParameter(String name)
获取初始参数。 Enumeration getInitParameterNames()
返回所有初始化参数名。 ServletConfig getServletConfig()
获取初始Servlet初始配置对象ServletConfig。 ServletContext getServletContext()
获取上下文对象ServletContext。 String getServletInfo()
获取Servlet信息的平庸实现。 void init(ServletConfig config)
初始化方法的实现,并在此调用了init的重载方法。 void init()
重载init方法,为了让我们自己定义初始化功能的方法。 void log(String msg)
打印日志的方法。 void log(String message, Throwable t)
打印日志的方法及重载。 abstract void service(ServletRequest req, ServletResponse res)
服务方法。 String getServletName()
获取ServletName的方法。 -
HttpServlet抽象类继承GenericServlet,除了基本的实现以外,增加了更多的基础功能。
方法签名 描述 HttpServlet()
构造器,用于处理继承。 void service(ServletRequest req, ServletResponse res)
对服务方法的实现。在该方法中,将请求和响应对象转换成对应HTTP协议的HttpServletRequest和HttpServletResponse对象,并调用重载的service方法。 void service(HttpServletRequest req, HttpServletResponse res)
重载的service方法,被重写的service方法所调用。在该方法中,通过请求方式判断,调用具体的do***方法完成请求的处理。 void doGet(HttpServletRequest req, HttpServletResponse resp)
对应GET请求的处理方法,DO系列省略。
4.3 自定义Servelet
来源于尚硅谷教程两种自定义的方式截图,非常清晰。
4.4 ServletConfig
ServletConfig
是 Java Servlet API
中的一个接口,它代表一个 Servlet
的配置信息。该接口定义了获取 Servlet
初始化参数和 Servlet
上下文的方法。
package jakarta.servlet;import java.util.Enumeration;public interface ServletConfig {// 获取Servlet名称String getServletName();// 获取Servlet上下文,ServletContext getServletContext();// 获取初始化参数String getInitParameter(String var1);// 获取所有初始化参数名Enumeration<String> getInitParameterNames();
}
4.5 ServletContext
ServletContext
是 Java Servlet API
中的一个接口,代表了 Servlet
的上下文环境。它提供了一种机制,使得运行在同一个 Web
应用程序中的不同 Servlet
之间可以共享数据和资源。
简而言之,这个Servlet
需要用到另一个Servlet
的时候需要用ServletContext
传话。
-
ServletContext
接口内置几十个方法,下面列举一些常见方法- 获取初始参数
方法名 描述 String getInitParameter(String name)
获取指定名称的上下文初始化参数的值。 Enumeration<String> getInitParameterNames()
获取所有上下文初始化参数的名称。 - 获取资源的磁盘路径:假设
Web
应用部署在Tomcat
的webapps
目录下,应用名为myapp
,那么/WEB-INF/config.xml
的实际路径可能是:/path/to/tomcat/webapps/myapp/WEB-INF/config.xml
方法名 描述 String getRealPath(String path)
将项目路径转换为实际的磁盘路径。 - 获取项目上下文路径:
URL
是http://localhost:8080/myapp/somePage
,getContextPath()
会返回/myapp
方法名 描述 String getContextPath()
获取项目上下文路径,动态变化的 - 应用域相关的
方法名 描述 Object getAttribute(String name)
获取指定名称的上下文属性值。 Enumeration<String> getAttributeNames()
获取所有上下文属性的名称。 void setAttribute(String name, Object value)
设置上下文属性的值。 void removeAttribute(String name)
移除指定名称的上下文属性。
4.6 HttpServletRequest
Tomcat
将请求报文封装成HttpServletRequest
对象,在调用service
方法的时候传入该对象,能从中获得所有请求信息。请求报文有哪些属性,就有哪些常用方法,以get
系为主,具体可以看源码,不再示例。
4.6 HttpServletResponse
Tomcat
在调用service
方法的时候传入HttpServletResponse
对象,设置完里面的响应报文相关属性之后,Tomcat
再将其转换为响应报文返回。常见方法以set
系为主,不再示例。
4.7 请求转发
- 定义:
请求转发(Request Forwarding
)是服务器端将一个请求从一个Servlet
转发到另一个Servlet
或其他资源的操作。 - 特点:
- 通过
HttpServletRequest
对象获取请求转发器实现 - 服务器内部实现,客户端不知道,访问地址不变
- 只产生一对请求和响应对象,请求参数可以传递,对象也会传递到下一个
Servlet
动态资源或者WEB-INF
下受保护的静态资源,无法转发至项目之外的其他资源。
- 通过
- 示例:
package com.cut.basic;import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/*** description: 请求转发Demo示例* author: tang* package: com.cut.basic* 2025/1/28 11:41*/ @WebServlet(name = "requestForwardingDemo",urlPatterns = {"/requestForwarding"} ) public class RequestForwardingDemo extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {RequestDispatcher dispatcher;// Type 1: 请求转发给另一个Servletdispatcher = req.getRequestDispatcher("forwardDestination");req.setAttribute("requestForwardingParams","I'll be back!");// Type 2: 请求转发给WEB-INF下的静态资源(HTML等资源)// dispatcher = req.getRequestDispatcher("WEB-INF/protected.html");// Type 3: 请求转发给外部资源,不可行// dispatcher = req.getRequestDispatcher("www.baidu.com");dispatcher.forward(req, resp);} }
package com.cut.basic;import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/*** description: 请求转发的目的地* author: tang* package: com.cut.basic* 2025/1/28 11:41*/ @WebServlet(name = "forwardDestination",urlPatterns = {"/forwardDestination"} ) public class ForwardDestination extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String requestForwardingParams = (String) req.getAttribute("requestForwardingParams");resp.getWriter().write(requestForwardingParams);} }
4.8 响应重定向
- 定义:响应重定向(
Response Redirect
)是一种服务器端的操作,用于将客户端的请求重定向到另一个URL
。 - 特点:
- 通过
HttpResponse
对象的sendRedirect
方法实现。 - 服务端通过
302
响应码告诉客户端,期间不止一对请求和响应对象, 客户端的地址也会产生变化。 - 相较于请求转发,响应重定向可以重定向到外部资源,但是不能访问
WEB-INF
下受保护的资源。
- 通过
- 示例:
略,自己测,就一个sendRedirect
方法。
5 Cookie 和Session
5.1 Cookie
- 定义:
Cookie 是一种存储在客户端(通常是浏览器)的小型文本文件,用于跟踪用户在网站上的活动或保存用户信息。 - 特点:
- 服务端创建
Cookie
,添加属性后作为响应头的set-cookie
属性放入到响应对象中,Tomcat
返回给客户端,客户端收到Cookie
之后,下次访问这个服务的时候会带上这些信息,Cookie
一般不保存敏感信息。 - 如果
Cookie
对象调用了setMaxAge(time)
方法,那么浏览器关闭不会销毁Cookie
,而是会在客户端本地保存time秒。 - 如果
Cookie
对象调用了setPath(src)
方法,那么客户端在访问该src
的时候才会带上这个Cookie
对象。
- 服务端创建
5.2 Session
- 定义:
Session
是一种用于在服务器端跟踪用户会话的技术。它允许服务器在多个请求之间保持用户的状态- 信息。每个用户在访问网站时都会被分配一个唯一的会话标识(Session ID
),服务器通过这个标识来识别用户的会话。 - 特点:
- 服务端在为客户端创建
Session
的时候会将Session
对象的ID
即JSESSIONID
以Cookie
的方式响应给客户端,在后续访问中客户端会携带这个Cookie
。 - 调用
getSession()
的时候,如果客户端带了ID
那么服务端会检查自己有没有,如果没有则创建,如果客户端没带也会创建。不调用是不会创建的,自己动手试试 - 可以调用
setMaxInactiveInterval(time)
设置Session的有效时间为time
分钟,invalidate()
方法可以销毁Session。
- 服务端在为客户端创建
6 Filter
6.1 介绍
过滤器(Filter) 是 Java Servlet 规范中定义的一种服务器端组件,用于在请求到达 Servlet 之前或响应返回客户端之前对请求和响应进行拦截和处理。与Servlet类似,定义自己的Filter类继承Filter接口并重写doFilter方法。
- Filter接口的几个方法
方法名 | 描述 |
---|---|
void init(FilterConfig filterConfig) | 初始化过滤器,由容器在加载过滤器时调用一次。filterConfig 提供了过滤器的初始化参数和上下文信息。 |
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | 每次请求到达时调用,用于对请求和响应进行处理。可以对请求进行预处理,调用 chain.doFilter(request, response) 将请求传递给下一个过滤器或目标资源,也可以对响应进行后处理。 |
void destroy() | 在过滤器被卸载时调用,用于释放过滤器占用的资源。 |
- 简单示例
package com.cut.basic;import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/*** description: 测试过滤器* author: tang* package: com.cut.basic* 2025/1/29*/ @WebFilter(urlPatterns = {"/hello_annotation"} ) public class FilterDemo implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 父转子得要求该对象确实指向子,这里是可以满足的HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;long t1 = System.currentTimeMillis();filterChain.doFilter(servletRequest, servletResponse);long t2 = System.currentTimeMillis();String redirectInfo = "request " + httpServletRequest.getContextPath() + " use time:" + (t2 - t1) + "ms";try {Thread.sleep(5000);System.out.println(redirectInfo);httpServletResponse.sendRedirect("index.html");} catch (InterruptedException e) {throw new RuntimeException(e);}} }
6.2 Filter生命周期
阶段 | 对应方法 | 执行时机 | 执行次数 |
---|---|---|---|
创建对象 | 构造器 | web应用启动时 | 1 |
初始化方法 | void init(FilterConfig filterConfig) | 构造完毕 | 1 |
过滤请求 | void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) | 每次请求 | 多次 |
销毁 | default void destroy() | web应用关闭时 | 1次 |
6.3 Tomcat对Filter接口的实现
在 Tomcat
中,doFilter
方法传入的 FilterChain
对象是由 Tomcat
容器实现并管理的。具体来说,Tomcat
使用了一个名为 ApplicationFilterChain
的类来实现 FilterChain
接口
public class ApplicationFilterChain implements FilterChain {private final Filter[] filters; // 过滤器数组private final Servlet servlet; // 目标 Servletprivate int index = 0; // 当前处理的过滤器索引public ApplicationFilterChain(Filter[] filters, Servlet servlet) {this.filters = filters;this.servlet = servlet;}@Overridepublic void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {if (index < filters.length) {Filter filter = filters[index];index++; // 准备调用下一个过滤器filter.doFilter(request, response, this); // 递归调用} else {servlet.service(request, response); // 调用目标 Servlet}}
}
通过源码分析,就能理解过滤器链的实现了,通过index管理,妙极!
7 Listener
6.1 介绍
监听器(Listener
)是 Java Servlet API
中的一种服务器端组件,用于监听 Web
应用中的各种事件,如会话创建、会话销毁、上下文初始化、上下文销毁等。监听器允许开发者在这些事件发生时执行特定的代码,从而实现对 Web
应用生命周期的管理和控制。
6.2 监听器分类
根据域的不同(请求域,会话域,应用域)可以分为三类监听器:
- Application域监听器
ServletContextListener
:监听与整个 Web 应用相关的生命周期事件,如初始化和销毁。ServletContextAttributeListener
:监听ServletContext
对象中属性的添加、删除和替换事件。
- Session域监听器
HttpSessionListener
:监听 HTTP 会话的创建和销毁事件。HttpSessionAttributeListener
:监听 HTTP 会话中属性的添加、删除和替换事件。HttpSessionBindingListener
:监听会话中对象的绑定和解绑事件。HttpSessionActivationListener
:监听会话的被动状态变化事件,例如会话从非活动状态变为活动状态。
- Request域监听器
ServletRequestListener
:监听 Servlet 请求的初始化和销毁事件。ServletRequestAttributeListener
:监听 Servlet 请求中属性的添加、删除和替换事件。
具体示例可以自己查资料,这里不再演示,主要分析监听器的实现原理。
6.3 监听器实现原理
以下是 Tomcat 运行应用服务时,监听器的七个详细步骤:
定义事件源(Event Source)
- 在 Tomcat 启动时,事件源(如
ServletContext
、HttpSession
或ServletRequest
)被创建。 - 事件源是能够触发事件的对象。例如,
ServletContext
在 Web 应用启动时被创建,HttpSession
在用户会话创建时被创建,ServletRequest
在每次请求时被创建。
定义事件(Event)
- 在事件发生时,事件对象(如
ServletContextEvent
、HttpSessionEvent
或ServletRequestEvent
)被创建。 - 事件对象封装了事件的详细信息,如事件源、事件类型等。例如,当
ServletContext
初始化时,会创建一个ServletContextEvent
对象。
定义监听器接口(Listener Interface)
- 在 Tomcat 启动时,监听器接口(如
ServletContextListener
、HttpSessionListener
或ServletRequestListener
)被定义。 - 监听器接口定义了监听器需要实现的方法,用于处理特定类型的事件。例如,
ServletContextListener
接口定义了contextInitialized
和contextDestroyed
方法。
实现监听器(Implement Listener)
- 在应用开发阶段,开发者实现监听器接口,并在相应的方法中编写处理事件的代码。
- 开发者实现监听器接口,例如实现
ServletContextListener
接口的类需要实现contextInitialized
和contextDestroyed
方法。
注册监听器(Register Listener)
- 在 Tomcat 启动时,监听器通过
web.xml
配置文件或注解(如@WebListener
)注册到事件源。 - 监听器需要在 Web 应用启动时注册到事件源。例如,通过
web.xml
配置文件或注解@WebListener
注册监听器。
触发事件(Trigger Event)
- 在事件发生时,事件源会创建一个事件对象,并通知所有注册的监听器。
- 当事件发生时,事件源会创建一个事件对象,并通知所有注册的监听器。例如,当
ServletContext
初始化时,会创建一个ServletContextEvent
对象,并通知所有注册的ServletContextListener
。
处理事件(Handle Event)
- 在事件发生时,监听器中相应的方法会被调用,开发者在这些方法中编写的代码将被执行,从而处理事件。
- 监听器中相应的方法会被调用,开发者在这些方法中编写的代码将被执行,从而处理事件。例如,
ServletContextListener
的contextInitialized
方法在ServletContext
初始化时被调用。