Servlet规范 、Tomcat容器、Springmvc框架

发布于:2025-07-18 ⋅ 阅读:(14) ⋅ 点赞:(0)

Tomcat 是 Servlet 规范的实现者,而 Spring MVC 是基于此规范构建的上层框架,通过 DispatcherServlet 和配套组件,优化了原生 Servlet 开发模式的繁琐性和架构松散性问题。

什么是Servlet规范

Servlet 是 Java EE 规范(现为 Jakarta EE)。

它定义了一套处理 HTTP 请求的标准接口(API)。

JAVA EE 规范和JAVA SE规范

  • JAVA SE规范是JDK自带的,是JDK的底层规范,主要包括: java.lang java.util等等
  • JAVA EE规范一般有 servlet规范,xxx webSocket规范?

懂了,一套接口是吧!

  • 使用
    需要额外引入依赖,(如 javax.servlet:javax.servlet-api 或 jakarta.servlet:jakarta.servlet-api)才能使用

在这里插入图片描述

核心接口

注意:1.8之后,原来的核心接口包javax.servlet.Servlet 变成了jakarta.servlet.Servlet .

Servlet

servlet接口是servlet规范的最最核心的接口

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

从整体来看: Servlet 的生命周期由 init() → service() → destroy() 这三个方法定义

HttpServlet

实际应用中,我们更多的是实现HttpServlet(针对http协议提供的接口)

在这里插入图片描述

这时候,HttpServlet内容发生了一些变化,主要是关于service()-逻辑处理方法进行了进一步细化,拓展出了 doget()、dopost()…在这里插入图片描述

拓展:Servlet 和控制器

我个人理解,每个Servlet实例其实就是对应一个springmvc中的控制器(xxxController)。

早起,没有mvc模式之前,一般是用继承HttpServlet的方法去自定义一个Servlet实例。

如下,定义一个UserServlet,实现对/add/edit 请求的处理

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
import com.google.gson.Gson; // 用于JSON处理,需要添加Gson依赖

@WebServlet(name = "UserServlet", urlPatterns = {"/add", "/edit"})
public class UserServlet extends HttpServlet {
    
    // 模拟数据存储
    private final DataStorage dataStorage = new DataStorage();
    private final Gson gson = new Gson();

	init()
	destory()

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        
        try {
            // 根据请求路径分发处理
            String path = request.getServletPath();
            switch (path) {
                case "/add":
                    handleAdd(request, response);
                    break;
                case "/edit":
                    handleEdit(request, response);
                    break;
                default:
                    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                    out.print(gson.toJson(new ApiResponse(false, "无效的请求路径")));
            }
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            out.print(gson.toJson(new ApiResponse(false, "服务器错误: " + e.getMessage())));
        } finally {
            out.flush();
        }
    }

    private void handleAdd(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        // 从请求中获取JSON数据
       
       ....


        sendJsonResponse(response, new ApiResponse(true, "添加成功", addedItem));
    }

    private void handleEdit(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
       	
       	....


        // 返回成功响应
        sendJsonResponse(response, new ApiResponse(true, "更新成功", result));
    }

    private void sendJsonResponse(HttpServletResponse response, Object data) 
            throws IOException {
        PrintWriter out = response.getWriter();
        out.print(gson.toJson(data));
    }

 
  
}

所以,对比能理解 : 每个servlet有且只有一个实例了吧

ServletRequest

HttpServletRequest

ServletResponse

HttpServletResponse

Filter

HttpSession

会话级别的全局变量
范围: 一个会话期间,所以是可以跨线程的

Servlet 规范本身并未直接定义线程级别的共享变量接口(如类似 ThreadLocal 的 API)。它的核心接口(如 ServletRequest、HttpSession)关注的是请求和会话范围的数据存储,而非线程绑定。

容器: 以tomcat为例

规范是规范,但是实现需要多方配合实现

在实际应用中:

在这里插入图片描述

Tomcat 实现了 Servlet 规范中的关键部分。

注意: 当然,HttpServlet则是开发者负责实现的,但是servlet的管理还是tomcat做的

在这里插入图片描述
这是一个纯tomcat环境中的请求处理过程,它主要负责

  1. 请求的封装: 封装成httpServletRequest
  2. 请求的映射: 通过其内部的Mapper组件 ,映射的来源由开发者通过web.xml或@webServlet指定
  3. 管理 Servlet全生命周期
    4。。。

tomcat同步阻塞

Tomcat 的默认处理模式确实是同步阻塞I/O,这是由其线程模型决定的:

  • 每个请求一个线程:Tomcat 使用线程池处理请求,每个请求从连接到响应完成都占用一个线程

  • 线程资源有限:最大线程数由 maxThreads 参数控制(默认 200)

原生Servlet的演化 --MVC

如果按照实现原生实现HttpServlet的方式去开发,会发现

  1. 代码冗余(尤其是在 init() 和destory()中),相似的请求处理逻辑(如参数解析、响应生成)需要反复编写
  2. 逻辑处理中,返回的响应,视图和数据不做区分,很难看

SpringMvc框架

为了改变以上痛点,进而演化除了MVC设计模式,

  • Model:封装业务数据和逻辑
  • View:负责展示层
  • Controller:协调模型和视图

在此模式上,开发出了现代框架 SpringMVC

原生的servlet开发变成了这样

@Controller
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;
    
    // 处理 /users/add 的POST请求
    @PostMapping("/add")
    public String addUser(@Valid User user, Model model) {
        userService.save(user);
        model.addAttribute("message", "添加成功");
        return "user/list"; // 视图名称
    }
    
    // 处理 /users/{id} 的GET请求
    @GetMapping("/{id}")
    @ResponseBody
    public ResponseEntity<User> getUser(@PathVariable String id) {
        return ResponseEntity.ok(userService.getUser(id));
    }
}

主要特征:

  1. 注解驱动开发,取代xml配置
  2. 框架自动管理生命周期
  3. 自动绑定方法参数,而不是手动从request解析参数
  4. 将原生的多个Servlet,变成只有一个DispatcherServlet入口
    等等等等。

springmvc & tomcat

“Spring MVC 在 Tomcat 的 Servlet 容器基础上,通过 DispatcherServlet 和配套组件(如 HandlerMapping)重构了请求映射和业务处理流程,但底层网络 I/O、线程管理等仍依赖 Tomcat 的原生能力。”

在这里插入图片描述
tomcat依旧是该干嘛干嘛!

注意: 对tomcat来讲,它不感知DispatcherServlet内部,它只知道这是一个标准的HttpServlet,只要调用service()方法就行了


网站公告

今日签到

点亮在社区的每一天
去签到