SpringBoot拦截过滤与监听

开课吧开课吧锤锤2021-08-12 17:32

上一篇讲解了thymeleaf基础语法及内置对象,结束了SpringBoot整合静态资源与模版引擎的所有讲解。本篇开始讲解SpringBoot拦截过滤与监听。

SpringBoot拦截过滤与监听

Servlet规范实现监听器  

servlet监听器是servlet规范中定义的特殊的类用于监听servletContext(application级别)、httpsession(session级别)、servletRequest(request级别)等作用域对象的创建与销毁事件,以及监听这些作用域对象中属性发生修改的事件。开发Servlet监听器需要实现相应的监听器接口并重写接口中的方法。  

ServletListener监听监听ServletContext、HttpSession、HttpServletRequest这三个对象创建和销毁事件的监听器:  

ServletContext 监听 ServletContext 对象的创建与销毁过程,一个完整的应用里只存在一个
HttpSession 监听 HttpSession 对象的创建和销毁过程,同一个用户在使用浏览器从开启到关闭的过程中使用的是一个session
HttpServletRequest 监听 ServletRequest 对象的创建和销毁过程(HTTP请求)

作用域比较:ServletContext>HttpSession>HttpServletRequest  

还可以使用  

HttpSessionAttributeListener  

ServletContextAttributeListener  

ServletRequestAttributeListener  

来监听域对象内属性的变化  

实现监听器的创建与销毁  

在config文件下创建ListenerContextConfig.java:  

package com.javafamily.familydemo.config;

import javax.servlet.*;
import javax.servlet.annotation.WebListener;

// 将当前Listener实例化,注入到Spring上下文中去
@WebListener
public class ListenerContextConfig implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent se) {
        System.out.println("初始化context");
    }

    @Override
    public void contextDestroyed(ServletContextEvent se) {
        System.out.println("销毁context");
    }

}

创建ListenerRequestConfig.java:  

package com.javafamily.familydemo.config;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ListenerRequestConfig implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("销毁request监听器");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("初始化request监听器");
    }
}

创建ListenerSessionConfig.java:  

package com.javafamily.familydemo.config;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class ListenerSessionConfig implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("创建session");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("销毁session");
    }

}

创建ListenRequestAttributeConfig.java:  

package com.javafamily.familydemo.config;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ListenRequestAttributeConfig implements ServletRequestAttributeListener {
    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        System.out.println("attributeAdded");
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        System.out.println("attributeRemoved");
    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        System.out.println("attributeReplaced");
    }

}

创建ListenSessionAttributeConfig.java:

package com.javafamily.familydemo.config;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener
public class ListenSessionAttributeConfig implements HttpSessionAttributeListener {
    @Override
    public void attributeAdded(HttpSessionBindingEvent sbe) {
        System.out.println("attributeAdded1");
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent arg0) {
        System.out.println("attributeRemoved1");
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent arg0) {
        System.out.println("attributeReplaced1");
    }
}

再在controller文件下创建ListenerController.java:  

package com.javafamily.familydemo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@RestController
public class ListenerController {

    @GetMapping("/listener")
    public String Listener(HttpServletRequest request,
                           HttpSession session) {

        // set一个值
        request.setAttribute("Java", "Family");
        // 替换一个值
        request.setAttribute("Java", "OtherFamily");
        // get一个值
        request.getAttribute("Java");
        // 删除一个值
        request.removeAttribute("Java");

        session.setAttribute("Java", "Our");
        session.setAttribute("Java", "Other");
        session.getAttribute("Java");
        session.invalidate();

        return "Listener测试";
    }
}

在request.setAttribute("Java","Family");和return"Listener测试";这两处打好断点进行debug。  

在代码执行完之后context就已经初始化了:  

SpringBoot拦截过滤与监听

浏览器访问链接http://localhost:8888/listener。查看打印结果:  

SpringBoot拦截过滤与监听

通过debug打印出的顺序,可以看出代码的执行顺序。  

点击左侧红色方块,停止debug,得到打印结果销毁context:  

SpringBoot拦截过滤与监听

