第29课-Servlet基础

第29课:Servlet基础

本课目标:掌握Servlet的核心概念、生命周期、配置方式,能够独立开发动态Web应用。


一、概念讲解

1.1 什么是Servlet

Servlet是Java EE规范中用于处理HTTP请求的服务器端组件。它是运行在Web服务器(如Tomcat)上的Java程序,负责接收客户端请求并生成响应。

复制代码
┌─────────────┐      HTTP请求      ┌─────────────┐      调用      ┌─────────────┐
│   浏览器     │ ─────────────────> │   Tomcat    │ ─────────────> │   Servlet   │
│  (Client)   │ <───────────────── │  (Server)   │ <───────────── │  (Handler)  │
└─────────────┘      HTTP响应      └─────────────┘      返回      └─────────────┘

1.2 Servlet生命周期

复制代码
┌──────────────┐    ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
│   加载实例    │ -> │  init()初始化 │ -> │ service()处理 │ -> │ destroy()销毁 │
│  Class.forName│   │   仅执行一次   │ │  每次请求调用  │  │   仅执行一次   │
└──────────────┘    └──────────────┘    └──────────────┘    └──────────────┘

1.3 Tomcat安装

  1. 下载Tomcat:https://tomcat.apache.org/download-90.cgi
  2. 解压到指定目录
  3. 配置环境变量 CATALINA_HOME
  4. 启动:bin\startup.bat
  5. 访问:http://localhost:8080

二、语法格式

2.1 Servlet接口核心方法

java 复制代码
public interface Servlet {
    void init(ServletConfig config) throws ServletException;
    ServletConfig getServletConfig();
    void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
    String getServletInfo();
    void destroy();
}

2.2 HttpServlet常用方法

java 复制代码
// doGet - 处理GET请求
protected void doGet(HttpServletRequest req, HttpServletResponse res)

// doPost - 处理POST请求
protected void doPost(HttpServletRequest req, HttpServletResponse res)

// doPut - 处理PUT请求
protected void doPut(HttpServletRequest req, HttpServletResponse res)

// doDelete - 处理DELETE请求
protected void doDelete(HttpServletRequest req, HttpServletResponse res)

三、代码案例

3.1 Hello Servlet

java 复制代码
package com.example.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("HelloServlet 初始化完成");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("<h1>Hello Servlet!</h1>");
        out.println("<p>当前时间: " + new java.util.Date() + "</p>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    public void destroy() {
        System.out.println("HelloServlet 销毁");
    }
}

▶ 运行结果:

复制代码
Servlet 执行效果:
┌─────────────────────────────────────┐
│ 控制台输出:                         │
│ HelloServlet 初始化完成             │
│                                     │
│ 浏览器显示 (访问 /hello):           │
│ ┌─────────────────────────────┐    │
│ │ <h1>Hello Servlet!</h1>     │    │
│ │ <p>当前时间: 2026-09-02     │    │
│ │    10:00:00</p>             │    │
│ └─────────────────────────────┘    │
│                                     │
│ 控制台输出 (服务器关闭时):          │
│ HelloServlet 销毁                   │
└─────────────────────────────────────┘

3.2 表单处理器

java 复制代码
package com.example.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html><head><title>登录</title></head>");
        out.println("<body>");
        out.println("<h2>用户登录</h2>");
        out.println("<form method='post' action='login'>");
        out.println("用户名: <input type='text' name='username'><br>");
        out.println("密码: <input type='password' name='password'><br>");
        out.println("<input type='submit' value='登录'>");
        out.println("</form></body></html>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();

        if ("admin".equals(username) && "123456".equals(password)) {
            out.println("<h1>登录成功,欢迎 " + username + "!</h1>");
        } else {
            out.println("<h1>用户名或密码错误!</h1>");
            out.println("<a href='login'>返回登录</a>");
        }
    }
}

▶ 运行结果:

复制代码
LoginServlet 执行效果:
┌─────────────────────────────────────┐
│ GET 请求 (访问 /login):             │
│ 浏览器显示登录表单:                 │
│ ┌─────────────────────────────┐    │
│ │ <h2>用户登录</h2>            │    │
│ │ 用户名: [            ]       │    │
│ │ 密码:   [            ]       │    │
│ │        [登录]                │    │
│ └─────────────────────────────┘    │
│                                     │
│ POST 请求 (输入 admin/123456):      │
│ 浏览器显示:                         │
│ ┌─────────────────────────────┐    │
│ │ <h1>登录成功,欢迎 admin!</h1>│    │
│ └─────────────────────────────┘    │
│                                     │
│ POST 请求 (输入错误密码):           │
│ 浏览器显示:                         │
│ ┌─────────────────────────────┐    │
│ │ <h1>用户名或密码错误!</h1>   │    │
│ │ <a href='login'>返回登录</a> │    │
│ └─────────────────────────────┘    │
└─────────────────────────────────────┘

