当前位置: 首页 > news >正文

java基础filter servlet interceptor controller之间的关系

servlet

Servlet是运行在Web服务器上的Java类。它们主要用于处理HTTP请求和响应。 Servlet可以接收来自客户端(例如浏览器)的HTTP请求并生成响应,这些响应通常是HTML页面、XML文档或其他格式的数据。Servlet通常被设计用来扮演Web应用的控制器或中心位置。Servlet 是用于创建动态 Web 内容的 Java 程序。在 Java EE(Java Enterprise Edition)平台上,Servlet 是服务器端组件,运行在 Web 服务器或应用服务器上。Servlet 的主要作用是处理客户端(通常是 Web 浏览器)发送的请求,并生成响应。

理解Servlet需要注意以下几点:

  1. Servlet是Java编写的。
  2. Servlet 是运行在 Web 服务器中的 Java 类。
  3. Servlet 继承了 javax.servlet.Servlet 接口并实现了该接口提供的方法。其中最重要的两个方法是 doGet() 和 doPost(),它们分别用于处理 HTTP GET 和 POST 请求。
  4. Servlet 可以通过对象化地使用 HttpServletRequest 和 HttpServletResponse 对象来访问 Web 客户端的请求信息和响应信息。
  5. Servlet 执行速度快,比 CGI 要快得多。一个 Servlet 可以为多个客户端请求提供服务,而不必像 CGI 一样每次都重新启动进程。

总之,Servlet是Java编写的Web服务器组件,用于处理HTTP请求和生成响应。Servlet极大地简化了基于Web的应用程序的开发,提高了性能和可扩展性。

下面是一些关于 Servlet 的关键点:

  1. 运行环境:Servlet 运行在支持 Java 的 Web 服务器或应用服务器上,如 Apache Tomcat、Jetty、GlassFish 等。

  2. 生命周期

    • 加载和初始化:Servlet 容器(Web 服务器或应用服务器)在首次接收请求时加载 Servlet 类,并调用 init() 方法进行初始化。
    • 处理请求:每次接收请求时,容器会创建一个新的线程,并调用 Servlet 的 service() 方法。这个方法会根据请求类型(GET、POST 等)进一步调用 doGet()doPost() 等方法。
    • 销毁:当容器决定卸载 Servlet 时,会调用 destroy() 方法,进行资源清理。
  3. 工作流程

    • 客户端发送 HTTP 请求到服务器。
    • 服务器将请求转发给对应的 Servlet。
    • Servlet 处理请求,执行业务逻辑。
    • Servlet 生成响应(如 HTML、JSON 等)并返回给客户端。
  4. Servlet API:Java Servlet API 提供了一组接口和类,用于创建 Servlet 应用程序。常用的类和接口包括:

    • HttpServlet:所有 HTTP 协议的 Servlet 类都应该扩展自这个类。
    • HttpServletRequest:封装了客户端请求信息。
    • HttpServletResponse:用于生成并发送响应给客户端。
  5. 优点

    • 高效:Servlet 由 Java 编写,具有跨平台特性,并且在性能上通常优于 CGI(Common Gateway Interface)。
    • 扩展性和灵活性:由于是基于 Java 编写的,Servlet 可以方便地集成其他 Java 库和技术。
    • 安全性:Java 本身提供了一些安全机制,如垃圾回收、类型安全等,使得 Servlet 在安全性方面也有一定优势。

Servlet 通常与 JSP(JavaServer Pages)结合使用,JSP 负责视图层,Servlet 负责控制层和业务逻辑处理。通过这种分层设计,可以更好地组织和维护 Web 应用程序。

servlet和spring中controller的联系

Servlet 和 Spring 中的 Controller 都是用于处理 Web 请求的服务器端组件,但它们有一些关键的区别和联系:

Servlet

  • 原理:Servlet 是 Java EE 的基础组件,用于处理 HTTP 请求和响应。每个 Servlet 类都继承自 HttpServlet 类,并重写 doGet()doPost() 等方法来处理不同类型的 HTTP 请求。
  • 使用:直接编写和配置 Servlet 需要编写大量的样板代码和配置,尤其是在大型项目中,手动管理这些 Servlet 会变得复杂。

