Java Web 之 Servlet 100问
Filter 是什么?
在Java Web开发中,Filter(过滤器)是一种用于在请求到达目标资源(如Servlet、JSP)之前或响应返回客户端之前
进行预处理和后处理的组件。Filter可以拦截请求和响应,执行特定的操作,如日志记录、字符编码设置、身份验证、权限检查、数据压缩
等。Filter 可以将完成这些通用的操作,避免在多个 Servlet 中编写重复代码
。
Filter 中,什么是链式处理?
链式处理
:多个Filter可以串联,形成一个处理链,每个Filter依次处理请求和响应。
Filter 常见的应用场景有哪些?
常见应用场景:日志记录、字符编码设置、权限检查、身份验证
等。
Filter 的工作原理是什么?
客户端请求到达 → Filter 拦截并预处理 → 请求到达 Servlet ,Servlet 生成响应 → Filter 后处理 → 返回响应。
Filter 的生命周期分为哪些阶段?
init()
→ doFilter()
→ destroy()
Filter 的生命周期离不开以上三个方法,它们分别代表 Filter 的初始化 → 执行过滤操作 → 销毁
三个生命阶段。
如何实现一个 Filter?
实现javax.servlet.Filter
接口,并重写init()
、doFilter()
、destroy()
方法:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;@WebFilter("/*") // 拦截所有请求
public class ExampleFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化操作}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 请求预处理System.out.println("Before processing request");// 传递给下一个Filter或目标资源chain.doFilter(request, response);// 响应后处理System.out.println("After processing response");}@Overridepublic void destroy() {// 销毁操作}
}
如何配置 Filter ?
可以通过注解(如@WebFilter
)或在web.xml
中配置Filter:
<filter><filter-name>ExampleFilter</filter-name><filter-class>com.example.ExampleFilter</filter-class>
</filter>
<filter-mapping><filter-name>ExampleFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
@WebFilter("/api/*")
会拦截哪些资源?
api/
路径下的所有资源都会被拦截。
@WebFilter("*.do")
会拦截哪些资源?
以.do
结尾的所有资源都会被拦截。
Listener 是什么?
在Java Web开发中,Listener(监听器)是一种用于监听Web应用中特定事件(如ServletContext、HttpSession、ServletRequest的创建、销毁或属性修改)的组件。Listener可以在这些事件发生时执行自定义逻辑,常用于初始化资源、统计在线用户、清理资源等场景。
Listener 的作用有哪些?
- 事件监听:监听Web应用中的各种事件,如应用启动、会话创建、请求到达等。
- 资源管理:在应用启动时初始化资源,在应用关闭时释放资源(如数据库连接等)。
- 日志记录:记录应用的关键事件,用于监控和调试。
- 初始化全局资源:在应用启动时初始化数据库连接池、缓存等。
- 统计在线用户数:跟踪用户会话状态,通过监听会话的创建和销毁,统计在线用户数。
Listener 常见的类型有哪些?
Java Web提供了多种Listener接口,用于监听不同的事件:
- ServletContextListener
- 监听
ServletContext
的创建和销毁。 - 常用方法:
contextInitialized()
、contextDestroyed()
。 - 应用场景:在应用启动时初始化全局资源(如数据库连接池),在应用关闭时释放资源。
- 监听
- HttpSessionListener
- 监听
HttpSession
的创建和销毁。 - 常用方法:
sessionCreated()
、sessionDestroyed()
。 - 应用场景:统计在线用户数、跟踪用户会话状态。
- 监听
- ServletRequestListener
- 监听
ServletRequest
的创建和销毁。 - 常用方法:
requestInitialized()
、requestDestroyed()
。 - 应用场景:记录请求日志、统计请求处理时间。
- 监听
- ServletContextAttributeListener
- 监听
ServletContext
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪全局属性的变化。
- 监听
- HttpSessionAttributeListener
- 监听
HttpSession
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪用户会话中属性的变化。
- 监听
- ServletRequestAttributeListener
- 监听
ServletRequest
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪请求中属性的变化。
- 监听
Session 相关的监听器有哪些?
和Session相关的监听器有两种:
HttpSessionListener
- 监听
HttpSession
的创建和销毁。 - 常用方法:
sessionCreated()
、sessionDestroyed()
。 - 应用场景:统计在线用户数、跟踪用户会话状态。
HttpSessionAttributeListener
- 监听
HttpSession
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪用户会话中属性的变化。
Request 相关的监听器有哪些?
Request相关的监听器有两种:
ServletRequestListener
- 监听
ServletRequest
的创建和销毁。 - 常用方法:
requestInitialized()
、requestDestroyed()
。 - 应用场景:记录请求日志、统计请求处理时间。
ServletRequestAttributeListener
- 监听
ServletRequest
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪请求中属性的变化。
ServletContext 相关的监听器有哪些?
ServletContext相关的监听器有两种:
ServletContextListener
- 监听
ServletContext
的创建和销毁。 - 常用方法:
contextInitialized()
、contextDestroyed()
。 - 应用场景:在应用启动时初始化全局资源(如数据库连接池),在应用关闭时释放资源。
ServletContextAttributeListener
- 监听
ServletContext
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪全局属性的变化。
Listener 如何实现?
要实现一个Listener,需要实现相应的接口,并重写其方法。例如,实现ServletContextListener
:
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;@WebListener
public class ExampleContextListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {// 应用启动时执行System.out.println("Web应用初始化");// 初始化全局资源,如数据库连接池}@Overridepublic void contextDestroyed(ServletContextEvent sce) {// 应用关闭时执行System.out.println("Web应用销毁");// 释放全局资源}
}
如何配置 Listener?
可以通过注解(如@WebListener
)或在web.xml
中配置Listener:
<listener><listener-class>com.example.ExampleContextListener</listener-class>
</listener>
Servlet 是什么?
Java Servlet | ||
---|---|---|
运行位置 | Web 服务器或应用服务器,如 Tomcat 等。 | |
主要功能 | 处理请求 | 处理客户端(一般是浏览器)发送的 HTTP 请求。 |
生成响应 | 生成动态Web内容,如 HTML、JSON 等。 | |
业务逻辑 | 在服务器端执行业务逻辑,如访问数据库、调用其他服务等。 | |
会话管理 | 管理客户端与服务器之间的会话,如使用Session、Cookie。 | |
本质 | Java程序 |
Servlet 的作用有哪些
作用 | |
---|---|
生成动态 HTML 页面 | 生成动态的 HTML 页面。 |
提供 Web 服务 | 提供 RESTful API 或 SOAP 服务。 |
文件上传和下载 | 处理文件上传和下载请求。 |
表单处理 | 处理用户提交的表单数据。 |
Servlet 的工作流程是什么?
流程 | 备注 |
---|---|
Servlet 容器(例如Tomcat)产生一个 Servlet 实例。 | 在一个应用程序中,每种Servlet类型只能有一个实例。同时产生一个 ServletContext 对象、一个 ServletConfig 对象。 |
用户发送 HTTP 请求。 | |
Servlet容器调用 Servlet 实例的service 方法。 | service 方法的参数 ServletRequest 对象和 ServletResponse 对象都是由 Servlet 容器封装好的,程序员可以直接使用这两个对象。 |
通过ServletRequest 获取 HTTP 请求。 | ServletRequest 中封装了当前的 HTTP 请求。 |
通过ServletResponse 返回响应内容。 | ServletResponse 表示当前用户的 HTTP 响应。 |
Servlet 的生命周期有哪些阶段
阶段 | 生命周期 | 备注 |
---|---|---|
阶段一 | 加载和实例化 | Web 容器加载 Servlet 类并创建其实例。 |
通常是在第一次收到请求时加载,但也可以通过配置在启动时加载。 | ||
阶段二 | 初始化 | 调用 init() 方法,完成 Servlet 的初始化工作。 |
开发者可以重写此方法,执行自定义的初始化逻辑(如加载配置文件、初始化数据库连接等)。 | ||
阶段三 | 处理请求 | 调用 service() 方法,处理客户端请求。 |
对于 HTTP 请求,通常会使用 HttpServlet 的子类,并重写 doGet() 、doPost() 等方法。 | ||
阶段四 | 销毁 | 调用 destroy() 方法,释放资源(如关闭数据库连接、清理缓存等)。 |
通常是在 Web 应用关闭或 Servlet 被移除时调用。 | ||
补充 | Servlet 的生命周期由 Web 容器(如 Tomcat)管理。 |
Servlet 的核心接口和类有哪些
13个核心接口和类 | 类型 | 所在 java 包 | 简介 |
---|---|---|---|
Servlet | 接口 | javax.servlet | 定义了 Servlet 的生命周期方法 |
void init(ServletConfig config) :初始化 Servlet。 | |||
void service(ServletRequest req, ServletResponse res) :处理请求。 | |||
void destroy() :销毁 Servlet。 | |||
ServletConfig getServletConfig() :获取 Servlet 配置信息。 | |||
String getServletInfo() :获取 Servlet 的描述信息。 | |||
GenericServlet | 抽象类 | javax.servlet | 提供了 Servlet 接口的基本实现,简化了 Servlet 的开发。 |
开发者可以继承此类,并重写 service() 方法。 | |||
HttpServlet | 类 | javax.servlet.http | 继承自 GenericServlet ,专门用于处理 HTTP 请求。 |
提供了对 HTTP 方法的支持(如 doGet() 、doPost() 、doPut() 、doDelete() 等)。 | |||
开发者通常继承此类,并重写相应的方法。 | |||
ServletRequest | 接口 | javax.servlet | |
HttpServletRequest | 接口 | javax.servlet.http | |
ServletResponse | 接口 | javax.servlet | |
HttpServletResponse | 接口 | javax.servlet.http | |
ServletConfig | 接口 | 封装 Servlet 配置。 | |
ServletDispatcher | 接口 | ||
ServletContext | 接口 | 封装了上下文(应用程序)的环境详情。 | |
Filter | 接口 | ||
Listener | 接口 |
Servlet 如何使用
导入Servlet
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope>
<!--提供provided 编译和测试有效,避免和 tomcat 中的 servlet-api 包冲突报错-->
</dependency>
以下是一个简单的 Servlet 示例,用于处理 HTTP GET 请求并返回 “Hello, World!”:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloWorldServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {// 设置响应内容类型response.setContentType("text/html;charset=UTF-8");// 获取输出流PrintWriter out = response.getWriter();// 向客户端发送响应out.println("<html>");out.println("<head><title>Hello World</title></head>");out.println("<body>");out.println("<h1>Hello, World!</h1>");out.println("</body>");out.println("</html>");}
}
Servlet 如何配置
两种配置方式 | 介绍 |
---|---|
web.xml 配置 | 在 web.xml 文件中定义 Servlet 和映射 |
注解配置 | 使用 @WebServlet 注解定义 Servlet 和映射 |
(1) web.xml
配置
在 web.xml
文件中定义 Servlet 和映射:
<servlet><servlet-name>HelloWorldServlet</servlet-name><servlet-class>HelloWorldServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>HelloWorldServlet</servlet-name><url-pattern>/hello</url-pattern>
</servlet-mapping>
(2) 注解配置
使用 @WebServlet
注解定义 Servlet 和映射:
配置之后,我们就可以通过
http://localhost:8080/hello
访问Servlet。
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;@WebServlet(name = "HelloWorldServlet", urlPatterns = "/hello")
public class HelloWorldServlet extends HttpServlet {// Servlet 代码
}
Servlet 中的常用方法有哪些
七个相关的类或接口 | 常用方法 | |
---|---|---|
Servlet | void init(ServletConfig config) | 初始化 Servlet,容器在创建 Servlet 实例后调用此方法。 |
void service(ServletRequest req, ServletResponse res) | 处理客户端请求的核心方法。 | |
void destroy() | 销毁 Servlet,容器在移除 Servlet 实例前调用此方法。 | |
ServletConfig getServletConfig() | 返回 ServletConfig 对象,用于获取 Servlet 的配置信息。 | |
String getServletInfo() | 返回 Servlet 的描述信息(如作者、版本等)。 | |
GenericServlet | void init() | 无参的初始化方法,开发者可以重写此方法来实现自定义的初始化逻辑。 |
void log(String msg) | 将消息写入 Servlet 容器的日志文件。 | |
void log(String msg, Throwable t) | 将消息和异常信息写入 Servlet 容器的日志文件。 | |
HttpServlet | void doGet(HttpServletRequest req, HttpServletResponse resp) | 处理 HTTP GET 请求。 |
void doPost(HttpServletRequest req, HttpServletResponse resp) | 处理 HTTP POST 请求。 | |
void doPut(HttpServletRequest req, HttpServletResponse resp) | 处理 HTTP PUT 请求。 | |
void doDelete(HttpServletRequest req, HttpServletResponse resp) | 处理 HTTP DELETE 请求。 | |
void service(HttpServletRequest req, HttpServletResponse resp) | 根据请求方法(GET、POST 等)调用相应的 doXxx 方法。 | |
ServletRequest 和 HttpServletRequest | String getParameter(String name) | 根据参数名称获取请求参数的值。 |
String[] getParameterValues(String name) | 根据参数名称获取多个请求参数的值(适用于多选框等场景)。 | |
Map<String, String[]> getParameterMap() | 返回所有请求参数的键值对。 | |
String getHeader(String name) | 根据头名称获取请求头的值。 | |
Enumeration<String> getHeaderNames() | 返回所有请求头的名称。 | |
InputStream getInputStream() | 返回一个二进制输入流,用于读取请求体中的数据。 | |
BufferedReader getReader() | 返回一个字符输入流,用于读取请求体中的文本数据。 | |
void setAttribute(String name, Object obj) | 设置请求属性的名称和值。 | |
Object getAttribute(String name) | 根据名称获取请求属性的值。 | |
void removeAttribute(String name) | 移除指定的请求属性。 | |
ServletResponse 和 HttpServletResponse | void setContentType(String type) | 设置响应的内容类型(MIME 类型),例如 text/html 或 application/json 。 |
void setCharacterEncoding(String charset) | 设置响应的字符编码,例如 UTF-8 。 | |
ServletOutputStream getOutputStream() | 返回一个二进制输出流,用于向客户端发送二进制数据。 | |
PrintWriter getWriter() | 返回一个字符输出流,用于向客户端发送文本数据。 | |
void setHeader(String name, String value) | 设置响应头的名称和值。 | |
void addHeader(String name, String value) | 添加一个响应头,允许多个同名的头信息。 | |
void sendRedirect(String location) | 将客户端重定向到指定的 URL。 | |
void setStatus(int sc) | 设置响应的状态码(如 200、404 等)。 | |
注意 | getOutputStream() 和getWriter() | 不能同时调用,同时调用会发生异常。 |
示例代码
以下是一个简单的 Servlet 示例,展示了常用方法的使用:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class ExampleServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置响应内容类型和字符编码response.setContentType("text/html;charset=UTF-8");// 获取请求参数String username = request.getParameter("username");// 获取输出流PrintWriter out = response.getWriter();// 向客户端发送响应out.println("<html>");out.println("<head><title>Example Servlet</title></head>");out.println("<body>");out.println("<h1>Hello, " + (username != null ? username : "Guest") + "!</h1>");out.println("</body>");out.println("</html>");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 处理 POST 请求doGet(request, response);}
}
ServletRequest 的核心方法有哪些
获取请求参数
String getParameter(String name) | 根据参数名称获取单个请求参数的值。例如,获取表单中 name="username" 的值。 |
---|---|
String[] getParameterValues(String name) | 根据参数名称获取多个请求参数的值(适用于多选框等场景)。 |
Map<String, String[]> getParameterMap() | 返回所有请求参数的键值对,其中键是参数名称,值是参数值的数组。 |
获取请求头信息
String getHeader(String name) | 根据头名称获取单个请求头的值。例如,获取 User-Agent 或 Content-Type 。 |
---|---|
Enumeration<String> getHeaders(String name) | 根据头名称获取多个请求头的值(适用于多值的头信息)。 |
Enumeration<String> getHeaderNames() | 返回所有请求头的名称。 |
获取输入流
ServletInputStream getInputStream() | 返回一个二进制输入流,用于读取请求体中的数据(例如文件上传或二进制数据)。 |
---|---|
BufferedReader getReader() | 返回一个字符输入流,用于读取请求体中的文本数据(例如 JSON 或 XML)。 |
注意 | getInputStream 和 getReader 不能同时调用,否则会抛出 IllegalStateException 。 |
获取请求属性
void setAttribute(String name, Object obj) | 设置请求属性的名称和值。 |
---|---|
Object getAttribute(String name) | 根据名称获取请求属性的值。 |
void removeAttribute(String name) | 移除指定的请求属性。 |
Enumeration<String> getAttributeNames() | 返回所有请求属性的名称。 |
获取客户端和服务器信息
String getRemoteAddr() | 获取客户端的 IP 地址。 |
---|---|
String getRemoteHost() | 获取客户端的主机名。 |
int getRemotePort() | 获取客户端的端口号。 |
String getServerName() | 获取服务器的主机名。 |
int getServerPort() | 获取服务器的端口号。 |
String getProtocol() | 获取请求的协议(例如 HTTP/1.1 )。 |
String getScheme() | 获取请求的协议方案(例如 http 或 https )。 |
(6) 其他方法
String getContentType() | 获取请求体的内容类型(MIME 类型)。 |
---|---|
int getContentLength() | 获取请求体的长度(字节数)。 |
Locale getLocale() | 获取客户端的本地化信息。 |
Enumeration<Locale> getLocales() | 获取客户端支持的所有本地化信息。 |
使用示例
以下是一个简单的示例,展示如何使用 ServletRequest
获取请求参数并生成响应:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置响应内容类型response.setContentType("text/html;charset=UTF-8");// 获取请求参数String username = request.getParameter("username");// 获取字符输出流PrintWriter out = response.getWriter();// 向客户端发送响应out.println("<html>");out.println("<head><title>Hello Servlet</title></head>");out.println("<body>");out.println("<h1>Hello, " + (username != null ? username : "Guest") + "!</h1>");out.println("</body>");out.println("</html>");}
}
注意事项
- 参数编码:如果请求参数包含非 ASCII 字符(例如中文),需要设置正确的字符编码(例如
UTF-8
),否则可能出现乱码。可以通过request.setCharacterEncoding("UTF-8")
设置。 - 输入流的使用:根据请求体的数据类型选择
getInputStream
(二进制)或getReader
(文本)。 - 属性与参数的区别:请求参数是客户端发送的数据,而请求属性是服务器端设置的数据,用于在请求处理过程中共享信息。
ServletRequest
与 HttpServletRequest
是什么关系
父子接口 | HttpServletRequest 是ServletRequest 的子接口。 |
---|---|
HTTP 专用 | 专用于 HTTP 协议,提供了更多与 HTTP 相关的方法 |
新增特殊方法 | 获取 HTTP 方法(getMethod )。 |
获取请求的 URL 信息(getRequestURI 、getQueryString )。 | |
管理会话(getSession )。 | |
获取 Cookie(getCookies )。 | |
实际开发常用 | 在实际开发中,通常使用 HttpServletRequest ,因为它提供了更多 HTTP 相关的功能。 |
ServletResponse
的核心方法有哪些
以下是 ServletResponse
接口中一些重要的方法:
设置内容类型与字符编码
方法 | 介绍 |
---|---|
void setContentType(String type) | 设置响应的内容类型,如 text/html 或 application/json 。可附加字符编码,如 text/html;charset=UTF-8 。 |
void setCharacterEncoding(String charset) | 设置响应的字符编码,如 UTF-8 。若已经通过 setContentType 设置,则此方法会覆盖之前的设置。 |
获取输出流
方法 | 介绍 |
---|---|
ServletOutputStream getOutputStream() | 返回一个二进制输出流,用于向客户端发送二进制数据(例如图片、文件等)。 |
PrintWriter getWriter() | 返回一个字符输出流,用于向客户端发送文本数据(例如 HTML、JSON 等)。 |
注意 | getOutputStream 和 getWriter 不能同时调用,否则会抛出 IllegalStateException 。 |
设置响应头
方法 | 介绍 |
---|---|
void setHeader(String name, String value) | 设置响应头的名称和值,例如 setHeader("Content-Disposition", "attachment; filename=file.txt") 。 |
void addHeader(String name, String value) | 添加一个响应头,允许多个同名的头信息。 |
void setIntHeader(String name, int value) | 设置一个整数值的响应头。 |
缓冲区控制
方法 | 介绍 |
---|---|
void setBufferSize(int size) | 设置响应缓冲区的大小。 |
int getBufferSize() | 获取当前响应缓冲区的大小。 |
`void flushBuffer() | 强制将缓冲区的内容发送到客户端。 |
void reset() | 重置响应,清除缓冲区、状态码和头信息。 |
void resetBuffer() | 仅重置缓冲区的内容,不清除状态码和头信息。 |
boolean isCommitted() | 检查响应是否已经提交(即数据是否已经发送到客户端)。 |
其他方法
方法 | 介绍 |
---|---|
void setLocale(Locale loc) | 设置响应的本地化信息。 |
Locale getLocale() | 获取响应的本地化信息。 |
使用示例
以下是一个简单的示例,展示如何使用 ServletResponse
向客户端返回 HTML 内容:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloWorldServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置内容类型和字符编码response.setContentType("text/html;charset=UTF-8");// 获取字符输出流PrintWriter out = response.getWriter();// 向客户端发送 HTML 内容out.println("<html>");out.println("<head><title>Hello World</title></head>");out.println("<body>");out.println("<h1>Hello, World!</h1>");out.println("</body>");out.println("</html>");}
}
注意事项
- 内容类型和字符编码:必须在调用
getWriter
或getOutputStream
之前设置内容类型和字符编码,否则设置可能无效。 - 输出流的选择:根据返回数据的类型选择
getWriter
(文本)或getOutputStream
(二进制)。 - 缓冲区管理:合理设置缓冲区大小,避免内存浪费或性能问题。
- 响应提交:一旦调用
flushBuffer
或缓冲区已满,响应就会被提交,之后无法修改状态码或头信息。
ServletResponse
与 HttpServletResponse
是什么关系
父子接口 | HttpServletResponse 是ServletResponse 的子接口。 |
---|---|
HTTP 专用 | 专用于 HTTP 协议,提供了更多与 HTTP 相关的方法 |
新增特殊方法 | 设置状态码(setStatus 、sendError )。 |
重定向(sendRedirect )。 | |
管理 Cookie(addCookie )。 | |
实际开发常用 | 实际开发中,通常使用 HttpServletResponse ,因为它提供了更多 HTTP 相关的功能。 |
Servlet
和ServletConfig
是什么关系
一对一 | 每个 Servlet 都有一个独立的 ServletConfig 对象,由 Servlet 容器(如 Tomcat)创建并传递给 Servlet。 |
---|---|
保存配置信息 | 通过 ServletConfig ,开发者可以访问 Servlet 的初始化参数、Servlet 上下文等信息。 |
ServletConfig
的核心方法有哪些
方法 | 介绍 | |
---|---|---|
获取初始化参数 | String getInitParameter(String name) | 根据参数名称获取 Servlet 的初始化参数值。如web.xml 中配置的 <init-param> 值 |
Enumeration<String> getInitParameterNames() | 返回所有初始化参数的名称。 | |
获取 ServletContext | ServletContext getServletContext() | 返回 ServletContext 对象,用于与 Servlet 容器通信。 |
获取 Servlet 名称 | String getServletName() | 返回 Servlet 名称。名称在 web.xml 中通过 <servlet-name> 配置,或注解 @WebServlet 指定。 |
使用示例
以下是一个简单的示例,展示如何使用 ServletConfig
获取初始化参数:
(1) 在 web.xml
中配置初始化参数
<servlet><servlet-name>MyServlet</servlet-name><servlet-class>com.example.MyServlet</servlet-class><init-param><param-name>username</param-name><param-value>admin</param-value></init-param><init-param><param-name>password</param-name><param-value>123456</param-value></init-param>
</servlet>
<servlet-mapping><servlet-name>MyServlet</servlet-name><url-pattern>/myservlet</url-pattern>
</servlet-mapping>
(2) 在 Servlet 中使用 ServletConfig
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyServlet extends HttpServlet {private String username;private String password;@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);// 获取初始化参数username = config.getInitParameter("username");password = config.getInitParameter("password");}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();out.println("<html>");out.println("<head><title>MyServlet</title></head>");out.println("<body>");out.println("<h1>Username: " + username + "</h1>");out.println("<h1>Password: " + password + "</h1>");out.println("</body>");out.println("</html>");}
}
ServletConfig
与 ServletContext
的区别是什么
ServletConfig | ServletContext | |
---|---|---|
范围不同 | 每个 Servlet 有独立的 ServletConfig 。 | 整个 Web 应用共享一个 ServletContext 对象。在应用关闭时销毁。 |
用途不同 | 用于访问Servlet 的初始化参数。 | 用于访问 Web 应用的全局信息,如上下文初始化参数,资源路径等。 |
创建时机不同 | ServletConfig 对象在 Servlet 初始化时(init 方法调用时)创建 | 当 Web 服务器(如 Tomcat)启动并加载 Web 应用时创建。 |
线程安全 | 线程安全,可以在多线程环境中使用。 | 线程安全,可以在多线程环境中使用。 |
如何通过注解配置初始化参数
如果使用注解配置 Servlet,可以通过 @WebServlet
的 initParams
属性设置初始化参数:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@WebServlet(name = "MyServlet",urlPatterns = "/myservlet",initParams = {@WebInitParam(name = "username", value = "admin"),@WebInitParam(name = "password", value = "123456")}
)
public class MyServlet extends HttpServlet {private String username;private String password;@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);// 获取初始化参数username = config.getInitParameter("username");password = config.getInitParameter("password");}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();out.println("<html>");out.println("<head><title>MyServlet</title></head>");out.println("<body>");out.println("<h1>Username: " + username + "</h1>");out.println("<h1>Password: " + password + "</h1>");out.println("</body>");out.println("</html>");}
}
ServletContext的核心方法有哪些
作用 | 方法 | 介绍 |
---|---|---|
获取初始化参数 | String getInitParameter(String name) | 根据参数名称获取 Web 应用的初始化参数值。这些参数通常在 web.xml 中通过 <context-param> 配置。 |
- | Enumeration<String> getInitParameterNames() | 返回所有 Web 应用初始化参数的名称。 |
获取资源 | URL getResource(String path) | 根据路径获取资源的 URL。路径必须以 / 开头,相对于 Web 应用的根目录。 |
- | InputStream getResourceAsStream(String path) | 根据路径获取资源的输入流。适用于读取文件内容。 |
- | String getRealPath(String path) | 根据虚拟路径获取文件系统的真实路径。例如,将 /WEB-INF/web.xml 转换为服务器文件系统中的绝对路径。 |
- | Set<String> getResourcePaths(String path) | 返回指定路径下的所有资源路径。 |
共享数据(属性) | void setAttribute(String name, Object object) | 在应用范围内设置属性,让所有 Servlet 和请求都可以访问。 |
- | Object getAttribute(String name) | 根据名称获取应用范围内的属性。 |
- | void removeAttribute(String name) | 移除应用范围内的属性。 |
- | Enumeration<String> getAttributeNames() | 返回所有应用范围内的属性名称。 |
记录日志 | void log(String message) | 将消息写入 Servlet 容器的日志文件。 |
- | void log(String message, Throwable throwable) | 将消息和异常信息写入 Servlet 容器的日志文件。 |
获取容器信息 | String getServerInfo() | 返回 Servlet 容器的名称和版本信息。 |
- | int getMajorVersion() | 返回 Servlet API 的主版本号。 |
- | int getMinorVersion() | 返回 Servlet API 的次版本号。 |
其他方法 | String getContextPath() | 返回 Web 应用的上下文路径(例如 /myapp )。 |
- | String getMimeType(String file) | 返回指定文件的 MIME 类型(例如 text/html 或 image/jpeg )。 |
- | RequestDispatcher getRequestDispatcher(String path) | 返回一个 RequestDispatcher 对象,用于请求转发或包含其他资源。 |
使用示例
以下是一些常见的使用场景和示例:
(1) 获取初始化参数
在 web.xml
中配置上下文参数:
<context-param><param-name>appName</param-name><param-value>My Web Application</param-value>
</context-param>
在 Servlet 中获取参数:
String appName = getServletContext().getInitParameter("appName");
System.out.println("Application Name: " + appName);
(2) 获取资源
读取 WEB-INF
目录下的配置文件:
InputStream inputStream = getServletContext().getResourceAsStream("/WEB-INF/config.properties");
Properties properties = new Properties();
properties.load(inputStream);
String value = properties.getProperty("key");
(3) 共享数据
设置应用范围内的属性:
getServletContext().setAttribute("userCount", 100);
获取应用范围内的属性:
int userCount = (Integer) getServletContext().getAttribute("userCount");
(4) 记录日志
记录日志信息:
getServletContext().log("An error occurred in the application.");
GenericServlet与Servlet是什么关系
实现 ServletConfig 和 Servlet 接口 | GenericServlet 实现了 Servlet 和 ServletConfig 接口,并提供了一些默认的方法实现。 |
---|---|
简化 Servlet 开发 | 开发者可以通过继承 GenericServlet 来创建自定义的 Servlet,而不需要实现所有 Servlet 接口的方法。 |
注意事项 | GenericServlet 没有提供 service 方法的默认实现,开发者必须重写此方法。 |
- | 可以通过重写无参的 init() 方法来实现自定义的初始化逻辑,而不需要直接处理 ServletConfig 对象。 |
GenericServlet的核心方法有哪些
方法 | 介绍 | |
---|---|---|
Servlet 生命周期方法 | void init(ServletConfig config) | 初始化 Servlet。GenericServlet 提供了默认实现,将 ServletConfig 对象保存起来,并调用无参的 init() 方法。 |
- | void init() | 无参的初始化方法,开发者可以重写此方法来实现自定义的初始化逻辑。 |
- | void service(ServletRequest req, ServletResponse res) | 处理客户端请求的核心方法。GenericServlet 没有提供默认实现,开发者必须重写此方法。 |
- | void destroy() | 销毁 Servlet。GenericServlet 提供了默认实现,开发者可以重写此方法来实现自定义的销毁逻辑。 |
获取配置信息 | ServletConfig getServletConfig() | 返回 ServletConfig 对象。 |
- | String getInitParameter(String name) | 根据参数名称获取 Servlet 的初始化参数值。 |
- | Enumeration<String> getInitParameterNames() | 返回所有初始化参数的名称。 |
- | ServletContext getServletContext() | 返回 ServletContext 对象。 |
日志 | void log(String msg) | 将消息写入 Servlet 容器的日志文件。 |
- | void log(String msg, Throwable t) | 将消息和异常信息写入 Servlet 容器的日志文件。 |
其它方法 | String getServletInfo() | 返回 Servlet 的描述信息。默认返回空字符串,开发者可以重写此方法。 |
- | String getServletName() | 返回 Servlet 的名称。 |
使用示例
以下是一个简单的示例,展示如何通过继承 GenericServlet
创建自定义的 Servlet:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;public class MyServlet extends GenericServlet {@Overridepublic void init() throws ServletException {// 自定义初始化逻辑System.out.println("Servlet initialized.");}@Overridepublic void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {// 设置响应内容类型res.setContentType("text/html;charset=UTF-8");// 获取输出流PrintWriter out = res.getWriter();// 向客户端发送响应out.println("<html>");out.println("<head><title>MyServlet</title></head>");out.println("<body>");out.println("<h1>Hello, World!</h1>");out.println("</body>");out.println("</html>");}@Overridepublic void destroy() {// 自定义销毁逻辑System.out.println("Servlet destroyed.");}
}
GenericServlet
与 HttpServlet
的区别是什么
区别 | GenericServlet | HttpServlet |
---|---|---|
父子类 | - | GenericServlet 的子类。 |
协议无关性 | 适用于任何协议,包括HTTP、FTP等。 | 专用于 HTTP 协议。提供了对 HTTP 方法的支持(如:doGet、doPost)。 |