杰瑞科技汇

JSP Servlet教程,如何快速入门与实战?

JSP & Servlet 完整教程

目录

  1. 第一部分:基础概念

    JSP Servlet教程,如何快速入门与实战?-图1
    (图片来源网络,侵删)
    • 什么是 Web 应用?
    • 什么是 Servlet?
    • 什么是 JSP?
    • 为什么 Servlet + JSP 是经典组合?
    • 运行环境:Servlet 容器
  2. 第二部分:开发环境搭建

    • 准备工作:JDK, Maven/Gradle
    • 核心工具:IDE (IntelliJ IDEA / Eclipse)
    • 选择 Servlet 容器:Tomcat
    • 在 IDEA 中配置 Tomcat 和创建 Web 项目
  3. 第三部分:Servlet 核心技术

    • 创建第一个 Servlet:HelloServlet
    • Servlet 生命周期 (init, service, destroy)
    • HttpServletRequest 对象:获取请求信息
    • HttpServletResponse 对象:设置响应信息
    • Servlet 映射与 web.xml 配置
  4. 第四部分:JSP 核心技术

    • 创建第一个 JSP 页面:hello.jsp
    • JSP 三大指令 (page, include, taglib)
    • JSP 动作标签 (jsp:include, jsp:forward, jsp:param)
    • JSP 内置对象(9个核心对象)
    • EL 表达式语言
    • JSTL (JSP Standard Tag Library)
  5. 第五部分:Servlet + JSP 协作 (MVC 模式)

    JSP Servlet教程,如何快速入门与实战?-图2
    (图片来源网络,侵删)
    • 什么是 MVC 模式?
    • 在 Servlet + JSP 中实现 MVC
    • 请求处理流程详解
    • 实战案例:用户登录注册
  6. 第六部分:高级主题与最佳实践

    • 会话管理 (HttpSession)
    • 过滤器
    • 监听器
    • 文件上传
    • 项目结构优化

第一部分:基础概念

什么是 Web 应用?

Web 应用(Web Application)是可以通过浏览器访问的应用程序,它运行在服务器上,通过 HTTP 协议与客户端(浏览器)进行通信,淘宝、京东、博客系统等。

什么是 Servlet?

Servlet (Server Applet) 是运行在 Web 服务器端的 Java 小程序,它是 Java EE(现在叫 Jakarta EE)规范的一部分。

  • 核心作用:接收和响应来自客户端的请求。
  • 工作方式:服务器(如 Tomcat)会加载 Servlet,并为每个请求创建一个线程来调用 Servlet 的 service() 方法。
  • 本质:一个实现了 javax.servlet.Servlet 接口的 Java 类。

你可以把 Servlet 想象成一个“请求处理器”,专门负责处理业务逻辑。

JSP Servlet教程,如何快速入门与实战?-图3
(图片来源网络,侵删)

什么是 JSP?

JSP (JavaServer Pages) 是一种用于创建动态 Web 页面的技术。

  • 核心作用:展示数据(生成 HTML 页面)。
  • 工作方式:JSP 文件看起来像 HTML,但可以嵌入 Java 代码,当服务器第一次请求一个 JSP 时,容器会将其翻译成一个 Servlet,然后像处理普通 Servlet 一样编译并执行。
  • 本质:最终也是一个 Servlet。

你可以把 JSP 想象成一个“视图模板”,专门负责页面展示。

为什么 Servlet + JSP 是经典组合?

它们各司其职,实现了“关注点分离”的思想,这正是 MVC(Model-View-Controller)模式的核心。

  • Servlet (Controller - 控制器):

    • 接收用户请求。
    • 调用业务逻辑层处理请求。
    • 选择合适的 JSP 页面进行响应。
    • 职责:控制流程,不关心页面长什么样。
  • JSP (View - 视图):

    • 负责页面的展示。
    • 从 Servlet 中获取数据并渲染成 HTML。
    • 职责:展示数据,不关心数据从哪里来。
  • JavaBean / POJO (Model - 模型):

    • 封装数据(如 User 对象)。
    • 包含业务逻辑(有时也会放在专门的 Service 层)。
    • 职责:数据和业务逻辑。

这种分工使得代码结构清晰、易于维护和扩展。

运行环境:Servlet 容器