Spring Controller

  • 原理:Spring 中的 Controller 是 Spring MVC 框架的一部分,简化了 Web 应用的开发。Controller 类中定义的处理方法通过注解(如 @RequestMapping@GetMapping@PostMapping 等)来映射到特定的 HTTP 请求路径。
  • 使用:Spring MVC 提供了很多自动化和便利功能,比如依赖注入、自动配置等,使得开发更加简洁和高效。开发者只需专注于业务逻辑,而不用关心底层的 Servlet 配置。

联系

  1. 底层实现:Spring MVC 的底层仍然依赖于 Servlet。Spring 的 DispatcherServlet 是一个特殊的 Servlet,它作为前端控制器(Front Controller)接收所有请求,然后将这些请求分发给不同的 Controller 方法进行处理。
  2. 简化开发:Spring MVC 通过抽象和简化 Servlet 的使用,使开发者不必直接处理低层的 Servlet 细节。DispatcherServlet 帮助处理了许多标准任务,比如请求路由、参数解析、视图解析等。
  3. 配置:在 Spring 应用中,web.xml(或等效的 Java 配置类)中通常会有一个配置 DispatcherServlet 的部分,这是 Spring MVC 框架的入口点。

示例代码

Servlet 示例:

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html");PrintWriter out = response.getWriter();out.println("<h1>Hello, Servlet!</h1>");}
}

Spring Controller 示例:

@Controller
public class HelloController {@GetMapping("/hello")public String hello(Model model) {model.addAttribute("message", "Hello, Spring MVC!");return "hello"; // 视图名,视图解析器会处理}
}

在 Spring MVC 中,你定义一个 DispatcherServlet,它会自动将请求转发到合适的 Controller 方法,并处理响应。通过这种方式,Spring MVC 简化了 Web 应用的开发,使得代码更加简洁和可维护。

filter、interceptor、controller之间的关系

在 Spring 框架中,FilterInterceptorController 是处理 HTTP 请求的三个不同层次的组件,它们各自的职责和使用场景如下:

Filter

  • 位置:位于最外层,属于 Servlet 规范的一部分,在 Servlet 容器中配置。
  • 作用:对进入应用的所有 HTTP 请求和响应进行预处理和后处理。
  • 典型用途:用于处理与请求和响应相关的通用任务,如日志记录、认证、跨域处理、请求压缩等。
  • 执行时机:在 DispatcherServlet 之前和之后执行。

示例:

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 预处理System.out.println("Filter is invoked before");chain.doFilter(request, response);// 后处理System.out.println("Filter is invoked after");}
}

Interceptor

  • 位置:位于 Spring MVC 的中间层,在 DispatcherServlet 之后,Controller 之前和之后。
  • 作用:拦截并处理具体的请求,在处理请求之前、请求处理之后以及视图渲染之前进行操作。
  • 典型用途:用于检查用户会话、处理权限验证、记录性能日志等。
  • 执行时机:在 Controller 方法调用之前和之后,以及视图渲染之前。

示例:

public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("Interceptor: preHandle");return true; // 返回 true 继续处理,返回 false 中断请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("Interceptor: postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("Interceptor: afterCompletion");}
}

配置:

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");}
}

Controller

  • 位置:位于请求处理的核心层,具体处理业务逻辑。
  • 作用:接收请求并返回响应,通常与服务层和数据层交互以处理业务逻辑和数据。
  • 典型用途:处理 HTTP 请求、调用业务逻辑、返回视图或数据。
  • 执行时机:在 Interceptor 之后执行。

示例:

@Controller
public class MyController {@GetMapping("/hello")public String hello(Model model) {model.addAttribute("message", "Hello, Spring MVC!");return "hello"; // 视图名,视图解析器会处理}
}

总结关系

  • Filter:最外层,用于通用的请求和响应处理,在 DispatcherServlet 之前执行。
  • Interceptor:中间层,特定于 Spring MVC,用于对特定请求进行预处理和后处理,在 DispatcherServlet 之后,Controller 之前和之后执行。
  • Controller:核心层,负责具体的业务逻辑处理和响应生成。

整个请求处理流程可以总结为:

