Servlet规范 、Tomcat容器、Springmvc框架
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()@Overrideprotected 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环境中的请求处理过程,它主要负责
- 请求的封装: 封装成httpServletRequest
- 请求的映射: 通过其内部的Mapper组件 ,映射的来源由开发者通过web.xml或@webServlet指定
- 管理 Servlet全生命周期
4。。。
tomcat同步阻塞
Tomcat 的默认处理模式确实是同步阻塞I/O,这是由其线程模型决定的:
-
每个请求一个线程:Tomcat 使用线程池处理请求,每个请求从连接到响应完成都占用一个线程
-
线程资源有限:最大线程数由 maxThreads 参数控制(默认 200)
原生Servlet的演化 --MVC
如果按照实现原生实现HttpServlet的方式去开发,会发现
- 代码冗余(尤其是在 init() 和destory()中),相似的请求处理逻辑(如参数解析、响应生成)需要反复编写
- 逻辑处理中,返回的响应,视图和数据不做区分,很难看
SpringMvc框架
为了改变以上痛点,进而演化除了MVC设计模式,
- Model:封装业务数据和逻辑
- View:负责展示层
- Controller:协调模型和视图
在此模式上,开发出了现代框架 SpringMVC
原生的servlet开发变成了这样
@Controller
@RequestMapping("/users")
public class UserController {@Autowiredprivate 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}")@ResponseBodypublic ResponseEntity<User> getUser(@PathVariable String id) {return ResponseEntity.ok(userService.getUser(id));}
}
主要特征:
- 注解驱动开发,取代xml配置
- 框架自动管理生命周期
- 自动绑定方法参数,而不是手动从request解析参数
- 将原生的多个Servlet,变成只有一个DispatcherServlet入口
等等等等。
springmvc & tomcat
“Spring MVC 在 Tomcat 的 Servlet 容器基础上,通过 DispatcherServlet 和配套组件(如 HandlerMapping)重构了请求映射和业务处理流程,但底层网络 I/O、线程管理等仍依赖 Tomcat 的原生能力。”
tomcat依旧是该干嘛干嘛!
注意: 对tomcat来讲,它不感知DispatcherServlet内部,它只知道这是一个标准的HttpServlet,只要调用service()方法就行了