Servlet 和 JSP 不能直接运行,需要一个 Servlet 容器来管理和执行它们。

  • 什么是 Servlet 容器? 它是一个 Web 服务器(如 Apache Tomcat, Jetty, JBoss/WildFly),负责加载 Servlet、处理 HTTP 请求、响应请求,并提供 Servlet 运行所需的环境。
  • 最常用的容器Apache Tomcat,它是开源的、轻量级的,非常适合学习和开发。

第二部分:开发环境搭建

准备工作

  • JDK (Java Development Kit): 确保已安装 JDK 8 或更高版本。
  • 构建工具: Maven 或 Gradle,推荐 Maven,用于管理项目依赖(如 Servlet API、JSTL 等)和构建项目。
  • IDE (集成开发环境): IntelliJ IDEA (Ultimate/Community 版均可) 或 Eclipse,强烈推荐 IDEA,对 Web 项目支持非常好。

核心工具:IDE (IntelliJ IDEA)

我们以 IntelliJ IDEA 为例进行讲解。

选择 Servlet 容器:Tomcat

  • 访问 Apache Tomcat 官网 下载最新稳定版(如 Tomcat 10)。
  • 解压到你喜欢的目录,D:\dev\apache-tomcat-10.1.x
  • 熟悉目录结构:
    • bin: 启动/关闭脚本 (.sh / .bat)。
    • conf: 配置文件 (如 server.xml)。
    • webapps: 部署 Web 应用的目录,你把项目打包成 .war 文件放这里,或者直接把项目文件夹放进来。
    • logs: 日志文件。

在 IDEA 中配置 Tomcat 和创建 Web 项目

  1. 配置 Tomcat:

    • File -> Settings -> Build, Execution, Deployment -> Application Servers
    • 点击 号,选择 Tomcat Server -> Local
    • 指定 Tomcat 的安装路径,点击 OK
  2. 创建新项目:

    • File -> New -> Project
    • 选择 Java Enterprise
    • 在右侧设置:
      • Application server: 选择你刚刚配置好的 Tomcat。
      • Template: 选择 Web application
      • Add sample code: 勾选,这样会自动生成一个 index.jsp 和一个 HelloServlet,方便你快速上手。
    • 点击 Create
  3. 项目结构:

    • 项目创建后,你会看到一个类似下面的结构:
      your_project_name
      ├── src
      │   └── main
      │       ├── java         # 存放 Java 源代码 (Servlet, JavaBean)
      │       ├── resources   # 存放配置文件
      │       └── webapp      # 存放 Web 资源
      │           ├── WEB-INF  # 重要!存放私有资源,不能被外部直接访问
      │           │   ├── lib  # 存放项目依赖的 jar 包
      │           │   └── web.xml # Web 应用的部署描述符 (可选,但推荐)
      │           └── index.jsp # 默认首页
      └── pom.xml             # Maven 项目文件,管理依赖

第三部分:Servlet 核心技术

创建第一个 Servlet:HelloServlet

  1. src/main/java 下创建一个包,com.example.controller
  2. 在该包下创建一个 Java 类 HelloServlet
  3. 让它继承 HttpServlet,并重写 doGetdoPost 方法。
package com.example.controller;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
// @WebServlet 是一个注解,用来替代 web.xml 的配置
// value 指定访问的 URL
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 设置响应内容类型和字符编码
        response.setContentType("text/html;charset=UTF-8");
        // 2. 获取输出流,向客户端写数据
        // PrintWriter out = response.getWriter();
        // out.println("<h1>Hello, Servlet!</h1>");
        // 3. 转发到 JSP 页面 (更常见的做法)
        request.setAttribute("message", "你好,Servlet!");
        // 请求转发,浏览器地址栏不会变
        request.getRequestDispatcher("/WEB-INF/views/hello.jsp").forward(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // POST 请求会调用 doGet
        doGet(request, response);
    }
}

Servlet 生命周期

Servlet 的生命周期由容器管理,主要包括三个阶段:

  1. 初始化 (init):
    • 当 Servlet 第一次被请求时,容器会创建它的实例,并调用 init(ServletConfig config) 方法。
    • 这个方法只执行一次,用于执行一次性的初始化操作(如加载数据库驱动、创建连接池等)。
  2. 处理请求 (service):
    • 每次客户端请求该 Servlet 时,容器会调用 service(ServletRequest req, ServletResponse res) 方法。
    • HttpServletservice 方法会根据请求的 HTTP 方法(GET, POST 等)调用相应的 doGet, doPost, doPut 等方法。
    • 这个方法可以被调用多次(每次请求)。
  3. 销毁 (destroy):
    • 当 Web 应用被卸载或服务器关闭时,容器会调用 destroy() 方法。
    • 这个方法也只执行一次,用于释放资源(如关闭数据库连接)。