  1. 客户端请求发送到服务器。
  2. Filter进行预处理。
  3. DispatcherServlet分发请求。
  4. Interceptor进行预处理。
  5. Controller处理请求并返回数据或视图。
  6. Interceptor进行后处理。
  7. Filter进行后处理。
  8. 服务器响应发送到客户端。

为什么有了filter,还需要interceptor?两者有什么区别?

Filter 和 Interceptor 虽然都可以用于拦截和处理 HTTP 请求,但它们在设计目的、使用场景和实现细节上有一些重要的区别。下面详细说明两者的区别及各自的优势。

Filter

  • 标准:属于 Java Servlet 规范的一部分,不依赖于 Spring 框架。
  • 作用范围:可以拦截所有进入应用的 HTTP 请求和响应,包括静态资源请求。
  • 典型用途:用于处理与请求和响应相关的通用任务,如日志记录、认证、跨域处理、请求压缩等。
  • 执行时机:在 DispatcherServlet 之前和之后执行。
  • 配置方式:通过 web.xml 文件或使用注解 @WebFilter 进行配置。

示例:

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 预处理System.out.println("Filter is invoked before");chain.doFilter(request, response);// 后处理System.out.println("Filter is invoked after");}
}

Interceptor

  • 标准:属于 Spring 框架的一部分,特定于 Spring MVC。
  • 作用范围:仅拦截由 Spring MVC 处理的请求,不包括静态资源请求。
  • 典型用途:用于处理与业务逻辑相关的任务,如检查用户会话、权限验证、记录性能日志等。
  • 执行时机:在 DispatcherServlet 之后,Controller 之前和之后,以及视图渲染之前执行。
  • 配置方式:通过 Spring 配置类或 XML 文件进行配置。

示例:

public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("Interceptor: preHandle");return true; // 返回 true 继续处理,返回 false 中断请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("Interceptor: postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("Interceptor: afterCompletion");}
}

配置:

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");}
}

主要区别

  1. 依赖框架

    • Filter:属于 Java EE 规范的一部分,可以在任何支持 Servlet 的容器中使用。
    • Interceptor:属于 Spring 框架的一部分,仅在 Spring MVC 环境中使用。
  2. 拦截范围

    • Filter:拦截所有 HTTP 请求和响应,包括静态资源。
    • Interceptor:仅拦截由 Spring MVC 处理的请求,不包括静态资源。
  3. 配置方式

    • Filter:通过 web.xml 文件或 @WebFilter 注解配置。
    • Interceptor:通过 Spring 配置类或 XML 文件配置。
  4. 执行时机

    • Filter:在 DispatcherServlet 之前和之后执行。
    • Interceptor:在 DispatcherServlet 之后,Controller 之前和之后,以及视图渲染之前执行。

为什么需要 Interceptor

  • Spring 集成:Interceptor 深度集成在 Spring MVC 框架中,可以直接访问 Spring 容器中的 bean 和其他组件,更加方便与业务逻辑和 Spring 特有功能的结合。
  • 灵活性:Interceptor 可以更细粒度地控制请求处理流程,比如在请求处理前、请求处理后、视图渲染前进行操作。
  • 方便配置:通过 Spring 的配置文件或注解,可以更方便地管理和配置拦截器,支持更复杂的拦截规则和条件。

总结

虽然 Filter 和 Interceptor 都可以用于拦截和处理 HTTP 请求,但它们各自有特定的使用场景和优势。Filter 更适合处理与请求和响应相关的通用任务,而 Interceptor 更适合与业务逻辑相关的任务,特别是在使用 Spring MVC 框架时。两者可以互补使用,以实现更灵活和强大的请求处理机制。

spring中实现filter

在 Spring 中也可以实现 Filter。Spring 提供了对 Servlet Filter 的支持,并且可以通过 Spring 配置进行管理和注入依赖。下面是如何在 Spring 应用中实现和配置 Filter 的详细说明。

实现 Filter

实现 Filter 与在标准 Servlet 容器中实现是相同的,都是通过实现 javax.servlet.Filter 接口来完成。

示例:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化代码}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 预处理System.out.println("Filter is invoked before");chain.doFilter(request, response);// 后处理System.out.println("Filter is invoked after");}@Overridepublic void destroy() {// 销毁代码}
}

在 Spring 中配置 Filter

