Springboot基础------控制器、过滤器、拦截器、监视器

控制器

控制器用于接收和响应用户发送的请求,一个控制器类需要被@Controller注解:(即controller层)

@Controller
class TestController {
}

注: @RestController实际上是@Controller和@ResponseBody的简化版,被这个注解标注的控制器类的方法默认向客户端直接返回字符串。

过滤器

介绍

过滤器可以在调用控制器方法之前进行一些操作,是基于Servlet规范的。过滤器类一般放在filter包下。(过滤器是处于客户端与服务器资源文件之间的一道过滤网,帮助我们过滤一些不符合要求的请求。通常用作:
统一设置字符编码
过滤敏感字符
进行登录校验以及 url 级别的访问权限控制。
大白话:过滤器就是一道上了锁的密码门,进入都需要指定密码才能进入,密码不对就进不去)。

生命周期

主要遵循Java Servlet规范中定义的过滤器生命周期。一个实现了javax.servlet.Filter接口的类,在Spring Boot应用中作为过滤器使用时,会经历以下生命周期阶段:

  1. 初始化阶段
    init(FilterConfig filterConfig):当Servlet容器(如Tomcat)启动时,会初始化在web.xml中或通过注解配置的过滤器。此方法在过滤器实例化后立即被调用,用于执行一些初始化操作,如加载配置文件、初始化资源等。如果初始化失败,会抛出ServletException。
  2. 过滤阶段
    doFilter(ServletRequest request, ServletResponse response, FilterChain chain):此方法在每次请求到达时都会被调用。它允许过滤器对请求和响应进行预处理和后处理。在doFilter方法中,可以通过调用chain.doFilter(request, response)将请求传递给下一个过滤器或目标Servlet,也可以决定不调用此方法以中断请求处理流程。
  3. 销毁阶段
    destroy():当Servlet容器关闭或Web应用被卸载时,会调用此方法。它用于释放过滤器所占用的资源,如关闭数据库连接、释放内存等。

实现过滤器

通过@WebFilter注解实现过滤器

在springboot 启动类添加该注解@ServletComponentScan
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
public class LogbackApplication {

    public static void main(String[] args) {
        SpringApplication.run(LogbackApplication.class, args);
    }

}

创建过滤类实现Filter接口

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author zjh
 * @className AnnotateFilter
 * @date 2024/7/26
 * @description TODO
 **/


// urlPatterns 过滤路径  filterName 过滤器name
@WebFilter(urlPatterns = "/zjh/*" ,filterName = "urlFilter")
public class AnnotateFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //过滤逻辑

    }
    
    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

使用非注解方式实现过滤器(直接注入到spring中)

实现类
import javax.servlet.*;
import java.io.IOException;

/**
 * @author zjh
 * @className NoAnnotateFilter
 * @date 2024/7/26
 * @description TODO
 **/
public class NoAnnotateFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //过滤逻辑
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
Filter配置文件
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author zjh
 * @className FilterConfig
 * @date 2024/7/26
 * @description TODO
 **/
@Configuration
public class FilterConfig {
    @Bean
    public NoAnnotateFilter noAnnotateFilter(){
        return new NoAnnotateFilter();
    }


    @Bean
    public FilterRegistrationBean getFilterRegistrationBean(NoAnnotateFilter noAnnotateFilter) {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(noAnnotateFilter);
        filterRegistrationBean.setOrder(2);
        filterRegistrationBean.addUrlPatterns("/zjh/*");
        filterRegistrationBean.setName("noAnnotateFilter");
        return filterRegistrationBean;
    }

}

拦截器

介绍

是Spring MVC框架中的一个重要特性,它允许你在请求处理流程中的特定点执行自定义逻辑。拦截器主要用于在控制器(Controller)处理请求之前和之后执行一些预处理和后处理工作。拦截器的主要目的是在不修改原有代码的情况下,实现对请求和响应的统一处理。

作用

拦截器的本质上是面向切面编程 AOP,符合切面编程的关注点都可以通过拦截器来实现。它通常用于以下场景:
权限控制: 拦截器可以在请求到达处理器之前进行权限验证,从而实现对不同用户的访问控制。
日志记录: 拦截器可以在请求处理过程中记录请求和响应的详细信息,便于后期分析和调试(可实现日志的脱敏)。
接口幂等性校验: 拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。
数据校验: 拦截器可以在请求到达处理器之前对请求数据进行校验,确保数据的合法性。
缓存处理: 拦截器可以在请求处理之后对响应数据进行缓存,提高系统性能。
通用行为: 读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现)

拦截器执行顺序

当有多个拦截器时,它们的执行顺序取决于注册顺序。先注册的拦截器先执行,后注册的拦截器后执行。在请求处理过程中,拦截器的preHandle方法按注册顺序执行,而postHandle和afterCompletion方法按注册顺序的逆序执行。
当有多个拦截器时,它们的执行流程如下:

执行所有拦截器的preHandle方法,按注册顺序执行。如果某个拦截器的preHandle方法返回false,则中断请求处理,直接执行该拦截器的afterCompletion方法。
执行处理器的处理方法。
执行所有拦截器的postHandle方法,按注册顺序的逆序执行。
渲染视图。
执行所有拦截器的afterCompletion方法,按注册顺序的逆序执行。

Springboot基础------控制器、过滤器、拦截器、监视器_第1张图片

生命周期

