Servlet底层逻辑的一些探索

Yuan.Sn

在读Spring文档时候,经常能够看到一个高频词汇 Servlet, 大概知道是跟 Web容器相关的,但是从来没有细看其中的JAVA EE设计。正好最近闲来无事,探索一下 Servlet相关的设计模式。

何为Servlet?

我们都知道,如果一个服务映射到了公网就需要进行http传输,而http传输就会涉及到一些繁杂的外部通讯规则,并且连接数量一上来,还要去进程管理、动态加载... 。大道至简,我们coder们还是要focus在业务逻辑本身的。因此,Sun Microsystems公司在 1997 年 正式封装出来了用于web传输的 Servlet 类,可以用过简单的对象调用,实现 http下的 Request , Respond 及其连接管理的便捷调用。

image
image

Servlet 架构

一个 Http请求、发送流进入java程序后 会严格遵守 Servlet 下的 Request-Response Model。模型主要有3个主要部分组成:Web服务器、Servlet 容器、请求客户端

image
image

Servlet Web 服务器 —— Nginx

何为 Web 服务器?Web server 可以把他看作一个简单处理静态文件的服务器,主要可以起到类似于网关的作用,对文件进行中转转发。

image
image

Servlet容器 —— Tomcat

为何需要Servlet 容器?Servelt是一套标准的 JEE framework 编写规范,有着完整的生命周期,为了不用亲自配置 生成与销毁,需要一个特定的容器进行管理。

image
image

一些Servlet的方法&&组件

ServletContext

ServletContext 可以理解为整个Web应用的"全局对象",每个应用有且只有一个实例。生命周期从应用启动到关闭,可以在所有Servlet之间共享数据。

ServletConfig

ServletConfig 是每个Servlet的"私有配置对象",用于获取该Servlet的初始化参数和基本信息。

ServletRequest && ServletResponse

ServletRequestServletResponse 是处理HTTP请求和响应的核心对象,Spring MVC中的各种注解底层都是操作这两个对象。

HttpServletRequest 主要有四个 核心功能:

  • 获取请求参数(getParameter / getParameterValues
  • 获取请求头(getHeader
  • 获取Session(getSession
  • 获取请求路径(getRequestURI / getRequestURL
1
2
3
4
5
6
7
8
9
// Servlet 写法
String name = request.getParameter("name");
String userAgent = request.getHeader("User-Agent");
HttpSession session = request.getSession();

// Spring 对应写法
public String demo(@RequestParam String name,
@RequestHeader("User-Agent") String userAgent,
HttpSession session) { }

HttpServletResponse 主要有5个核心功能:

  • 设置响应类型(setContentType
  • 输出响应数据(getWriter / getOutputStream
  • 重定向(sendRedirect
  • 设置状态码(setStatus
  • 添加Cookie(addCookie
1
2
3
4
5
6
7
8
9
// Servlet 写法
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"name\":\"test\"}");

// Spring 对应写法
@ResponseBody
public User getUser() {
return new User("test"); // Jackson自动序列化为JSON
}

Servlet Filter

Filter是Servlet规范的核心组件,可以在请求到达Servlet之前和响应返回客户端之前进行拦截处理,可以进行数据的检验、日志的记录、跨域处理...。

image
image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
请求: Client -> Filter1 -> Filter2 -> Servlet
响应: Servlet -> Filter2 -> Filter1 -> Client
**/

@WebFilter("/*") // 拦截所有请求
public class LoggingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {

// 请求前处理
System.out.println("请求进入: " + ((HttpServletRequest)request).getRequestURI());

// 调用下一个Filter或Servlet(核心!)
chain.doFilter(request, response);

// 响应后处理
System.out.println("响应返回,耗时: " + duration + "ms");
}
}

Servlet Listener

Listener(监听器)用于监听Web应用中的各种事件,比如应用启动、Session创建、请求开始等。

Servelt在Spring Boot下的封装

传统Java生态下,需要通过 Servlet, Filter, ServletContextListener来处理网络请求。但是有了 Spring Boot,就可以通过 注释的方式,把这些 BEAN 注入到程序当中了。感觉这个也没什么好说的,一直在用 非常熟练。

image
image


参考资料

Comments