有几种方法可以在 Spring 中配置 Filter:使用注解、在 web.xml 中配置,或者通过 Spring Boot 的 FilterRegistrationBean

方法一:使用注解

可以直接在 Filter 类上使用 @WebFilter 注解,如上示例。

方法二:使用 web.xml

在传统的 web 应用中,可以通过 web.xml 文件进行配置。

web.xml:

<filter><filter-name>myFilter</filter-name><filter-class>com.example.MyFilter</filter-class>
</filter>
<filter-mapping><filter-name>myFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
方法三:使用 Spring Boot 的 FilterRegistrationBean

如果使用 Spring Boot,可以通过 FilterRegistrationBean 来注册 Filter。

示例:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<MyFilter> loggingFilter() {FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new MyFilter());registrationBean.addUrlPatterns("/*");return registrationBean;}
}

总结

  1. Filter 实现:通过实现 javax.servlet.Filter 接口,可以在 Spring 中创建自定义的 Filter。
  2. 配置方式:可以通过注解 @WebFilterweb.xml 配置文件,或者 Spring Boot 提供的 FilterRegistrationBean 进行配置。
  3. 作用范围:无论通过哪种方式配置,Filter 都是在 DispatcherServlet 之前和之后执行,拦截所有进入应用的 HTTP 请求和响应。

在 Spring 中实现和配置 Filter 可以灵活地处理通用的请求和响应任务,同时还可以结合 Spring 的依赖注入和其他功能,使得 Filter 的开发和管理更加便捷。

传统模式-spring之前

在 Spring 出现之前,Java EE(现在称为 Jakarta EE)环境中的请求处理流程主要依赖于 Servlet 和 Filter。整个流程通常如下:

请求处理流程(没有 Spring 的情况下)

  1. 客户端请求

    • 客户端(通常是浏览器)发送一个 HTTP 请求到服务器。
  2. Web 服务器接收请求

    • Web 服务器(如 Apache Tomcat)接收到这个请求,并根据 URL 路径确定如何处理这个请求。
  3. Filter 链处理

    • 服务器首先将请求传递给一系列配置的 Filter。这些 Filter 可以对请求进行预处理(如认证、日志记录、压缩等)。
    • 每个 Filter 都实现了 javax.servlet.Filter 接口,并在 doFilter 方法中处理请求。
    • Filter 链中的每个 Filter 按照配置的顺序依次执行。每个 Filter 可以选择继续将请求传递给链中的下一个 Filter,或者在某些条件下阻止请求的进一步处理。

Filter 示例

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 预处理System.out.println("Filter is invoked before");chain.doFilter(request, response);// 后处理System.out.println("Filter is invoked after");}
}
  1. 请求到达 Servlet
    • 经过所有 Filter 之后,请求最终到达指定的 Servlet。
    • Servlet 根据请求的路径和类型(如 GET、POST)选择合适的方法进行处理(如 doGetdoPost)。

Servlet 示例

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html");PrintWriter out = response.getWriter();out.println("<h1>Hello, Servlet!</h1>");}
}
  1. Servlet 处理请求

    • Servlet 执行业务逻辑,比如读取请求参数、查询数据库、调用其他服务等。
    • 处理完请求后,Servlet 生成响应数据,通常是 HTML、JSON 或 XML 格式。
  2. 响应通过 Filter 链返回

    • Servlet 生成的响应通过 Filter 链返回。每个 Filter 还可以对响应进行后处理(如压缩响应内容、添加响应头等)。
  3. 服务器返回响应给客户端

    • 处理完成的响应通过 Web 服务器返回给客户端,客户端(浏览器)显示或处理响应内容。

流程图示

[Client]|v
[Web Server]|v
[Filter 1] --> [Filter 2] --> ... --> [Filter N]|                                      |v                                      v
[Servlet]|v
[Filter N] --> ... --> [Filter 2] --> [Filter 1]|v
[Web Server]|v
[Client]

总结

  1. 客户端请求:发送到 Web 服务器。
  2. Web 服务器接收请求:并决定交给哪个 Servlet 处理。
  3. Filter 链处理:请求先经过一系列 Filter 进行预处理。
  4. Servlet 处理请求:请求到达指定的 Servlet 进行业务逻辑处理。
  5. 响应通过 Filter 链返回:处理后的响应通过 Filter 链返回给客户端。
  6. 服务器返回响应给客户端:客户端接收到响应并进行显示或处理。

