Servlet的继承树,生命周期和线程不安全

1、Servlet 继承树

java 复制代码
3)Servlet的继承树
- Servlet接口
   public interface Servlet{
       public void init(config);
       public void service(request,response);
       public void destroy();
   }
- GenericServlet抽象类
   public abstract class GenericServlet implements Servlet{
       实现了init方法和destroy方法。service方法仍然保持抽象
   }
- HttpServlet抽象类 - 最初设计时,基于http协议,因此产生了HttpServlet,将来可能会基于其他协议出现其他协议下的Servlet
   public abstract class HttpServlet extends GenericServlet{
        实现了service方法。然后重载了service方法
        protected void service(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException{
            String method=request.getMethod();
            if("POST".equals(method)){
                doPost(request,response);
            }else if("PUT".equals(method)){
                doPut(...)
            }else{...
            }
        }
        细化了服务方法:
        public void doPost(){}
        public void doGet(){}
        public void doDelete(){}
        public void doPut(){}
   }

2、Servlet 生命周期

XML 复制代码
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
        </dependency>

        <dependency>
            <groupId>com.csdn</groupId>
            <artifactId>pro03-fruit-optimize</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
java 复制代码
package com.csdn.servlet;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebServlet;
import java.io.IOException;
//4、演示Servlet生命周期
@WebServlet("/h04")
public class ServletLifecycle extends GenericServlet {
    // tomcat被执行的时候,他是不会被实例化的,这样是比较合理的
    // 因为假设项目里面有一万个Servlet,tomcat在启动的时候,
    // 就要实例化一万个实例对象,但是一万个也不知道用户什么时候来访问,
    // 放在tomcat里面,就会使tomcat启动的时间拉长,延迟实例化,只执行一次
    public ServletLifecycle() {
        System.out.println("ServletLifecycle正在实例化....");
    }
    //当有请求到来时,会被执行,多次请求可以执行多次
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("ServletLifecycle正在服务....");
    }
    //请求到来时,先实例化,然后执行init方法,只执行一次,然后执行service方法
    @Override
    public void init() throws ServletException {
        System.out.println("ServletLifecycle正在初始化....");

    }
    //tomcat停止时,执行destroy方法
    @Override
    public void destroy() {
        System.out.println("ServletLifecycle正在销毁....");
    }
}
java 复制代码
4)Servlet的生命周期
- Servlet是tomcat去实例化的,不是程序员new的
- Servlet中的服务方法也不是程序员主动调用的,也是由tomcat去调用的。当有请求到来时,tomcat通过反射执行service方法
- Servlet的生命周期分为四个阶段:实例化、初始化、服务、销毁
- 默认情况下,Servlet不会随着容器的启动而被实例化,而是当第一次有人请求我的时候,我才会被实例化
  当容器停止时,容器中的Servlet实例会被销毁,destroy方法被调用

3、Servlet 线程不安全问题

java 复制代码
package com.csdn.servlet;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebServlet;
import java.io.IOException;
//5、演示线程不安全的问题
@WebServlet("/h05")
public class ThreadUnsafeServlet extends GenericServlet {
    public Integer i = 1;
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        if (i % 2 == 0) {
            System.out.print("A");
        } else {
            System.out.print("B");
        }
        i++;
    }
}
java 复制代码
- Servlet在tomcat容器中是单实例的是线程不安全的
        ① 单实例的意思是:所有客户端发过来的请求都是同一个ServletLifecycle实例来处理
            第一个用户发请求过来时,容器会去实例化servlet,然后进入服务阶段,从此之后,所有的请求到来时,直接执行服务方法
        ② 线程不安全的意思时:既然所有的请求到来时是同一个servlet实例去处理的,那么这些请求之间不能共用数据(共用变量)
            什么情况下共用变量?servlet中有成员变量,而服务方法中需要根据成员变量的值决定程序流程
            如果第一个请求到来时,执行服务方法,然后在服务方法中更改成员的值,从而就会导致其他的请求到来时流程发生变化
            小结:线程不安全的本质是:Servlet由成员变量;成员变量的值可能发生变化;业务逻辑依赖于这个变量
        ③ 如何解决线程不安全的问题:尽量避免使用成员变量;如果非要使用成员变量,那么要注意业务逻辑不要受成员变量值影响
相关推荐
vibag13 分钟前
第十六届蓝桥杯复盘
java·算法·蓝桥杯·竞赛
珹洺27 分钟前
计算机操作系统(十一)调度器/调度程序,闲逛调度与调度算法的评价指标
android·java·算法
墨着染霜华30 分钟前
JAVA8怎么使用9的List.of
java·list
编程、小哥哥1 小时前
Java求职面经分享:Spring Boot到微服务,从理论到实践
java·hadoop·spring boot·微服务·kafka
有梦想的攻城狮2 小时前
spring中的BeanFactoryAware接口详解
java·后端·spring·beanfactory
若汝棋茗2 小时前
C#在 .NET 9.0 中启用二进制序列化:配置、风险与替代方案
java·c#·.net·序列化
通达的K2 小时前
Java的常见算法和Lambda表达式
java·数据结构·算法
liubo666_2 小时前
JVM梳理(逻辑清晰)
java·jvm·后端
一刀到底2112 小时前
java 在用redis 的时候,如何合理的处理分页问题? redis应当如何存储性能最佳
java·开发语言·redis
软考真题app2 小时前
软件设计师考试三大核心算法考点深度解析(红黑树 / 拓扑排序 / KMP 算法)真题考点分析——求三连
java·开发语言·算法·软考·软件设计师