HttpServletRequest 对象

代表客户端的请求信息,常用方法:

  • String getParameter(String name): 获取表单单值参数。
  • String[] getParameterValues(String name): 获取表单多值参数(如复选框)。
  • getRequestDispatcher(String path): 获取请求转发器。
  • setAttribute(String name, Object o): 设置请求范围内的属性。
  • getAttribute(String name): 获取请求范围内的属性。
  • getMethod(): 获取请求方法 (GET/POST)。
  • getRequestURI(): 获取请求的 URI。

HttpServletResponse 对象

代表服务器的响应信息,常用方法:

  • getWriter(): 获取字符输出流,用于输出文本内容。
  • getOutputStream(): 获取字节输出流,用于输出二进制内容(如图片、文件)。
  • setContentType(String type): 设置响应内容的 MIME 类型(如 text/html, application/json)。
  • sendRedirect(String location): 重定向到新的 URL。注意:会改变浏览器地址栏。

Servlet 映射与 web.xml 配置

将一个 Servlet 和一个 URL 关联起来有两种方式:

  • 使用注解(推荐) 在 Servlet 类上使用 @WebServlet 注解。

    @WebServlet("/hello") // 简单映射
    // 或
    @WebServlet(urlPatterns = {"/hello", "/hi"}, name = "HelloServlet") // 复杂映射
    public class HelloServlet { ... }
  • 使用 web.xml 配置(传统方式)WEB-INF/web.xml 文件中配置。

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.example.controller.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

第四部分:JSP 核心技术

创建第一个 JSP 页面:hello.jsp

webapp 目录下创建 hello.jsp 文件。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>First JSP</title>
</head>
<body>
    <h1>Hello, JSP!</h1>
    <p>当前时间: <%= new java.util.Date() %></p>
</body>
</html>

通过浏览器访问 http://localhost:8080/your_project_name/hello.jsp 即可看到效果。

JSP 三大指令

指令用于设置整个 JSP 页面的属性,语法为 <%@ directive ... %>

  • page 指令: 定义页面的全局属性。

    • contentType: 设置 MIME 类型和字符编码。<%@ page contentType="text/html;charset=UTF-8" %>
    • pageEncoding: JSP 文件本身的编码。
    • import: 导入 Java 类。<%@ page import="java.util.List" %>
    • isELIgnored: 是否忽略 EL 表达式。
  • include 指令: 在翻译阶段将其他文件的内容静态包含进来,内容会被合并成一个 Servlet。

    • <%@ include file="header.jsp" %>
  • taglib 指令: 引入标签库,如 JSTL。

    • <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

JSP 动作标签

动作标签在请求处理阶段起作用,用于控制 JSP 的执行流程。

  • jsp:include: 动态包含,在运行时包含另一个页面的输出,两个页面是独立的 Servlet。
    • <jsp:include page="footer.jsp" />
  • jsp:forward: 请求转发,将请求转发给另一个资源,浏览器地址栏不变。
    • <jsp:forward page="/another.jsp" />
  • jsp:param: 用于向被包含或转发的页面传递参数。
    • ` `

JSP 内置对象

JSP 容器会自动创建一些对象,可以直接在 JSP 页面中使用,无需声明,最核心的9个:

对象 类型 描述
request HttpServletRequest 封装 HTTP 请求信息
response HttpServletResponse 封装 HTTP 响应信息
session HttpSession 封装用户会话信息
application ServletContext 封装整个 Web 应用的上下文信息
config ServletConfig 封装 Servlet 的配置信息
out JspWriter 用于向客户端输出内容
pageContext PageContext 当前页面的上下文,可以获取其他所有内置对象
exception Throwable 封装页面发生的异常信息 (在 isErrorPage="true" 的页面中可用)
page Object 指向当前 JSP 页面本身 (this 的引用),很少使用

EL 表达式语言