这种设计模式确保了请求和响应在到达和离开 Servlet 之前可以进行各种通用的处理任务,提供了一个灵活的机制来实现横切关注点(如安全、日志等)。

spring之后

在引入 Spring 之后,尤其是 Spring MVC 框架,这个请求处理流程变得更加结构化和模块化。Spring 提供了更高级的抽象和便利功能来处理 Web 请求。下面是有了 Spring 之后的请求处理流程。

请求处理流程(使用 Spring 后)

  1. 客户端请求

    • 客户端(通常是浏览器)发送一个 HTTP 请求到服务器。
  2. Web 服务器接收请求

    • Web 服务器(如 Apache Tomcat)接收到请求,并根据 URL 路径确定如何处理这个请求。
  3. Filter 链处理

    • 请求首先传递给配置的 Servlet Filter,这部分与之前的流程类似,Filter 可以进行预处理。
    • 如果使用 Spring Boot,可以通过 FilterRegistrationBean 来注册 Filter。

Filter 示例

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 预处理System.out.println("Filter is invoked before");chain.doFilter(request, response);// 后处理System.out.println("Filter is invoked after");}
}
  1. 请求到达 DispatcherServlet
    • DispatcherServlet 是 Spring MVC 框架的前端控制器,负责接收所有进入应用的 HTTP 请求。
    • web.xml 或 Spring Boot 配置中,所有请求路径通常会映射到 DispatcherServlet

Spring Boot 配置示例

@SpringBootApplication
public class MySpringBootApplication {public static void main(String[] args) {SpringApplication.run(MySpringBootApplication.class, args);}
}
  1. HandlerMapping

    • DispatcherServlet 使用 HandlerMapping 根据请求 URL 找到合适的处理器(通常是一个 Controller 方法)。
  2. HandlerInterceptor 链处理

    • 在找到具体的处理器之前,请求会经过一系列配置的 HandlerInterceptor 进行预处理。
    • Interceptor 可以在处理请求之前、处理请求之后以及视图渲染之前执行。

Interceptor 示例

public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("Interceptor: preHandle");return true; // 返回 true 继续处理,返回 false 中断请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("Interceptor: postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("Interceptor: afterCompletion");}
}

配置 Interceptor

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");}
}
  1. 处理请求(Controller)
    • 找到具体的处理器后,DispatcherServlet 调用对应的 Controller 方法来处理请求。
    • Controller 方法执行具体的业务逻辑,通常与服务层和数据层交互,并生成视图或数据响应。

Controller 示例

@Controller
public class MyController {@GetMapping("/hello")public String hello(Model model) {model.addAttribute("message", "Hello, Spring MVC!");return "hello"; // 视图名,视图解析器会处理}
}
  1. 视图解析与渲染

    • 如果 Controller 方法返回的是视图名,DispatcherServlet 使用 ViewResolver 解析视图,并渲染最终的视图(通常是 JSP、Thymeleaf 等)。
  2. 响应通过 Interceptor 链返回

    • 在视图渲染之前和之后,HandlerInterceptor 也可以进行后处理。
  3. 响应通过 Filter 链返回

  • 处理完成的响应通过 Filter 链返回到客户端。
  1. 服务器返回响应给客户端
  • 客户端接收到响应并进行显示或处理。

流程图示

[Client]|v
[Web Server]|v
[Filter 1] --> [Filter 2] --> ... --> [Filter N]|                                      |v                                      v
[DispatcherServlet] --> [Interceptor 1] --> [Interceptor 2] --> ... --> [Interceptor N]|                                                                  |v                                                                  v
[Controller]|v
[Interceptor N] --> ... --> [Interceptor 2] --> [Interceptor 1]|v
[Filter N] --> ... --> [Filter 2] --> [Filter 1]|v
[Web Server]|v
[Client]

总结

在 Spring 出现之后,请求处理流程变得更加模块化和结构化。DispatcherServlet 作为前端控制器,简化了请求的分发和处理逻辑。Filter 和 Interceptor 提供了强大的预处理和后处理能力,使得请求和响应的处理更加灵活和可扩展。通过这种架构,Spring MVC 提供了一个高效且易于维护的 Web 应用开发框架。

DispatcherServlet 作用

DispatcherServlet 是 Spring MVC 框架中的核心组件,被称为前端控制器(Front Controller)。它负责将所有进入应用的 HTTP 请求分发到合适的处理器(通常是控制器方法)。DispatcherServlet 提供了一个统一的请求处理入口,简化了请求分发和处理逻辑。它的作用和工作原理可以总结如下:

DispatcherServlet 的主要作用