注:记得在启动类中添加@ServletComponentScan注解:  

@SpringBootApplication
@MapperScan(basePackages = {"com.javafamily.familydemo.mapper"})
// 扫描Servlet主键(监听器是Servlet主键的一种)
@ServletComponentScan
public class FamilyDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(FamilyDemoApplication.class, args);
    }
}

Servlet规范实现过滤器  

Servlet过滤器是服务器与客户端请求与响应的中间层组件,能够在前端向后端请求数据之前拦截请求,也能在后端的响应发送回前端之前处理响应。它能够过滤请求和改变请求的数据。  

SpringBoot拦截过滤与监听

在SpringBoot项目中过滤器有两种比较主流的注册方式,一种是使用@WebFilter注解,另一种是使用springboot提供的FilterRegistrationBean方式。  

使用@WebFilter注解  

在config文件下创建FilterConfig.java:  

package com.javafamily.familydemo.config;

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

// urlPatterns={"/*"}表示过滤器过滤所有的请求
@WebFilter(filterName = "WebFilterConfig", urlPatterns = {"/*"})
public class FilterConfig implements Filter {
    @Override
    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
        System.out.println("拦截器初始化");
    }

    @Override
    // 实现业务处理的核心函数
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter方法之前进行过滤请求");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("doFilter方法之后进行响应处理");
    }

    @Override
    public void destroy() {
        System.out.println("销毁拦截器");
    }
}

@WebFilter注解无法保证过滤器之间的执行顺序,当使用多个过滤器时,我们会有对过滤器制定执行顺序的需求,@WebFilter注解是无法满足的。  

使用FilterRegistrationBean方式  

FilterRegistrationBean提供了setOrder方法,可以通过设置优先级进行排序:  

package com.javafamily.familydemo.config;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

public class BeanFilterConfig {
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new FilterConfig());
        registration.setName("filter");
        // 拦截路径
        registration.addUrlPatterns("/*");
        // 设置优先级,1最高
        registration.setOrder(1);
        return registration;
    }
}

拦截器的实现  

在Spring中拦截器有三个方法:  

preHandle 预处理回调方法,实现处理器的预处理
postHandle 后处理回调方法,实现处理器的后处理
afterCompletion  整个请求处理完毕回调方法

方法到达Controller之前preHandle对方法进行预处理,Controller给出响应之后交给postHandle进行处理,处理完成到达模版引擎页面进行页面渲染,最后到达postHandle方法。  

SpringBoot拦截过滤与监听

拦截器和过滤器的规范,作用范围,使用资源,粒度都有不同。  

在config文件下创建MyHandlerInterceptor.java:  

package com.javafamily.familydemo.config;

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;

@Component
public class MyHandlerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("afterCompletion");
    }
}

继承WebMvcConfigurerAdapter注册拦截器:  

package com.javafamily.familydemo.config;

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

import javax.annotation.Resource;

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Resource
    MyHandlerInterceptor myHandlerInterceptor;

    @Override
    // 添加拦截器
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册到Spring容器中
        registry.addInterceptor(myHandlerInterceptor).addPathPatterns("/*");

        // 多个拦截器(注册顺序就是执行顺序)
//        registry.addInterceptor(myHandlerInterceptor1).addPathPatterns("/*");
//        registry.addInterceptor(myHandlerInterceptor2).addPathPatterns("/*");
//        registry.addInterceptor(myHandlerInterceptor3).addPathPatterns("/*");
    }
}

执行代码后,浏览器访问http://localhost:8888,在控制台得到执行顺序:  

SpringBoot拦截过滤与监听

以上就是开课吧广场小编为大家整理发布的“SpringBoot拦截过滤与监听”一文,更多Java教程相关内容尽在开课吧广场Java教程频道!

开课吧广场Java教程

免责声明:本站所提供的内容均来源于网友提供或网络搜集,由本站编辑整理,仅供个人研究、交流学习使用。如涉及版权问题,请联系本站管理员予以更改或删除。
有用
分享
全部评论快来秀出你的观点
登录 后可发表观点…
发表
暂无评论,快来抢沙发!
高并发编程训练营