3.3 计数器应用

java 复制代码
package com.example.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/counter")
public class CounterServlet extends HttpServlet {

    private int totalCount = 0;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        // 获取Session级别的计数器
        HttpSession session = req.getSession();
        Integer sessionCount = (Integer) session.getAttribute("sessionCount");
        if (sessionCount == null) {
            sessionCount = 0;
        }
        sessionCount++;
        session.setAttribute("sessionCount", sessionCount);

        // 全局计数器
        totalCount++;

        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("<h1>访问计数器</h1>");
        out.println("<p>您的访问次数: " + sessionCount + "</p>");
        out.println("<p>总访问次数: " + totalCount + "</p>");
    }
}

▶ 运行结果:

复制代码
CounterServlet 执行效果:
┌─────────────────────────────────────┐
│ 第一次访问:                         │
│ 浏览器显示:                         │
│ ┌─────────────────────────────┐    │
│ │ <h1>访问计数器</h1>          │    │
│ │ <p>您的访问次数: 1</p>       │    │
│ │ <p>总访问次数: 1</p>         │    │
│ └─────────────────────────────┘    │
│                                     │
│ 第二次访问 (同一浏览器):            │
│ 浏览器显示:                         │
│ ┌─────────────────────────────┐    │
│ │ <h1>访问计数器</h1>          │    │
│ │ <p>您的访问次数: 2</p>       │    │
│ │ <p>总访问次数: 2</p>         │    │
│ └─────────────────────────────┘    │
│                                     │
│ 其他浏览器访问:                     │
│ 浏览器显示:                         │
│ ┌─────────────────────────────┐    │
│ │ <h1>访问计数器</h1>          │    │
│ │ <p>您的访问次数: 1</p>       │    │
│ │ <p>总访问次数: 3</p>         │    │
│ └─────────────────────────────┘    │
└─────────────────────────────────────┘

3.4 web.xml配置方式

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">

    <!-- 配置Servlet -->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.example.servlet.HelloServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- 配置Servlet映射 -->
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <!-- 欢迎页面 -->
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

四、常见错误

错误 原因 解决方案
404 Not Found URL路径配置错误 检查@WebServlet或web.xml中的url-pattern
405 Method Not Allowed 请求方法不匹配 检查是否重写了doGet/doPost
中文乱码 编码不一致 设置req.setCharacterEncoding("UTF-8")和resp.setContentType
NullPointerException Servlet未正确初始化 检查load-on-startup配置
ClassNotFoundException Servlet类路径错误 检查servlet-class的完整包名

五、课后练习

  1. 创建一个Servlet,显示当前服务器时间
  2. 创建一个Servlet,接收表单提交的姓名和年龄,显示欢迎信息
  3. 使用web.xml配置方式注册Servlet(不用注解)
  4. 实现一个简单的计算器Servlet,支持加减乘除

六、本课小结

知识点 说明
Servlet Java EE的Web组件,处理HTTP请求
生命周期 init() -> service() -> destroy()
HttpServlet 继承GenericServlet,处理HTTP协议
@WebServlet 注解方式配置Servlet,替代web.xml
Tomcat 轻量级Web服务器和Servlet容器

本课程持续更新中,欢迎关注!

相关推荐
毅炼1 小时前
不写多语言 SDK,怎么让 Python、Go、Node 服务接入注册中心?
java·后端·系统架构·gateway
2501_937860941 小时前
上篇:网络编程基础与UDP套接字编程
java·网络·计算机网络
泡海椒1 小时前
jquick-pdf 表格行列尺寸控制实战:单元格合并的可行边界
java·开发语言·pdf
Wang's Blog1 小时前
Java 项目实战: 外卖平台-后台系统登录功能开发
java·服务器·redis
海鸥-w2 小时前
spingboot定义一个全局异常处理器
java
曹牧2 小时前
Jackson 反序列化字段名不匹配
java
名字还没想好☜2 小时前
Spring Boot 优雅停机实战:等在途请求处理完再退出,配合 K8s preStop 别丢请求
java·后端·spring
摇滚侠2 小时前
《Spring Boot 3:高级与架构设计》第 1 章 Bean 与 BeanDefinition 个人理解 2
java·spring boot·笔记·后端
qq_269506752 小时前
第30课-请求与响应
java