  1. 统一入口:所有的 HTTP 请求首先由 DispatcherServlet 接收。它充当了 Web 应用的入口点,集中管理和处理所有请求。

  2. 请求分发:根据请求 URL 和 HTTP 方法,DispatcherServlet 使用 HandlerMapping 将请求分发给适当的处理器(控制器方法)。

  3. 处理链管理DispatcherServlet 调用配置的 HandlerInterceptor 进行预处理和后处理,类似于拦截器。

  4. 视图解析:在控制器处理完请求后,DispatcherServlet 使用 ViewResolver 解析视图,并进行渲染。

  5. 异常处理:统一处理应用程序中的异常,可以配置全局异常处理机制。

DispatcherServlet 的工作流程

  1. 接收请求

    • 客户端请求到达 Web 服务器后,服务器将请求转发给 DispatcherServlet
  2. HandlerMapping

    • DispatcherServlet 使用 HandlerMapping 查找与请求路径和方法匹配的处理器(控制器方法)。
  3. HandlerAdapter

    • DispatcherServlet 使用 HandlerAdapter 来执行找到的处理器。这使得处理器可以是多种类型(例如,控制器方法、注解方法等)。
  4. 执行拦截器

    • 在处理器执行前,调用配置的 HandlerInterceptorpreHandle 方法进行预处理。
    • 如果 preHandle 返回 true,则继续执行处理器;否则,处理被中断。
  5. 调用处理器

    • 执行找到的处理器(通常是控制器方法),处理请求并返回模型和视图(ModelAndView)。
  6. 执行拦截器后处理

    • 在处理器执行后,调用 HandlerInterceptorpostHandle 方法进行后处理。
  7. 视图解析与渲染

    • 使用 ViewResolver 解析处理器返回的视图名,将其转换为实际的视图对象。
    • 渲染视图,将处理结果(通常是 HTML 内容)写入响应。
  8. 完成请求

    • 调用 HandlerInterceptorafterCompletion 方法进行清理工作。
    • 将响应返回给客户端。

DispatcherServlet 的配置

在 Spring Boot 中,DispatcherServlet 自动配置并注册为应用的前端控制器,处理所有路径(/)。在传统的 Spring MVC 应用中,可以在 web.xml 文件中配置 DispatcherServlet

web.xml:

<web-app><servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
</web-app>

在 Spring Boot 中,DispatcherServlet 的配置可以通过属性文件进行定制,例如:

application.properties:

spring.mvc.servlet.path=/api

总结

DispatcherServlet 是 Spring MVC 的核心组件,提供了一个统一的请求处理机制。通过集中管理请求分发、拦截器处理、视图解析和异常处理,它简化了 Web 应用的架构,使开发者能够专注于业务逻辑的实现。

多个filter和interceptor的执行顺序

在 Spring 应用中,多个 Filter 和多个 Interceptor 之间的执行顺序是可以通过配置进行控制的。下面分别介绍它们的执行顺序及如何配置。

多个 Filter 的执行顺序

多个 Filter 的执行顺序取决于它们的注册顺序。以下是几种常见的配置方法:

使用 web.xml 配置

web.xmlFilter 的定义顺序决定了它们的执行顺序,先定义的 Filter 先执行。

<filter><filter-name>Filter1</filter-name><filter-class>com.example.Filter1</filter-class>
</filter>
<filter><filter-name>Filter2</filter-name><filter-class>com.example.Filter2</filter-class>
</filter>
<filter-mapping><filter-name>Filter1</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping><filter-name>Filter2</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
使用 Spring Boot 的 FilterRegistrationBean

通过 FilterRegistrationBean 注册 Filter 时,可以设置优先级来控制执行顺序。

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<Filter1> filter1() {FilterRegistrationBean<Filter1> registrationBean = new FilterRegistrationBean<>(new Filter1());registrationBean.setOrder(1); // 优先级,值越小越先执行return registrationBean;}@Beanpublic FilterRegistrationBean<Filter2> filter2() {FilterRegistrationBean<Filter2> registrationBean = new FilterRegistrationBean<>(new Filter2());registrationBean.setOrder(2);return registrationBean;}
}

多个 Interceptor 的执行顺序

多个 Interceptor 的执行顺序由它们在 WebMvcConfigurer 中注册的顺序决定。注册顺序即执行顺序。

配置 Interceptor 的顺序

在 Spring 配置类中,通过实现 WebMvcConfigurer 接口并在 addInterceptors 方法中注册 Interceptor,顺序即为执行顺序。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new Interceptor1()).addPathPatterns("/**");registry.addInterceptor(new Interceptor2()).addPathPatterns("/**");}
}