EL (Expression Language) 是一种简化在 JSP 中访问数据的表达式,语法 ${expression}

  • 作用:替代 JSP 中的脚本片段(<%= ... %>)。
  • 优点:语法更简洁,可读性更好。
  • 示例:
    • 获取请求参数:${param.name} (对应 request.getParameter("name"))
    • 获取请求属性:${user.name} (对应 request.getAttribute("user").getName())
    • 获取会话属性:${sessionScope.user.name}
    • 获取应用属性:${applicationScope.appConfig}
    • 遍历集合 (配合 JSTL):
      <c:forEach items="${list}" var="item">
          <p>${item}</p>
      </c:forEach>

JSTL (JSP Standard Tag Library)

JSTL 是一套标准标签库,用于消除 JSP 页面上的 Java 代码,使页面更纯粹。

  • 使用前: 在 pom.xml 中添加依赖。
    <dependency>
        <groupId>jakarta.servlet.jsp.jstl</groupId>
        <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.web</groupId>
        <artifactId>jakarta.servlet.jsp.jstl</artifactId>
        <version>2.0.0</version>
    </dependency>
  • 核心标签库 (c): 最常用。
    • <c:set>: 设置变量。
    • <c:if test="${condition}">...</c:if>: 条件判断。
    • <c:choose>, <c:when>, <c:otherwise>: 多条件分支。
    • <c:forEach>: 循环遍历。
    • <c:redirect>: 重定向。

第五部分:Servlet + JSP 协作 (MVC 模式)

这是整个教程的核心,我们通过一个“用户登录”的例子来演示完整的 MVC 流程。

场景:用户输入用户名和密码,点击登录,如果正确,显示欢迎页面;如果错误,返回登录页面并提示错误。

项目结构:

src/main/java
├── com.example.controller
│   └── LoginServlet.java
├── com.example.model
│   └── User.java
└── com.example.service
    └── UserService.java
src/main/webapp
├── WEB-INF
│   └── views
│       ├── login.jsp
│       └── welcome.jsp
└── index.jsp (重定向到 login.jsp)

步骤 1: Model (模型) - User.javaUserService.java

User.java (JavaBean, 封装数据)

package com.example.model;
public class User {
    private String username;
    private String password;
    // 构造器、Getter 和 Setter
    public User() {}
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    // ... getter and setter methods
}

UserService.java (业务逻辑层)

package com.example.service;
import com.example.model.User;
public class UserService {
    public boolean checkLogin(User user) {
        // 这里应该是查询数据库等复杂逻辑
        // 为了演示,我们写死一个正确的用户名和密码
        return "admin".equals(user.getUsername()) && "123456".equals(user.getPassword());
    }
}

步骤 2: View (视图) - JSP 页面

login.jsp (登录表单)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>登录</title>
</head>
<body>
    <h1>用户登录</h1>
    <!-- 使用 EL 表达式显示错误信息 -->
    <c:if test="${not empty errorMsg}">
        <p style="color: red;">${errorMsg}</p>
    </c:if>
    <form action="login" method="post">
        用户名: <input type="text" name="username"><br>
        密码:   <input type="password" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

welcome.jsp (欢迎页面)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>欢迎</title>
</head>
<body>
    <h1>欢迎, ${sessionScope.user.username}!</h1>
    <p>登录成功!</p>
    <a href="logout">退出登录</a>
</body>
</html>

步骤 3: Controller (控制器) - LoginServlet.java

package com.example.controller;
import com.example.model.User;
import com.example.service.UserService;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private UserService userService = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 如果是 GET 请求,直接转发到登录页面
        request.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 2. 封装数据到 Model
        User user = new User(username, password);
        // 3. 调用 Service 处理业务逻辑
        if (userService.checkLogin(user)) {
            // 登录成功
            // 将用户信息存入 session
            request.getSession().setAttribute("user", user);
            // 转发到欢迎页面
            request.getRequestDispatcher("/WEB-INF/views/welcome.jsp").forward(request, response);
        } else {
            // 登录失败
            // 设置错误信息
            request.setAttribute("errorMsg", "用户名或密码错误!");
            // 转发回登录页面
            request.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(request, response);
        }
    }
}
  1. 用户在 login.jsp 输入用户名密码,点击登录。
  2. 表单以 POST 方式提交到 LoginServlet (/login)。
  3. LoginServletdoPost 方法被调用。
  4. 它获取表单数据,创建 User 对象。
  5. 调用 UserServicecheckLogin 方法进行验证。
  6. 如果成功:
    • User 对象存入 session
    • 使用 request.getRequestDispatcher().forward() 转发到 welcome.jsp
    • welcome.jsp 使用 EL 从 sessionScope 中取出用户名并显示。
  7. 如果失败:
    • 设置一个错误信息到 request 范围。
    • 转发回 login.jsp
    • login.jsp 使用 EL 显示 requestScope 中的错误信息。