拦截器的生命周期由Spring容器管理。当Spring容器启动时,拦截器会被实例化并初始化;当Spring容器关闭时,拦截器会被销毁。

拦截器的实现

拦截器编写(实现HandlerInterceptor接口)

在更高版本中HandlerInterceptorAdapter已经弃用,推荐实现HandlerInterceptor接口。实现拦截类的拦截逻辑。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author zjh
 * @className LogbackInterceptor
 * @date 2024/7/29
 * @description 拦截器处理类
 **/
@Component
public class LogbackInterceptor implements HandlerInterceptor {
    /**
     * 在 controller 执行之前进行拦截,返回结果将决定后续操作是否执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 编写拦截器逻辑
        System.out.println("===拦截器1前处理===");
        return true;
    }
    /**
     * 在执行完 controller 的方法后进行拦截,可对 model 和 view 进行修改
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("===拦截器1后处理===");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
    /**
     * 在整个请求完成之后执行,即视图渲染之后执行,若返回 json 数据则不会执行此方法
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

注: preHandle方法的返回值如果为true表示正常执行,如果为false表示阻止请求正常执行

HandlerInterceptorAdapter内含方法介绍

预处理preHandle()方法

用户发送请求时,先执行preHandle()方法。会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则执行用户请求的url方法。

后处理postHandle()方法

调用了Service并返回ModelAndView,但未进行页面渲染,可以在这里继续修改ModelAndView或者返回值

返回处理afterCompletion()方法

已经渲染了页面,在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。

注: 一般使用preHandle这个拦截器进行预处理,对url进行请求拦截

拦截器注册(实现WebMvcConfigurer接口)

需要继承WebMvcConfigurerAdapter类,在更高版本WebMvcConfigurerAdapter已经弃用。推荐实现WebMvcConfigurer接口,并重写addInterceptors(InterceptorRegistry registry)方法。也可以通过继承WebMvcConfigurationSupport类来实现,但是只能继承一次,而且会导致其他不注册在此类中的拦截器失效,不建议使用。

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author zjh
 * @className InterceptorConfig
 * @date 2024/7/29
 * @description 拦截器注册
 **/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    private final LogbackInterceptor logbackInterceptor;
    public InterceptorConfig(LogbackInterceptor logbackInterceptor) {
        this.logbackInterceptor = logbackInterceptor;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        //注册自己的拦截器并设置拦截的请求路径
     registry.addInterceptor(logbackInterceptor).addPathPatterns("/**");
    }
}

性能优化策略

拦截器在请求处理过程中可能会影响系统性能,以下是一些性能优化策略:

减少拦截器数量:尽量将相关功能集中到一个拦截器中,避免创建过多的拦截器。
精确配置拦截规则:通过addPathPatterns和excludePathPatterns方法精确配置拦截规则,避免不必要的拦截。
使用异步处理:在拦截器中使用异步处理,避免阻塞请求处理过程。
使用缓存:在拦截器中使用缓存,减少对数据库或其他资源的访问。

监听器

介绍

在Spring Boot中,监听器(Listener)的概念并不直接等同于传统Java EE或Servlet环境中的监听器,如ServletContextListener、HttpSessionListener等。Spring Boot作为一个现代化的、基于Spring框架的简化开发平台,它更多地依赖于Spring的事件发布-监听机制(Application Events)来处理类似监听器的功能。

Spring的事件发布-监听机制

Spring的事件发布-监听机制允许应用程序组件之间进行解耦的通信。当一个组件发生某个特定事件时,它可以发布一个事件,然后其他组件可以监听这个事件并做出响应。这种机制是通过ApplicationEvent类和ApplicationListener接口实现的。

ApplicationEvent:所有Spring事件类的基类。自定义事件需要继承这个类。
ApplicationListener:这是一个泛型接口,用于监听特定类型的事件。实现这个接口的类必须指定它们希望监听的事件类型。

SpringBoot提供的内置监听器

ApplicationStartingEvent:应用程序开始启动时触发
ApplicationEnvironmentPreparedEvent:应用程序环境准备好时触发,此时上下文还没有创建
ApplicationContextInitializedEvent:应用程序上下文创建之前触发
ApplicationPreparedEvent:应用程序上下文创建完成后触发,此时所有的bean已经加载完成
ApplicationStartedEvent:应用程序启动完成时触发
ApplicationReadyEvent:应用程序已经准备好接收请求时触发
ApplicationFailedEvent:应用程序启动失败时触发

实现监听的器的方法

实现ApplicationListener

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * @author zjh
 * @className CustomEventListener
 * @date 2024/7/29
 * @description TODO
 **/
@Component
public class CustomEventListener implements ApplicationListener<ApplicationEvent> {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        // 处理事件逻辑
        System.out.println("Spring Boot 应用启动... " + event.toString());
    }
}

注: @Component 是 Spring 框架中的一个核心注解,它用于标记一个类作为 Spring 容器中的一个组件(Bean),以便 Spring 可以自动检测到它,并对其进行管理。当 Spring 容器启动时,它会扫描带有 @Component 注解的类,并将其实例化、组装成 Spring 应用上下文(ApplicationContext)中的 Bean。

使用@EventListener注解

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyEventListener {

    @EventListener
    public void handleContextRefreshedEvent(ContextRefreshedEvent event) {
        // 你的逻辑
    }
}

你可能感兴趣的:(spring,boot,后端,java)