在上述例子中,Interceptor1 会先于 Interceptor2 执行。

执行顺序总结

  • Filter 执行顺序

    1. doFilter 方法按照注册顺序执行,先注册的 Filter 先执行。
    2. doFilter 方法中调用 chain.doFilter(request, response),表示传递给下一个 FilterServlet
  • Interceptor 执行顺序

    1. preHandle 方法按照注册顺序执行,先注册的 Interceptor 先执行。
    2. postHandleafterCompletion 方法按照注册顺序的逆序执行,即最后注册的 Interceptor 最先执行它们的 postHandleafterCompletion 方法。

执行顺序示例

假设有两个 Filter (Filter1Filter2) 和两个 Interceptor (Interceptor1Interceptor2),它们的执行顺序如下:

  • Filters:

    • Filter1doFilter 方法前半部分
    • Filter2doFilter 方法前半部分
    • ServletDispatcherServlet 处理请求
    • Filter2doFilter 方法后半部分
    • Filter1doFilter 方法后半部分
  • Interceptors:

    • Interceptor1preHandle 方法
    • Interceptor2preHandle 方法
    • Controller 处理请求
    • Interceptor2postHandle 方法
    • Interceptor1postHandle 方法
    • Interceptor2afterCompletion 方法
    • Interceptor1afterCompletion 方法

通过合理配置和理解 FilterInterceptor 的执行顺序,可以更有效地管理和处理 HTTP 请求及其生命周期中的各个环节。

默认的filter和interceptor执行顺序

如果没有显式定义执行顺序,FilterInterceptor 的执行顺序将取决于框架的默认行为和它们的加载顺序。

