【Servlet 基础】

本文详细介绍了Servlet的基础知识,包括Servlet概述、执行原理、生命周期、Servlet 3.0注解配置以及IDEA与Tomcat的相关配置。Servlet是一个服务器端的小程序,通过实现Servlet接口并在Tomcat中配置,可以处理HTTP请求。Servlet生命周期主要涉及init、service和destroy方法,而在Servlet 3.0中可以通过注解简化配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【Servlet 基础】

引入:
要想用户通过浏览器实现访问动态资源,得到不同的结果需要在服务器的动态资源部分,编写具有逻辑性的 Java 代码,Java 代码封装在 Java 类中,浏览器实际访问找到的是这种封装的 Java 类,这种 Java 类不是自己运行的,依赖于服务器才能运行,没有主方法(main 方法),相当于是 Tomcat 执行它
这时这个 Java 类就需要遵守一定的规则(在 Java 中就可以理解为接口,这个接口就是 Servlet),才能被 Tomcat 所识别并执行

一、 Servlet 概述

概念:全称为:server applet,是运行在服务器端的小程序
Servlet 就是一个接口,定义了 Java 类被浏览器访问到(Tomcat 识别)的规则
将来我们可以自定义一个类,实现 Servlet 接口,复写方法,进行使用

1. 版本对应

版本对应

  • Servlet 、JSP 、EL 表达式显示的是最佳版本

(使用版本一定要保持一致,否则代码无法运行)

2. 快速入门

  1. 创建 JavaEE 项目 参照此文章创建 Web 项目内容
  2. 定义一个类,实现 Servlet 接口
  3. 实现接口中的抽象方法
  4. 配置 Servlet
  • 定义一个类,实现 Servlet 接口,实现接口中的抽象方法,在此只实现一个提供服务的接口
import javax.servlet.*;
import java.io.IOException;

public class ServletTest01 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    
    // 提供服务的接口
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello , Servlet !");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

  • 配置 Servlet,在 webapp/WEB-INF/web.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>test01</servlet-name>
        <servlet-class>com.example.tomcat_test.ServletTest01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>test01</servlet-name>
        <url-pattern>/test01</url-pattern> <!-- 在原有设定的路径下添加访问路径,注意斜杠 -->
    </servlet-mapping>
</web-app>
  • 在浏览器中输入:http://localhost:8080/tomcat_test/test01 (依照自己设定的访问路径进行访问),访问的页面结果为空白,但是 IDEA 控制台输出结果(页面刷新一次,提供服务的方法会被调用一次)
  • 查看当前默认页(index.jsp)的访问路径: 运行 → 编辑配置 → 部署
    (可以进行自定义设置,最好与项目名称保持一致),如下图中的:应用程序上下文
    访问路径

二、 Servlet 详解

1. Servlet 执行原理

实体分为三个部分:

  • 编写的实现 Servlet 接口的类
  • web.xml 配置文件
  • 浏览器