第六部分:高级主题与最佳实践

会话管理 (HttpSession)

  • 作用: 跟踪一个用户在整个网站中的多次请求,记录登录状态、购物车信息等。
  • 获取: HttpSession session = request.getSession();
    • request.getSession(true): session 不存在,则创建一个。
    • request.getSession(false): session 不存在,则返回 null
  • 常用方法:
    • session.setAttribute(String name, Object value): 存储属性。
    • session.getAttribute(String name): 获取属性。
    • session.invalidate(): 销毁整个 session,通常用于用户退出登录。
  • 原理: 服务器为每个会话创建一个唯一的 ID (Session ID),并通过 Cookie 发送给浏览器,后续浏览器请求时会带上这个 Session ID,服务器就能识别出是哪个用户。

过滤器

  • 作用: 对请求和响应进行预处理和后处理,可以统一处理字符编码、权限验证、日志记录等。
  • 特点: 可以拦截对某一组资源的请求。
  • 实现:
    1. 创建一个类实现 javax.servlet.Filter 接口。
    2. 实现 doFilter 方法。
    3. doFilter 方法中,调用 chain.doFilter(request, response) 之前做预处理,之后做后处理。
    4. 使用 @WebFilterweb.xml 注册过滤器。

示例:字符编码过滤器

@WebFilter("/*") // 拦截所有请求
public class EncodingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 设置请求和响应的编码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        // 放行,让请求继续向下走
        chain.doFilter(request, response);
    }
    // ... init, destroy 方法
}

监听器

  • 作用: 监听 Web 应用中某些重要事件的发生,并做出相应处理,应用启动、会话创建/销毁、属性变化等。
  • 常用监听器:
    • ServletContextListener: 监听 Web 应用的启动和销毁,常用于在应用启动时加载初始化数据、创建数据库连接池。
    • HttpSessionListener: 监听会话的创建和销毁,可用于统计当前在线人数。

文件上传

  • 原理: 使用 multipart/form-data 编码的表单提交文件,需要第三方库来解析请求体。
  • 常用库: Apache Commons FileUpload, Servlet 3.0+ 内置支持。
  • Servlet 3.0+ 方式:
    1. 表单设置 enctype="multipart/form-data"
    2. 在 Servlet 上使用 @MultipartConfig 注解。
    3. 使用 request.getPart("fileInputName") 获取上传的文件部分。

项目结构优化

对于更复杂的项目,可以采用分层架构:

src/main/java
├── controller    # 控制层,Servlet
├── service       # 业务逻辑层
├── dao           # 数据访问层 (Data Access Object),负责数据库操作
├── model         # 模型层,JavaBean
└── util          # 工具类

这种结构使得每一层的职责更加单一,代码复用性更高。


恭喜你!通过这份教程,你已经掌握了 JSP + Servlet 的核心知识,并理解了经典的 MVC 开发模式。

  • 回顾: Servlet 负责“控制”,JSP 负责“展示”,通过请求转发和重定向将它们连接起来,并使用 Model (JavaBean) 来传递数据。
  • 优点: 简单、直观,非常适合理解 Web 应用的基本工作原理。
  • 缺点: 在大型项目中,JSP 中仍然会混有少量逻辑,代码量较大,维护性不如现在的现代框架。

下一步学习方向:

  1. 框架化: 学习 Spring MVC,它在 Servlet 之上构建,提供了更强大的功能,如 IoC (控制反转)、AOP (面向切面编程),是目前 Java Web 开发的主流。
  2. 前后端分离: 学习 Spring Boot + Vue.js/React/Angular 的前后端分离模式,前端负责 UI 和交互,后端只提供 RESTful API,这是目前更流行、更灵活的开发方式。

JSP + Servlet 是 Java Web 开发的基石,掌握了它,你学习更高级的框架将会事半功倍,祝你学习愉快!

分享:
扫描分享到社交APP
上一篇
下一篇