【JavaWeb学习 | 第18篇】Servlet与MVC


🌈 个人主页: Hygge_Code
🔥 热门专栏:从0开始学习Java | Linux学习| 计算机网络
💫 个人格言: "既然选择了远方,便不顾风雨兼程"

文章目录

  • 深入理解Servlet与MVC
    • JSP内置对象回顾🥝
      • [1. request对象](#1. request对象)
      • [2. response对象](#2. response对象)
      • [3. session对象](#3. session对象)
      • [4. application对象](#4. application对象)
      • [5. Cookie的操作方式](#5. Cookie的操作方式)
      • [6. GET请求与POST请求的区别](#6. GET请求与POST请求的区别)
    • 一、Servlet------Web应用的请求处理核心🥝
      • [1. Servlet的核心概念](#1. Servlet的核心概念)
      • [2. Servlet的体系结构](#2. Servlet的体系结构)
        • [2.1 Servlet接口的核心方法](#2.1 Servlet接口的核心方法)
        • [2.2 ServletConfig接口的核心方法](#2.2 ServletConfig接口的核心方法)
      • [3. Servlet案例:登录功能实现](#3. Servlet案例:登录功能实现)
        • [3.1 编写LoginServlet类(实现Servlet接口)](#3.1 编写LoginServlet类(实现Servlet接口))
        • [3.2 配置web.xml文件](#3.2 配置web.xml文件)
          • 🐦‍🔥web.xml配置详解🐦‍🔥
          • [1. `<servlet>` 标签:注册 Servlet 实例](#1. <servlet> 标签:注册 Servlet 实例)
          • [2. `<servlet-mapping>` 标签:映射请求地址](#2. <servlet-mapping> 标签:映射请求地址)
        • [3.3 编写登录页面(index.jsp)](#3.3 编写登录页面(index.jsp))
        • [3.4 测试结果与生命周期验证](#3.4 测试结果与生命周期验证)
      • [4. Servlet的生命周期详解](#4. Servlet的生命周期详解)
      • [5. JSP的本质](#5. JSP的本质)
    • 二、请求处理与响应机制
      • [1. 请求与响应的体系结构](#1. 请求与响应的体系结构)
      • [2. ServletRequest接口常用方法](#2. ServletRequest接口常用方法)
        • [2.1 ServletRequest接口用法示例](#2.1 ServletRequest接口用法示例)
        • [2.2 GET与POST请求的参数获取差异](#2.2 GET与POST请求的参数获取差异)
      • [3. ServletResponse接口常用方法](#3. ServletResponse接口常用方法)
        • [3.1 ServletResponse接口用法示例](#3.1 ServletResponse接口用法示例)
      • [4. HttpServletRequest接口常用方法](#4. HttpServletRequest接口常用方法)
      • [5. HttpServletResponse接口常用方法](#5. HttpServletResponse接口常用方法)
      • [6. HttpServlet的核心方法](#6. HttpServlet的核心方法)
        • [6.1 实战:注册功能实现(继承HttpServlet)](#6.1 实战:注册功能实现(继承HttpServlet))
        • [6.2 编写注册页面(register.jsp)](#6.2 编写注册页面(register.jsp))
        • [6.3 配置web.xml(添加注册Servlet映射)](#6.3 配置web.xml(添加注册Servlet映射))
      • [7. ServletContext接口常用方法](#7. ServletContext接口常用方法)
        • [7.1 配置上下文初始化参数(web.xml)](#7.1 配置上下文初始化参数(web.xml))
        • [7.2 读取上下文参数(修改RegisterServlet)](#7.2 读取上下文参数(修改RegisterServlet))
      • [8. Servlet交互流程简单图示](#8. Servlet交互流程简单图示)
    • 三、MVC设计模式------Web应用的架构核心

深入理解Servlet与MVC

在Java Web开发体系中,Servlet、MVC设计模式和Filter是构建高性能、易维护Web应用的三大核心支柱。它们分别承担着请求处理、架构设计和请求过滤的关键职责,共同构成了Java Web应用的基础骨架。

JSP内置对象回顾🥝

1. request对象

request对象专门用于接收客户端发送的请求信息,核心方法及作用如下:

  • 获取单个参数值:String parameterValue = request.getParameter("参数名称");
  • 获取多个参数值(如复选框):String[] parameterValues = request.getParameterValues("参数名称");
  • 获取所有参数名与值的映射:Map<String,String[]> paramMap = request.getParameterMap();(注:原文档中getPrameterMap为拼写错误,正确方法名应为getParameterMap
  • 获取当前请求的URL(包含上下文路径):String uri = request.getRequestURI();
  • 获取当前会话:HttpSession session = request.getSession();
  • 获取请求转发对象:RequestDispatcher dispatcher = request.getRequestDispatcher("转发的页面");

2. response对象

response对象用于向客户端返回处理结果,核心方法及作用如下:

  • 重定向到新资源:response.sendRedirect("新的页面");(重定向会发起新的HTTP请求,URL地址会变更)
  • 设置响应状态码:response.setStatus(200);(200表示成功,404表示资源未找到,500表示服务器内部错误等)
  • 获取响应输出流(用于打印字符串):PrintWriter writer = response.getWriter();

3. session对象

session的设计初衷是跟踪当前登录用户的操作状态,其工作原理如下:

  • 用户首次请求时,未携带sessionID,服务器会创建一个唯一的session对象并分配sessionID
  • 服务器将sessionID通过Cookie写入客户端,后续用户所有请求都会携带该sessionID
  • 服务器通过sessionID识别用户身份,session中存储的均为用户私有数据
  • session默认超时时间可通过配置设置,超时后服务器会销毁该session对象

4. application对象

application对象的数据类型为ServletContext,代表Servlet运行的上下文环境,核心特性如下:

  • 上下文环境包含Servlet运行的所有环境配置,是应用级别的全局对象
  • 存储在application中的数据对整个Web应用生效,所有用户可共享
  • 常用于存储全局配置信息(如数据库连接参数、系统常量等)

5. Cookie的操作方式

Cookie用于在客户端存储少量数据,其操作遵循"请求获取、响应添加"的原则:

  • 添加Cookie(响应阶段):通过response对象完成,response.addCookie(cookie);
  • 获取Cookie(请求阶段):通过request对象完成,Cookie[] cookies = request.getCookies();(返回Cookie数组,需遍历获取目标Cookie)

6. GET请求与POST请求的区别

请求方式 参数存储位置 安全性 参数长度限制 适用场景
GET URL地址栏 较低(参数暴露) 有(由服务器/浏览器限制) 数据查询、页面跳转(无敏感信息)
POST 请求体中 较高(参数隐藏) 数据提交、登录注册(含敏感信息)

一、Servlet------Web应用的请求处理核心🥝

1. Servlet的核心概念

Servlet是运行在服务器端的Java程序,能够接收客户端的HTTP请求,执行相应的业务逻辑,并向客户端返回处理结果。

2. Servlet的体系结构

2.1 Servlet接口的核心方法

Servlet接口定义了Servlet的生命周期方法,由Servlet容器(如Tomcat)负责调用:

  • 初始化方法:public void init(ServletConfig config) throws ServletException;------Servlet实例创建后调用,用于完成初始化(如读取配置参数)
  • 获取配置信息:public ServletConfig getServletConfig();------返回当前Servlet的配置对象
  • 请求处理方法:public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;------接收并处理客户端请求,是核心业务方法
  • 获取Servlet信息:public String getServletInfo();------返回Servlet的相关信息(如作者、版本、版权)
  • 销毁方法:public void destroy();------Servlet容器关闭时调用,用于释放资源(如关闭数据库连接)
2.2 ServletConfig接口的核心方法

ServletConfig接口用于获取Servlet的初始化配置信息,核心方法如下:

  • 获取Servlet实例名称:public String getServletName();------返回web.xml中配置的<servlet-name>
  • 获取Servlet上下文:public ServletContext getServletContext();------返回当前Web应用的ServletContext对象
  • 获取指定名称的初始化参数:public String getInitParameter(String name);------返回web.xml中配置的指定名称的初始化参数值
  • 获取所有初始化参数名称:public Enumeration<String> getInitParameterNames();------返回所有初始化参数名称的枚举集合

3. Servlet案例:登录功能实现

3.1 编写LoginServlet类(实现Servlet接口)
java 复制代码
package com.cyx.jsp.servlet;

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

public class LoginServlet implements Servlet {
    private ServletConfig servletConfig;

    @Override
    public void init(ServletConfig config) throws ServletException {
        // 初始化ServletConfig对象
        this.servletConfig = config;
        // 获取Servlet实例名称并打印
        String servletName = config.getServletName();
        System.out.println("Servlet 实例的名称:" + servletName);
        // 获取所有初始化参数并打印
        Enumeration<String> initParameterNames = config.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            String initParameterName = initParameterNames.nextElement();
            String initParameterValue = config.getInitParameter(initParameterName);
            System.out.println("Servlet 初始化参数 " + initParameterName + ":" + initParameterValue);
        }
    }

    @Override
    public ServletConfig getServletConfig() {
        // 返回ServletConfig对象
        return servletConfig;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        // 处理客户端登录请求
        System.out.println("Servlet 处理请求");
    }

    @Override
    public String getServletInfo() {
        // 返回Servlet相关信息
        return "Login Servlet";
    }

    @Override
    public void destroy() {
        // 销毁Servlet时执行
        System.out.println("Servlet 销毁");
    }
}
3.2 配置web.xml文件

web.xml是Servlet的核心配置文件,用于注册Servlet实例并配置请求映射:

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">
    <display-name>ServletApp</display-name>

    <!--Servlet 实例配置-->
    <servlet>
        <!-- Servlet 实例的名称(需与servlet-mapping中名称一致)-->
        <servlet-name>loginServlet</servlet-name>
        <!-- Servlet 的全类名(包名+类名)-->
        <servlet-class>com.cyx.jsp.servlet.LoginServlet</servlet-class>
        <!-- 初始化参数配置 -->
        <init-param>
            <param-name>characterEncoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </servlet>

    <!--Servlet 实例与请求地址的映射配置-->
    <servlet-mapping>
        <servlet-name>loginServlet</servlet-name>
        <!-- 匹配的请求地址(客户端通过该地址访问Servlet)-->
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

    <!--session 超时配置(单位:分钟)-->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
</web-app>
🐦‍🔥web.xml配置详解🐦‍🔥

上面这段配置是 Servlet 在 web.xml 中的核心注册与映射配置,用于告诉服务器"哪个 Servlet 处理哪个请求地址"。下面逐一解释各部分含义及命名规则:

1. <servlet> 标签:注册 Servlet 实例

作用:向服务器声明一个 Servlet 实例,指定其名称、对应的 Java 类,以及初始化参数。

子标签 含义 能否随意起名?
<servlet-name> 给当前 Servlet 起一个唯一标识名称 (如 loginServlet),需与下面 <servlet-mapping> 中的名称一致,否则无法映射。 可以自定义,但必须唯一 (同一 web.xml 中不能有重复的 <servlet-name>),建议见名知意(如处理登录的叫 loginServlet)。
<servlet-class> 指定 Servlet 对应的全类名 (包名 + 类名,如 com.cyx.jsp.servlet.LoginServlet),服务器通过这个路径找到对应的 Java 类并加载。 不能随意起名!必须与实际 Java 类的包名和类名完全一致(包括大小写),否则服务器会报"类找不到"错误。
<init-param> 配置当前 Servlet 的初始化参数 (可选),如编码格式、配置项等,Servlet 可通过 ServletConfig 获取这些参数。 <param-name> 可自定义(如 characterEncoding),<param-value> 按需求设置(如 UTF-8),但参数名建议与业务相关。
2. <servlet-mapping> 标签:映射请求地址

作用:将上面注册的 Servlet 与客户端的请求地址绑定,告诉服务器"当收到某个请求时,交给哪个 Servlet 处理"。

子标签 含义 能否随意起名?
<servlet-name> 关联的 Servlet 名称,必须与 <servlet> 中定义的 <servlet-name> 完全一致,否则映射失败。 不能随意改,必须和对应 <servlet> 的名称保持一致。
<url-pattern> 指定客户端访问该 Servlet 的请求路径 (如 /login),客户端通过 http://服务器地址:端口/上下文路径/url-pattern 访问(例如 http://localhost:8080/myapp/login)。 可以自定义,但有规则: - 必须以 / 开头(如 /login/user/add); - 支持通配符(如 /* 匹配所有请求,/user/* 匹配 /user 下的所有请求); - 建议与业务相关(如登录用 /login,注册用 /register)。
3.3 编写登录页面(index.jsp)
jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML>
<html>
<head>
    <title>登录页面</title>
</head>
<body>
<!-- 表单提交地址为/login,请求方式为POST -->
<form action="login" method="post">
    <div>
        <input type="text" name="username" placeholder="请输入用户名">
    </div>
    <div>
        <input type="password" name="password" placeholder="请输入密码">
    </div>
    <div>
        <input type="submit" value="登录">
    </div>
</form>
</body>
</html>
3.4 测试结果与生命周期验证

启动Tomcat服务器,访问index.jsp并提交登录请求,观察控制台输出:

  • 首次访问时,控制台打印:
  • 多次提交请求时,仅打印Servlet 处理请求(说明Servlet实例为单例,仅初始化一次)
  1. 关闭Tomcat服务器时,控制台打印Servlet 销毁(说明Servlet与容器共存亡)

4. Servlet的生命周期详解

通过上述测试,可明确Servlet的完整生命周期由以下四个阶段组成,全程由Servlet容器管理:

  1. 实例化:客户端首次发送请求时,Servlet容器创建Servlet实例(单例模式,整个应用仅一个实例)
  2. 初始化 :实例创建后,容器立即调用init()方法,完成初始化操作(仅执行一次)
  3. 请求处理 :每次客户端发送请求,容器调用service()方法处理请求(可执行多次)
  4. 销毁 :Servlet容器关闭或应用卸载时,容器调用destroy()方法释放资源(仅执行一次)[跟随容器共存亡]

5. JSP的本质

JSP(Java Server Pages)是简化的Servlet,其本质是Servlet,工作原理如下:

  • 客户端请求JSP页面时,Servlet容器(如Tomcat)会将JSP文件编译为Java类(.java文件)
  • 编译后的Java类继承自org.apache.jasper.runtime.HttpJspBase(该类继承自HttpServlet)
  • 最终编译为.class文件并加载运行,处理请求并返回响应结果

JSP与Servlet的核心区别:

  • JSP侧重页面内容展示,允许在HTML中嵌入Java代码,适合构建视图层
  • Servlet侧重业务逻辑处理,通过Java代码动态生成HTML,适合构建控制层

二、请求处理与响应机制

1. 请求与响应的体系结构

2. ServletRequest接口常用方法

ServletRequest接口定义了通用的请求处理方法,核心方法如下:

  • 操作请求属性(用于请求转发时的数据传递):
    • 获取属性值:Object getAttribute(String attributeName);
    • 设置属性值:void setAttribute(String attributeName, Object attributeValue);(注:原文档中attributeVaue为拼写错误,正确参数名为attributeValue
    • 移除属性:void removeAttribute(String attributeName);
    • 获取所有属性名:Enumeration<String> getAttributeNames();
  • 操作请求参数:
    • 获取单个参数值:String getParameter(String parameterName);
    • 获取多个参数值:String[] getParameterValues(String parameterName);
    • 获取所有参数名:Enumeration<String> getParameterNames();
    • 获取参数映射:Map<String, String[]> getParameterMap();
  • 字符编码处理:
    • 获取字符编码:String getCharacterEncoding();
    • 设置字符编码:void setCharacterEncoding(String charset) throws UnsupportedEncodingException;(需在读取参数前设置,否则无效)
  • 流操作(读取请求体数据):
    • 获取字符流:BufferedReader getReader() throws IOException;(仅能读取请求体数据,与字节流互斥)
    • 获取字节流:ServletInputStream getInputStream() throws IOException;(仅能读取请求体数据,与字符流互斥)
  • 其他核心方法:
    • 获取Servlet上下文:ServletContext getServletContext();
    • 获取请求转发对象:RequestDispatcher getRequestDispatcher(String path);
2.1 ServletRequest接口用法示例
java 复制代码
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("请求的字符集编码需要在读取请求信息之前进行设置,否则设置的字符集编码格式将不生效");
    // 获取并打印默认字符编码
    System.out.println("请求字符集编码:" + servletRequest.getCharacterEncoding());
    // 设置字符编码为UTF-8
    servletRequest.setCharacterEncoding("UTF-8");
    System.out.println("请求字符集编码:" + servletRequest.getCharacterEncoding());

    // 通过字符流读取请求体数据(POST请求适用)
    BufferedReader reader = servletRequest.getReader();
    System.out.println("开始读取请求参数信息");
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
    System.out.println("请求参数信息读取完毕");
    System.out.println("================");

    // 获取请求中的属性数据
    System.out.println("开始获取请求中存储的数据");
    Enumeration<String> attributeNames = servletRequest.getAttributeNames();
    while (attributeNames.hasMoreElements()) {
        String attributeName = attributeNames.nextElement();
        Object attributeValue = servletRequest.getAttribute(attributeName);
        System.out.println(attributeName + " => " + attributeValue);
    }
    System.out.println("请求中存储的数据获取完毕");
    System.out.println("================");

    // 方式一:通过Enumeration获取请求参数
    System.out.println("方式一:开始获取请求参数信息");
    Enumeration<String> parameterNames = servletRequest.getParameterNames();
    while (parameterNames.hasMoreElements()) {
        String parameterName = parameterNames.nextElement();
        String parameterValue = servletRequest.getParameter(parameterName);
        System.out.println(parameterName + " => " + parameterValue);
    }
    System.out.println("方式一:请求参数信息获取完毕");
    System.out.println("================");

    // 方式二:通过Map获取请求参数
    System.out.println("方式二:开始获取请求参数信息");
    Map<String, String[]> parameterMap = servletRequest.getParameterMap();
    parameterMap.forEach((k, values) -> System.out.println(k + " => " + Arrays.toString(values)));
    System.out.println("方式二:请求参数信息获取完毕");
    System.out.println("请求所使用的上下文路径:" + servletRequest.getServletContext().getContextPath());
}
  • POST请求测试

  • GET请求测试

  • 结论

使用GET方式发送的请求,只能通过getParameter 方法获取;使用POST方式发送的请求,只能使用流来获取。这是因为使用GET方式发送的请求,参数在URL地址中,解析这些参数的时候将其存放在一个Map集合中,因此可以直接获取。而POS方式发送的请求,参数在请求体中,这部分内容只能通过流来读取,然后再进行处理。

2.2 GET与POST请求的参数获取差异

通过测试可得出以下结论:

  • **GET请求:**参数存储在URL地址栏中,Servlet容器会自动解析参数并存储在Map集合中,可通过getParameter()getParameterValues()等方法直接获取
  • **POST请求:**参数存储在请求体中,需通过getReader()getInputStream()读取请求体数据,手动解析参数

3. ServletResponse接口常用方法

ServletResponse接口定义了通用的响应处理方法,核心方法如下:

  • 字符编码与内容类型处理:
    • 获取字符编码:String getCharacterEncoding();
    • 设置字符编码:void setCharacterEncoding(String charset);
    • 获取内容类型:String getContentType();
    • 设置内容类型:void setContentType(String contentType);(如text/html;charset=utf-8,同时指定内容类型和字符编码)
  • 流操作(向客户端输出数据):
    • 获取字节流(用于下载文件):ServletOutputStream getOutputStream() throws IOException;
    • 获取字符流(用于输出HTML、字符串等):PrintWriter getWriter() throws IOException;
3.1 ServletResponse接口用法示例

在Servlet的service方法中追加响应处理代码:

java 复制代码
// 响应字符编码处理
System.out.println("响应的字符集编码:" + servletResponse.getCharacterEncoding());
servletResponse.setCharacterEncoding("UTF-8");
System.out.println("响应的字符集编码:" + servletResponse.getCharacterEncoding());

// 响应内容类型处理
System.out.println("响应的内容类型:" + servletResponse.getContentType());
servletResponse.setContentType("text/html;charset=utf-8");
System.out.println("响应的内容类型:" + servletResponse.getContentType());

// 通过PrintWriter向客户端输出内容
PrintWriter writer = servletResponse.getWriter();
writer.print("登录请求已处理");
writer.flush(); // 刷新流,确保数据发送
writer.close(); // 关闭流

测试结果:

4. HttpServletRequest接口常用方法

HttpServletRequest接口针对HTTP协议扩展了请求处理方法,核心方法如下:

  • Cookie操作:Cookie[] getCookies();(获取客户端发送的所有Cookie)
  • 请求头操作:
    • 获取指定请求头:String getHeader(String headerName);
    • 获取所有请求头名称:Enumeration<String> getHeaderNames();
  • 请求信息获取:
    • 获取请求方式:String getMethod();(返回GET、POST、PUT、DELETE等)
    • 获取上下文路径:String getContextPath();(返回Web应用的根路径)
    • 获取会话:HttpSession getSession();(获取或创建Session)
    • 获取请求地址:String getRequestURI();(返回包含上下文路径的请求地址)

5. HttpServletResponse接口常用方法

HttpServletResponse接口针对HTTP协议扩展了响应处理方法,核心方法如下:

  • Cookie操作:void addCookie(Cookie cookie);(向客户端添加Cookie)
  • 错误响应:
    • 发送错误状态码和信息:void sendError(int status, String errorMsg) throws IOException;
    • 发送错误状态码:void sendError(int status) throws IOException;
  • 重定向:void sendRedirect(String redirectURL) throws IOException;(重定向到指定URL)
  • 响应头操作:
    • 设置响应头:void setHeader(String headerName, String headerValue);
    • 添加响应头:void addHeader(String headerName, String headerValue);(与setHeader的区别:addHeader可添加多个同名头,setHeader会覆盖同名头)
  • 设置响应状态码:void setStatus(int status);

6. HttpServlet的核心方法

HttpServlet是HTTP协议专用的Servlet抽象类,重写了service方法,核心逻辑如下:

  • 重写service(ServletRequest req, ServletResponse res):将请求和响应对象强转为HttpServletRequest和HttpServletResponse,调用重载的service(HttpServletRequest req, HttpServletResponse res)方法
  • 重载service(HttpServletRequest req, HttpServletResponse res):根据请求方式(GET、POST、PUT、DELETE等),调用对应的doXxx方法(如doGetdoPost
  • 常用doXxx方法:
    • doGet(HttpServletRequest req, HttpServletResponse res):处理GET请求
    • doPost(HttpServletRequest req, HttpServletResponse res):处理POST请求
    • doPut(HttpServletRequest req, HttpServletResponse res):处理PUT请求
    • doDelete(HttpServletRequest req, HttpServletResponse res):处理DELETE请求
6.1 实战:注册功能实现(继承HttpServlet)
java 复制代码
package com.cyx.jsp.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;

public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求头信息
        System.out.println("开始获取请求头信息");
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = req.getHeader(headerName);
            System.out.println(headerName + " => " + headerValue);
        }
        System.out.println("请求头信息获取完毕");

        // 获取请求基本信息
        System.out.println("请求方式:" + req.getMethod());
        System.out.println("请求地址:" + req.getRequestURI());
        System.out.println("请求的上下文路径:" + req.getContextPath());
        System.out.println("==================");

        // 获取请求参数
        System.out.println("开始读取请求参数");
        Map<String, String[]> parameterMap = req.getParameterMap();
        parameterMap.forEach((k, values) -> System.out.println(k + " => " + Arrays.toString(values)));
        System.out.println("请求参数读取完毕");
        System.out.println();

        // 构建响应
        System.out.println("响应开始");
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print("注册请求已经处理");
        writer.flush();
        writer.close();
    }
}
6.2 编写注册页面(register.jsp)
jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML>
<html>
<head>
    <title>注册页面</title>
</head>
<body>
<form action="createUser" method="post">
    <div>
        <input type="text" name="username" placeholder="请输入用户名">
    </div>
    <div>
        <input type="password" name="password" placeholder="请输入密码">
    </div>
    <div>
        <input type="submit" value="注册">
    </div>
</form>
</body>
</html>
6.3 配置web.xml(添加注册Servlet映射)
xml 复制代码
<servlet>
    <servlet-name>registerServlet</servlet-name>
    <servlet-class>com.cyx.jsp.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>registerServlet</servlet-name>
    <url-pattern>/createUser</url-pattern>
</servlet-mapping>

注册后,控制台的运行结果如下:

7. ServletContext接口常用方法

ServletContext(上下文对象)是应用级别的全局对象,核心方法如下:

  • 获取上下文路径:String getContextPath();(返回Web应用的根路径)
  • 获取资源绝对路径:String getRealPath(String path);(根据相对路径获取服务器上的绝对路径)
  • 操作上下文初始化参数(在web.xml中配置的全局参数):
    • 获取指定参数值:String getInitParameter(String parameterName);
    • 获取所有参数名:Enumeration<String> getInitParameterNames();
  • 操作上下文属性(全局共享数据):
    • 获取属性值:Object getAttribute(String attributeName);
    • 设置属性值:void setAttribute(String attributeName, Object attributeValue);
    • 移除属性:void removeAttribute(String attributeName);
    • 获取所有属性名:Enumeration<String> getAttributeNames();
7.1 配置上下文初始化参数(web.xml)
xml 复制代码
<context-param>
    <param-name>characterEncoding</param-name>
    <param-value>UTF-8</param-value> <!-- 原文档中"UFT-8"为拼写错误,正确编码为"UTF-8" -->
</context-param>
7.2 读取上下文参数(修改RegisterServlet)
java 复制代码
@Override
public void init(ServletConfig config) throws ServletException {
    super.init(config); // 继承HttpServlet时需调用父类init方法
    System.out.println("开始读取上下文参数信息");
    ServletContext servletContext = config.getServletContext();
    Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
    while (initParameterNames.hasMoreElements()) {
        String initParameterName = initParameterNames.nextElement();
        String initParameterValue = servletContext.getInitParameter(initParameterName);
        System.out.println(initParameterName + " => " + initParameterValue);
    }
}

8. Servlet交互流程简单图示

三、MVC设计模式------Web应用的架构核心

1. MVC的核心概念

**MVC(Model-View-Controller)**是一种经典的软件架构模式,将应用程序分为三个核心组件,实现职责分离:

  • Model(模型):持有应用程序的所有数据、状态和业务逻辑,独立于视图和控制器。模型负责数据的存储、验证和处理,是应用程序的核心。
  • View(视图):用于呈现模型中的数据,提供用户交互界面。视图仅负责数据展示,不包含业务逻辑,可根据模型数据动态更新。
  • Controller(控制器):位于视图和模型之间,负责接收用户输入,解析输入并调用模型处理数据,最后将处理结果传递给视图展示。

2. MVC模式的核心优点

  • 解耦性强:模型与视图分离,修改视图不会影响模型,修改模型也不会影响视图,提高了代码的可维护性。
  • 复用性高:一个模型可对应多个视图(如同一组数据可通过列表、图表等多种形式展示),模型可独立移植到其他平台。
  • 开发效率高:开发人员可分工协作,前端开发者专注于视图设计,后端开发者专注于模型和业务逻辑开发。
  • 扩展性好:新增功能时,可单独扩展模型、视图或控制器,无需修改其他组件。

3. JSP中的MVC实现

在JSP Web应用中,MVC的三个组件对应如下:

  • Controller(控制器):Servlet------接收请求、调用模型处理数据、转发请求到视图
  • View(视图):JSP页面------展示模型数据,提供用户交互界面
  • Model(模型):Java Bean------封装数据和业务逻辑,如User类、Product类等
3.1 应用:用户信息展示功能(MVC完整实现)
(1)编写Model(User类,Java Bean)
java 复制代码
package com.cyx.jsp.pojo;

public class User {
    private String username;
    private String name;
    private String sex;
    private int age;

    // getter方法
    public String getUsername() {
        return username;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public int getAge() {
        return age;
    }

    // setter方法
    public void setUsername(String username) {
        this.username = username;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // toString方法(原文档中缺少右大括号,已补充)
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }
}
(2)编写Controller(UserInfoServlet,Servlet)
java 复制代码
package com.cyx.jsp.servlet;

import com.cyx.jsp.pojo.User;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class UserInfoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 模拟业务逻辑处理(如从数据库查询用户信息)
        User user = new User();
        user.setUsername("admin");
        user.setName("管理员");
        user.setSex("男");
        user.setAge(20);

        // 2. 设置响应格式和编码
        resp.setContentType("text/html;charset=utf-8");
        resp.setCharacterEncoding("UTF-8");

        // 3. 将模型数据传递给视图(此处直接输出,实际开发中可通过请求转发传递给JSP)
        PrintWriter writer = resp.getWriter();
        writer.print("用户信息:" + user.toString());
        writer.flush();
        writer.close();
    }
}
(3)编写View(user.jsp,视图页面)
jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>显示用户信息</title>
</head>
<body>
<!-- 点击链接发送GET请求到UserInfoServlet -->
<a href="showUserInfo">显示用户信息</a>
</body>
</html>
(4)配置web.xml(注册UserInfoServlet)
xml 复制代码
<servlet>
    <servlet-name>userInfoServlet</servlet-name>
    <servlet-class>com.servlet.UserInfoServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>userInfoServlet</servlet-name>
    <url-pattern>/showUserInfo</url-pattern>
</servlet-mapping>

启动服务器,访问user.jsp,测试结果如下:


如果我的内容对你有帮助,请 点赞 , 评论 , 收藏 。创作不易,大家的支持就是我坚持下去的动力!

相关推荐
黑岚樱梦1 小时前
操作系统第五章学习
学习
IDOlaoluo1 小时前
apache-maven-3.9.9-bin.zip 使用步骤(超简单版)
java·maven·apache
曹牧1 小时前
Java:list<map<string,sting>>与C#互操作
java·c#·list
卷到起飞的数分1 小时前
23.Maven高级——私服
java·maven
ゞ 正在缓冲99%…1 小时前
2025.9.24华为软开
java·算法·华为
Zzzzzxl_1 小时前
互联网大厂Java/Agent面试实战:JVM、Spring Boot、微服务与RAG全栈问答
java·jvm·springboot·agent·rag·microservices·vectordb
cmdch20171 小时前
AWS亚马逊
java
Qiuner1 小时前
Spring Boot 机制四: AOP 代理机制源码级深度解析(JDK / CGLIB 全链路)
java·spring boot·后端
TDengine (老段)1 小时前
TDengine 字符串函数 GROUP_CONCAT 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据