执行部分:

  1. 浏览器部分:
    1. 通过:http://localhost:8080/,找到某个主机的某个应用程序(Tomcat)
    2. 通过:tomcat_test/ 找到 Tomcat 中部署的项目
    3. 再通过:/test01 (资源名称)进行访问
  2. 配置文件部分:
    1. 找到与配置文件 web.xml 中的 <url-pattern> 吻合部分
    2. 再次通过相同的 <servlet-name> 标签,找到之下配置的 <servlet-class> ,其中写入的全类名,利用反射路径访问
  3. Tomcat 部分:
    1. 之后 Tomcat 将全类名对应的字节码文件加载进内存(Class.forName();
    2. 创建对象(clazz.newInstance();
    3. 调用方法

总结:

  1. 当服务器接收到客户端浏览器的请求后,会解析请求的 URL 路径,获取访问的 Servlet 的资源路径
  2. 查找 web.xml 配置文件,是否有对应的 <url-pattern> 标签体内容
  3. 如果有,则再找到对应的 <servlet-name> 全类名
  4. Tomcat 会将字节码文件加载进内存,并且创建其对象
  5. 调用具体方法

2. Servlet 方法(生命周期)

编写的类实现 Servlet 接口后,必须重写五个方法,这些方法中就包含着 Servlet 的生命周期

  1. 被创建:执行 init 方法,只会执行一次
  2. 提供服务:执行 service 方法,可以执行多次
  3. 被销毁:执行 destroy 方法,只会执行一次
  • 编写测试类
import javax.servlet.*;
import java.io.IOException;

public class ServletTest02 implements Servlet {
    /**
     * 初始化的方法
     * 在 Servlet 被创建时执行,只会执行一次
     * @param servletConfig
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init...初始化的方法!");
    }

    /**
     * 获取 ServletConfig 对象
     * ServletConfig :Servlet 的配置对象
     * @return
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 提供服务的方法
     * 每一次 Servlet 被访问时执行,可以执行多次
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service...提供服务的方法!");
    }

    /**
     * 获取 Servlet 的一些信息,版本、作者等等信息
     * @return
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 销毁的方法
     * 在服务器正常关闭时执行,只会执行一次
     */
    @Override
    public void destroy() {
        System.out.println("destroy...销毁的方法!");
    }
}
  • 配置 web.xml 文件,使用浏览器访问
    <!-- 配置 Servlet -->
    <servlet>
        <servlet-name>test02</servlet-name>
        <servlet-class>com.example.tomcat_test.ServletTest02</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>test02</servlet-name>
        <url-pattern>/test02</url-pattern> <!-- 在原有设定的路径下添加访问路径,注意斜杠 -->
    </servlet-mapping>

3. 生命周期详解

  1. 被创建:执行 init 方法,只会执行一次
    • 默认情况下, Servlet 会在第一次被访问时,被创建
    • 可以配置执行 Servlet 的创建时机:在 web.xml 配置文件中的 <servlet> 标签下进行配置
      1. 第一次被访问时创建
        <load-on-startup> 标签中的值为负数(默认值为-1)
      2. 在服务器启动时创建
        <load-on-startup> 标签中的值为0或正整数(随便的正整数,一般指定为 0~10)
    • Servlet 的 init 方法,只执行一次,说明一个 Servlet 在内存中只存在一个对象,说明 Servlet 是单例
      1. 多个用户同时进行访问时,可能存在线程安全问题
      2. 解决:尽量不要在 Servlet 中定义成员变量,即使定义了成员变量,也不要对其修改值(保持常量状态)
  2. 提供服务:执行 service 方法,可以执行多次
    • 每次访问 Servlet 是,service 方法都会被调用一次
  3. 被销毁:执行 destroy 方法,只会执行一次
    • Servlet 被销毁时执行,服务器关闭时,Servlet 被销毁
    • 只有服务器正常关闭时,才会执行 destroy 方法
    • destroy 方法在 Servlet 被销毁之前执行,一般用于释放资源
	<servlet>
        <servlet-name>test02</servlet-name>
        <servlet-class>com.example.tomcat_test.ServletTest02</servlet-class>
        <!-- 指定 Servlet 的创建时机
            1. 第一次被访问时创建
            <load-on-startup> 标签中的值为负数(默认值为-1)
            2. 在服务器启动时创建
            <load-on-startup> 标签中的值为0或正整数(随便的正整数,一般指定为 0~10)
         -->

        <load-on-startup>-1</load-on-startup>
    </servlet>

4. Servlet 3.0 注解配置

Servlet 3.0 支持注解配置,可以不需要配置文件 web.xml

步骤:

  1. 创建 JavaEE 项目,选择 Servlet 的版本 3.0 以上,可以不创建 web.xml
  2. 定义一个类,实现 Servlet 接口
  3. 复写方法
  4. 在类上使用 @WebServlet 注解,进行配置
    例如:@WebServlet("资源路径")

注解 @WebServlet 源代码:

package javax.servlet.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
    String name() default "";

    String[] value() default {};

    String[] urlPatterns() default {};

    int loadOnStartup() default -1;

    WebInitParam[] initParams() default {};

    boolean asyncSupported() default false;

    String smallIcon() default "";

    String largeIcon() default "";

    String description() default "";

    String displayName() default "";
}

使用:

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

@WebServlet(urlPatterns = "/test03") // 也可以不用写 urlPatterns,直接输入英文双引号和资源路径
public class ServletTest03 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Servlet 3.0 注解配置!");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

5. IDEA 与 Tomcat 相关配置问题

  1. IDEA 会为每一个 Tomcat 部署的项目单独建立一份配置文件,查看控制台的 log 日志:Using CATALINA_BASE: 部分的路径下即为配置文件

  2. 工作空间项目Tomcat 部署的 web 项目 区分:

    • Tomcat 真正访问的是“Tomcat 部署的 web 项目”,“Tomcat 部署的 web 项目”对应着“工作空间项目”的 web 目录下的所有资源
    • WEB-INF 目录下的资源不能被浏览器直接访问
    • 断点调试:使用“小虫子”图标(debug)启动访问

6. Servlet 的体系结构

继承自
继承自
HttpServlet 抽象类
GenericServlet 抽象类
Servlet 接口
  • GenericServlet 抽象类:将 Servlet 接口中的其他方法做了默认空实现,只将 service() 方法作为抽象方法,所以将来定义 Servlet 类时,可以继承 GenericServlet 类,实现 service() 方法即可,如果需要使用别的方法,直接复写即可
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/test05")
public class ServletTest05 extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("继承 GenericServlet 抽象类!");
    }
}

引出 HttpServlet 抽象类:
由于在实现 Servlet 类中重写 service方法必须要进行:判断请求方式

伪代码:

String method=req.getMethod();
if("GET".equals(method)){
	// get 方式获取数据
}else if("POST".equals(method)){
	// post 方式获取数据
}

而 HttpServlet 抽象类将这个方法封装为 doGet(){}doPost(){} 两个抽象方法,所以以后如果需要这种代码逻辑,直接继承 HttpServlet 抽象类,重写这两个抽象方法即可

  • HttpServlet 抽象类:对 http 协议的一种封装,简化操作
    • 定义类继承 HttpServlet 抽象类
    • 复写 doGet()doPost() 方法
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/test06")
public class ServletTest06 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet 方法!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost 方法!");
    }
}

7. Servlet 相关配置问题

  • urlpartten :Servlet 访问路径
    • 一个 Servlet 实现类可以定义多个访问路径(资源路径):@WebServlet({"/test01","/test02","/test03"})
    • 路径定义规则:
      1. /xxx :最常用
      2. /xxx/xxx :多层路径,目录结构
      3. *.do :后缀名可以随意定义,但是前面不能加 / 否则会报错
    • 关于 * 为通配符,可以随意书写
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值