好的,我们来详细讲解 Servlet 的基础知识。
Servlet 基础
Servlet 是运行在 Web 服务器或应用服务器上的 Java 程序,用于处理客户端(通常是 Web 浏览器)的请求并生成响应。它是 Java EE (Jakarta EE) 规范中 Web 层技术的核心组件。
1. Servlet 的配置方法
Servlet 可以通过两种主要方式部署和配置:
① 使用
web.xml配置文件 (传统方式)这是 Java EE 规范早期版本的标准方式。在web.xml文件中定义 Servlet 的名称、类名以及 URL 映射模式。<?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-name>MyServlet</servlet-name> <!-- Servlet 逻辑名称 --> <servlet-class>com.example.MyServlet</servlet-class> <!-- 完整的类名 --> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <!-- 关联到上面的逻辑名称 --> <url-pattern>/myservlet</url-pattern> <!-- 访问该 Servlet 的 URL 模式 --> </servlet-mapping> </web-app>② 使用注解的方式 (Servlet 3.0+)从 Servlet 3.0 规范开始,可以直接在 Servlet 类上使用
@WebServlet注解来定义,无需web.xml配置(或减少其配置)。import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; @WebServlet( name = "MyAnnotatedServlet", // 可选,Servlet 名称 urlPatterns = {"/annotated", "/anotherpath"} // 定义访问该 Servlet 的 URL 模式 ) public class MyAnnotatedServlet extends HttpServlet { // ... Servlet 的业务逻辑代码 (doGet, doPost 等) }这种方式更简洁、现代,是推荐的做法。
2. HTTP 方法处理 (doGet,doPost,doPut,doDelete)
Servlet 的核心功能是处理不同类型的 HTTP 请求。开发者通常覆盖HttpServlet类中的相应方法:
doGet(HttpServletRequest request, HttpServletResponse response): 处理 HTTPGET请求。通常用于获取资源(如查询数据、加载页面),请求参数附加在 URL 后面(查询字符串),可被缓存、书签收藏,有长度限制。不应用于改变服务器状态的操作。doPost(HttpServletRequest request, HttpServletResponse response): 处理 HTTPPOST请求。通常用于提交数据(如表单提交、文件上传),请求参数放在请求体中,不会被缓存、书签收藏,没有长度限制。用于改变服务器状态的操作(如创建、更新数据)。doPut(HttpServletRequest request, HttpServletResponse response): 处理 HTTPPUT请求。通常用于更新整个资源。使用相对较少。doDelete(HttpServletRequest request, HttpServletResponse response): 处理 HTTPDELETE请求。通常用于删除资源。使用相对较少。
示例 (doGet处理查询参数):
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取请求参数 (例如: /myservlet?name=John&age=30) String name = request.getParameter("name"); String ageStr = request.getParameter("age"); int age = (ageStr != null && !ageStr.isEmpty()) ? Integer.parseInt(ageStr) : 0; // 设置响应内容类型 response.setContentType("text/html;charset=UTF-8"); // 获取输出流写入响应 PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head><title>GET Example</title></head>"); out.println("<body>"); out.println("<h1>Hello, " + name + "!</h1>"); out.println("<p>You are " + age + " years old.</p>"); out.println("</body></html>"); } finally { out.close(); } }3.HttpServletRequest
该对象代表客户端的 HTTP 请求。它提供了访问请求信息的方法。
- ① 消息行: 包含 HTTP 方法 (GET, POST 等)、请求的 URI、HTTP 协议版本。
- 方法:
request.getMethod() - URI:
request.getRequestURI() - 协议:
request.getProtocol()
- 方法:
- ② 消息头: 包含元数据 (如
Content-Type,User-Agent,Cookie,Authorization)。- 获取单个头值:
String headerValue = request.getHeader("Header-Name"); - 获取所有头名:
Enumeration<String> headerNames = request.getHeaderNames();
- 获取单个头值:
- ③ 请求的参数: 客户端发送的数据。对于
GET在 URL 查询字符串中,对于POST等在请求体中。- 获取单个参数值:
String value = request.getParameter("paramName"); - 获取多值参数 (如复选框):
String[] values = request.getParameterValues("paramName"); - 获取所有参数名:
Enumeration<String> paramNames = request.getParameterNames(); - 获取参数 Map:
Map<String, String[]> paramMap = request.getParameterMap();
- 获取单个参数值:
- ④ 请求的转发 (
RequestDispatcher): 允许将请求在服务器内部转发给另一个资源(Servlet、JSP 页面、HTML 文件)进行处理或生成响应的一部分/全部。RequestDispatcher dispatcher = request.getRequestDispatcher("/path/to/resource"); // 获取转发器 dispatcher.forward(request, response); // 执行转发- 浏览器 URL不变,因为转发发生在服务器内部。
request和response对象被传递给目标资源。- 常用于 MVC 模式中的控制器 (Servlet) 将请求转发给视图 (JSP) 进行展示。
4.HttpServletResponse
该对象代表服务器对客户端的 HTTP 响应。它提供了设置响应和向客户端发送数据的方法。
- ① 数据流,输出: 用于向客户端发送响应体内容。
- 字符流 (常用于文本、HTML):
PrintWriter out = response.getWriter(); - 字节流 (常用于文件、图片等二进制数据):
ServletOutputStream out = response.getOutputStream(); - 注意: 在获取输出流之前通常需要设置内容类型 (
setContentType) 和字符编码 (setCharacterEncoding)。两者可以合并设置response.setContentType("text/html;charset=UTF-8");
- 字符流 (常用于文本、HTML):
- ② 响应头和响应码:
- 设置响应头:
response.setHeader("Header-Name", "Header-Value");(如Cache-Control,Location(用于重定向)) - 设置状态码:
response.setStatus(HttpServletResponse.SC_OK);(200) 或response.sendError(HttpServletResponse.SC_NOT_FOUND);(404) 等。常用常量定义在HttpServletResponse接口中。
- 设置响应头:
- ③ 请求的重定向: 通知客户端重新发起一个新的请求到指定的 URL。
response.sendRedirect("http://www.example.com/newlocation"); // 绝对URL response.sendRedirect("/app/newpath"); // 应用内相对URL (相对于当前Web应用的上下文根)- 浏览器 URL改变为新的地址。
- 发送一个
302 Found(或303 See Other) 状态码和Location响应头。 - 常用于页面跳转、登录后重定向到主页等。与转发 (
forward) 不同,重定向是客户端的二次请求。
5.Cookie
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据。浏览器会在后续的请求中自动携带该 Cookie 发送回同一服务器。通常用于会话管理、用户偏好设置、跟踪等。
- ① 浏览器向服务器发送请求,服务器分配的一个 Cookie…: Cookie 的创建和发送是由服务器发起的。
- ② 创建 cookie:
Cookie myCookie = new Cookie("cookieName", "cookieValue"); // 创建Cookie对象 response.addCookie(myCookie); // 将Cookie添加到响应中,发送给浏览器 - ③ 查看 cookie,查看 cookie 的名,查看 cookie 的值:
Cookie[] cookies = request.getCookies(); // 从请求中获取所有Cookie if (cookies != null) { for (Cookie cookie : cookies) { String name = cookie.getName(); // 获取Cookie名 String value = cookie.getValue(); // 获取Cookie值 // ... 处理逻辑 } } - ④ 修改 cookie 的值: 修改 Cookie 的值需要创建一个同名的新 Cookie 对象并再次发送给客户端。
Cookie updatedCookie = new Cookie("cookieName", "newValue"); response.addCookie(updatedCookie); - ⑤ 在请求中得到 cookie 和更新 cookie: 如上③所示获取 Cookie。更新值如④所示。
- ⑥ 设置 cookie 的有效期: 默认情况下,Cookie 是会话 Cookie,浏览器关闭后即失效。要创建持久 Cookie,需设置
setMaxAge(单位:秒)。myCookie.setMaxAge(60 * 60 * 24 * 7); // 设置有效期为一周 (秒)
6.Session---HttpSession
Session 是服务器端用于跟踪特定用户会话状态的一种机制。它在用户第一次访问服务器时创建,并在会话过期或显式失效时销毁。Session 通常依赖于 Cookie (存储 Session ID) 或 URL 重写。
- ① 浏览器向服务器发送请求,服务器分配的一个
Session…: Session 由服务器创建和管理。 - ② 从请求中把
session取出来:HttpSession session = request.getSession(); // 获取当前Session,如果不存在则创建一个新的 HttpSession session = request.getSession(false); // 获取当前Session,如果不存在则返回null - ③ 设置
session的值: Session 对象可以存储任意数量的属性(键值对)。session.setAttribute("username", "john_doe"); // 存储属性 session.setAttribute("cartItems", cartItemList); - ④ 查看
sessionID:String sessionId = session.getId(); // 获取当前Session的唯一ID - ⑤ 查看
session的值:String username = (String) session.getAttribute("username"); // 获取属性值 List<CartItem> cart = (List<CartItem>) session.getAttribute("cartItems"); Object value = session.getAttribute("someKey"); // 返回Object类型,需强转- 管理 Session:
- 使 Session 失效 (用户注销):
session.invalidate(); - 设置 Session 最大不活动间隔 (秒):
session.setMaxInactiveInterval(30 * 60);// 30分钟 - 在
web.xml中配置全局 Session 超时时间 (分钟):<session-config> <session-timeout>30</session-timeout> </session-config>
- 使 Session 失效 (用户注销):
- 管理 Session:
7.ServletContext
ServletContext代表整个 Web 应用程序。它在 Web 应用启动时创建,在应用停止或卸载时销毁。一个 Web 应用只有一个ServletContext实例。所有 Servlet 和 JSP 页面都可以访问它。
- 作用域:全局,整个应用范围内共享。
- 获取方式:
ServletContext context = getServletContext(); // 在Servlet内部 ServletContext context = request.getServletContext(); // 通过request - 主要用途:
- 存储和获取全局共享属性:
setAttribute(String name, Object object),getAttribute(String name),removeAttribute(String name) - 获取 Web 应用的初始化参数 (在
web.xml中配置的<context-param>):<context-param> <param-name>appName</param-name> <param-value>MyAwesomeApp</param-value> </context-param>String appName = context.getInitParameter("appName"); - 获取资源的真实路径 (相对于 Web 应用根目录):
String realPath = context.getRealPath("/WEB-INF/config.xml"); - 获取资源作为输入流:
InputStream is = context.getResourceAsStream("/WEB-INF/config.xml"); - 记录日志:
context.log("An important message");
- 存储和获取全局共享属性:
8.ServletConfig
ServletConfig对象代表单个 Servlet的配置信息。它在 Servlet 初始化时由容器创建并传递给 Servlet。每个 Servlet 实例都有其自己的ServletConfig对象。
- 作用域:Servlet 级别,仅对配置的那个 Servlet 有效。
- 获取方式: 在 Servlet 的
init(ServletConfig config)方法中,或者之后通过getServletConfig()方法。 - 主要用途:
- 获取 Servlet 的名称:
String servletName = config.getServletName(); - 获取该 Servlet 的初始化参数(在
web.xml的<servlet>标签内用<init-param>配置,或在@WebServlet注解中用initParams属性配置):<servlet> <servlet-name>ConfigServlet</servlet-name> <servlet-class>com.example.ConfigServlet</servlet-class> <init-param> <param-name>param1</param-name> <param-value>value1</param-value> </init-param> </servlet>@WebServlet( name = "AnnotatedConfigServlet", urlPatterns = {"/config"}, initParams = { @WebInitParam(name = "param1", value = "value1"), @WebInitParam(name = "param2", value = "value2") } )String paramValue = config.getInitParameter("param1"); Enumeration<String> paramNames = config.getInitParameterNames(); - 获取
ServletContext:ServletContext context = config.getServletContext();
- 获取 Servlet 的名称:
- ① 覆写
init方法: 如果需要在 Servlet 初始化时执行一些操作(如读取配置参数、建立数据库连接池),可以覆盖init方法。通常调用super.init(config)以确保父类初始化逻辑执行。public class MyServlet extends HttpServlet { private String myParam; @Override public void init(ServletConfig config) throws ServletException { super.init(config); // 重要!调用父类初始化 myParam = config.getInitParameter("myParam"); // 读取初始化参数 // ... 其他初始化逻辑 (如连接池初始化) } // ... doGet, doPost 等方法 } - ② 配置本 servlet 的参数: 如上所述,通过
web.xml的<init-param>或@WebServlet的initParams属性进行配置。