默认情况下的 Filter 执行顺序

  1. 在 web.xml 中定义

    • Filter 的执行顺序由它们在 web.xml 文件中的定义顺序决定。先定义的 Filter 会先执行。
    • 如果 web.xml 中的 Filter 顺序如下:
      <filter><filter-name>Filter1</filter-name><filter-class>com.example.Filter1</filter-class>
      </filter>
      <filter><filter-name>Filter2</filter-name><filter-class>com.example.Filter2</filter-class>
      </filter>
      <filter-mapping><filter-name>Filter1</filter-name><url-pattern>/*</url-pattern>
      </filter-mapping>
      <filter-mapping><filter-name>Filter2</filter-name><url-pattern>/*</url-pattern>
      </filter-mapping>
      
    • 执行顺序为:Filter1 -> Filter2 -> Servlet -> Filter2 -> Filter1
  2. 在 Spring Boot 中未定义顺序

    • 如果使用 Spring Boot 并通过 FilterRegistrationBean 注册多个 Filter,且没有设置顺序,Filter 的执行顺序由 Spring Boot 自动确定,通常是按声明的顺序执行。
    • 如果顺序没有显式设置,可能会出现意外的执行顺序,因此建议总是显式设置顺序。

默认情况下的 Interceptor 执行顺序

  1. 在 WebMvcConfigurer 中定义

    • Interceptor 的执行顺序由它们在 WebMvcConfigurer 中注册的顺序决定。先注册的 Interceptor 先执行其 preHandle 方法,postHandleafterCompletion 方法按相反的顺序执行。
    • 如果顺序如下:
      @Configuration
      public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new Interceptor1()).addPathPatterns("/**");registry.addInterceptor(new Interceptor2()).addPathPatterns("/**");}
      }
      
    • 执行顺序为:
      • Interceptor1preHandle
      • Interceptor2preHandle
      • 控制器方法执行
      • Interceptor2postHandle
      • Interceptor1postHandle
      • Interceptor2afterCompletion
      • Interceptor1afterCompletion
  2. Spring Boot 默认配置

    • Spring Boot 默认使用 Ordered 接口或 @Order 注解来确定组件的顺序。如果没有显式设置,顺序取决于组件的加载顺序和自动配置顺序。

没有显式定义顺序时的潜在问题

没有显式定义顺序可能会导致 FilterInterceptor 按不可预期的顺序执行,从而引发难以调试的问题。因此,明确设置执行顺序是一个最佳实践。

设置顺序的推荐方式

  1. 显式设置 Filter 顺序

    • 在 Spring Boot 中使用 FilterRegistrationBean 设置顺序。
      @Bean
      public FilterRegistrationBean<Filter1> filter1() {FilterRegistrationBean<Filter1> registrationBean = new FilterRegistrationBean<>(new Filter1());registrationBean.setOrder(1); // 优先级,值越小越先执行return registrationBean;
      }@Bean
      public FilterRegistrationBean<Filter2> filter2() {FilterRegistrationBean<Filter2> registrationBean = new FilterRegistrationBean<>(new Filter2());registrationBean.setOrder(2);return registrationBean;
      }
      
  2. 显式设置 Interceptor 顺序

    • WebMvcConfigurer 中注册时按照期望的顺序进行注册。
      @Configuration
      public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new Interceptor1()).addPathPatterns("/**");registry.addInterceptor(new Interceptor2()).addPathPatterns("/**");}
      }
      

通过明确设置 FilterInterceptor 的顺序,可以确保请求处理的预期行为,减少潜在的错误和调试难度。

相关文章:

  • Python 怎么注释大段
  • 操作失败——后端
  • 华为、华三交换机、路由器启用基于端口的环回检测功能配置
  • Python怎么翻译:探索Python在翻译领域的无限可能
  • gitlab将本地文件项目上传至gitlab服务
  • 微电子加速迈向后摩尔时代!复旦大学梅永丰课题组集成 DNN 与纳米薄膜技术,精准分析入射光角度
  • 计算机基础(5)——进制与进制转换
  • 明天15点!如何打好重保预防针:迎战HVV经验分享
  • python11 序列的相关操作
  • Unity 性能优化之LOD技术(十)
  • vue 将echart 下载为base64图片
  • 【计算机毕业设计】谷物识别系统Python+人工智能深度学习+TensorFlow+卷积算法网络模型+图像识别
  • 解决 Spring Cloud GateWay报错:Exceeded limit on max bytes to buffer : 262144
  • 如何把docker里的内容拷贝出来
  • 挑战你的数据结构技能:复习题来袭【6】
  • SegmentFault for Android 3.0 发布
  • __proto__ 和 prototype的关系
  • 30天自制操作系统-2
  • css选择器
  • ES10 特性的完整指南
  • ES6简单总结(搭配简单的讲解和小案例)
  • js 实现textarea输入字数提示
  • js中forEach回调同异步问题
  • laravel 用artisan创建自己的模板
  • spark本地环境的搭建到运行第一个spark程序
  • Vue.js源码(2):初探List Rendering
  • 百度小程序遇到的问题
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 一道面试题引发的“血案”
  • 栈实现走出迷宫(C++)
  • 追踪解析 FutureTask 源码
  • 自动记录MySQL慢查询快照脚本
  • 1.Ext JS 建立web开发工程
  • scrapy中间件源码分析及常用中间件大全
  • 阿里云API、SDK和CLI应用实践方案
  • 关于Android全面屏虚拟导航栏的适配总结
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • #14vue3生成表单并跳转到外部地址的方式
  • #define、const、typedef的差别
  • #Ubuntu(修改root信息)
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • (1)常见O(n^2)排序算法解析
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .net FrameWork简介,数组,枚举
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .net解析传过来的xml_DOM4J解析XML文件
  • .NET与 java通用的3DES加密解密方法
  • .pop ----remove 删除