zoukankan      html  css  js  c++  java
  • Spring boot 拦截器和过滤器

    1. 过滤器

    Filter介绍

    Filter可以认为是Servlet的一种“加强版”,是对Servlet的扩展(既可以对请求进行预处理,又可以对处理结果进行后续处理。使用Filter完整的一般流程是:Filter对用户请求进行【预处理】,接着将请求交给Servlet进行预处理并【生成响应】,最后Filter再对服务器响应进行【后处理】。

    Filter的优点

    • 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。
    • 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
    • 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。
    • 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

    Filter的应用场景

    • 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。
    • 日志Filter:详细记录某些特殊的用户请求。
    • 负责解码的Filter,包括对非标准编码的请求解码。
    • 能改变XML内容的XSLT Filter等。
    • Filter可以负责拦截多个请求或响应;一个请求或响应也可以被多个Filter拦截。

    创建Filter

    1. 创建Filter处理类(实现javax.servlet.Filter接口)
    • void init(FilterConfig config):用于完成Filter的初始化。
    • void destory():用于Filter销毁前,完成某些资源的回收。
    • void doFilter(ServletRequest request,ServletResponse response,FilterChain chain):实现过滤功能,该方法就是对每个请求及响应增加的额外处理。该方法可以实现对用户请求进行预处理(ServletRequest request),也可实现对服务器响应进行后处理(ServletResponse response)—它们的分界线为是否调用了chain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。
    1. web.xml文件中配置Filter

    Filter 示例

    复制代码
    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
        
        //to visit     http://localhost:8080/filter/say
    }
    复制代码
    复制代码
    package com.example.demo.configuration;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    /**
     * 使用spring boot提供的FilterRegistrationBean注册Filter
     *
     */
    public class MyFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("MyFilter init");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
                throws IOException, ServletException {
            // do something 处理request 或response
            System.out.println("MyFilter doFilter");
            
            // 调用filter链中的下一个filter
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.println("MyFilter destroy");
        }
    }
    复制代码
    复制代码
    package com.example.demo.configuration;
    
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /***
     * 使用spring boot提供的FilterRegistrationBean注册Filter
     *
     */
    @Configuration
    public class FilterConfig {
        @Bean
        public FilterRegistrationBean registrationBean() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
            filterRegistrationBean.addUrlPatterns("/*");
            
            return filterRegistrationBean;
        }
    }
    复制代码
    复制代码
    package com.example.demo.configuration;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    
    import org.springframework.stereotype.Component;
    /**
     * 方式二
     * 使用原生servlet注解定义Filter 
     *
     */
    //注入spring容器
    @Component
    // 定义filterName 和过滤的url
    @WebFilter(filterName = "my2Filter", urlPatterns = "/*")
    public class My2Filter implements Filter{
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("MyFilter2 init");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
                throws IOException, ServletException {
            System.out.println("MyFilter2 doFilter");
            
            // 调用filter链中的下一个filter
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.println("MyFilter2 destroy");
        }
    }
    复制代码
    复制代码
    package com.example.demo.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/filter")
    public class DomainController {
        
        @RequestMapping(value="say", method=RequestMethod.GET)
        public void say(){
            System.out.println("ok");
        }
    }
    复制代码
    server.port = 8080
    server.context-path=/
    
    # tomcat相关设置  
    server.tomcat.uri-encoding=UTF-8

     2. 拦截器

    Interceptor介绍

    拦截器,在AOP(Aspect-Oriented Programming)中用于在【某个方法或字段被访问】之前进行拦截,然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。拦截器是**动态拦截Action调用的对象**。它提供了一种机制可以使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个Action执行前阻止其执行。同时也提供了一种可以提取Action中可重用的部分的方式。

    拦截器**将Action共用的行为独立出来,在Action执行前后执行**。这也就是我们所说的AOP,它是分散关注的编程方法,它将通用需求功能从不相关类之中分离出来;同时,能够共享一个行为,一旦行为发生变化,不必修改很多类,只要修改这个行为就可以。

    拦截器将很多功能从我们的Action中独立出来,大量减少了我们Action的代码,独立出来的行为就有很好的重用性。

    当你提交对Action(默认是.action结尾的url)的请求时,ServletDispatcher会根据你的请求,去调度并执行相应的Action。在Action执行之前,调用被Interceptor截取,Interceptor在Action执行前后执行。


    创建Interceptor必须实现com.opensymphony.xwork2.interceptor.Interceptor接口,该接口定义了如下三个方法。

    • void init():在该拦截器被实例化之后,在该拦截器执行拦截之前,系统将回调该方法。对于每个拦截器而言,其init()方法只执行一次。因此,该方法的方法体主要用于初始化资源。
    • void destory():该方法与init()方法对应。在拦截器实例被销毁之前,系统将回调该拦截器的destory方法,该方法用于销毁在init方法里打开的资源。
    • String intercept(ActionInvocation invocation):该方法是用户需要实现的拦截动作。就像Action的execute方法一样。intercept方法会返回一个字符串作为逻辑视图。如果该方法直接返回了一个字符串,系统会将跳转到该逻辑视图对应的实际视图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过调用该参数的invoke方法,将控制权转给下一个拦截器,或者转给Action的execute方法(如果该拦截器后没有其他拦截器,则直接执行Action的execute方法)。
       

    拦截器示例

    复制代码
    package com.example.demo.interceptor.configuration;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.beust.jcommander.internal.Nullable;
    
    /**
     * 定义拦截器
     *
     */
    public class MyInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            System.out.println("MyInterceptor preHandle");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) 
                throws Exception {
            System.out.println("MyInterceptor postHandle");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) 
                throws Exception {
            System.out.println("MyInterceptor afterCompletion");
        }
    }
    复制代码
    复制代码
    package com.example.demo.interceptor.configuration;
    
    import java.util.List;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.format.FormatterRegistry;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.validation.MessageCodesResolver;
    import org.springframework.validation.Validator;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
    import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    /**
     * 配置拦截器
     *
     */
    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer{
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new MyInterceptor());
        }
    
        @Override
        public void configurePathMatch(PathMatchConfigurer configurer) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void addFormatters(FormatterRegistry registry) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public Validator getValidator() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public MessageCodesResolver getMessageCodesResolver() {
            // TODO Auto-generated method stub
            return null;
        }
    }
    复制代码

     

    3. Filter和Interceptor的区别

    • Filter是基于函数回调的,而Interceptor则是基于Java反射的。
    • Filter依赖于Servlet容器,而Interceptor不依赖于Servlet容器。
    • Filter对几乎所有的请求起作用,而Interceptor只能对action请求起作用。
    • Interceptor可以访问Action的上下文,值栈里的对象,而Filter不能。
    • 在action的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。

    4. Filter和Interceptor的执行顺序

    过滤前-拦截前-action执行-拦截后-过滤后

    MyFilter doFilter
    MyFilter2 doFilter
    MyInterceptor preHandle
    ok
    MyInterceptor postHandle
    MyInterceptor afterCompletion
    MyFilter doFilter
    MyFilter2 doFilter

    过滤器拦截器运行先后步骤

     5. 普通的可以使用反射

     反射的应用 3 动态代理+切面编程 AOP代理

    复制代码
            // 11. 反射的应用 3 动态代理+切面编程 AOP代理
            // 在调用指定方法之前和之后调用preAction()和postAction()方法
            SuperMan man = new SuperMan();//创建一个被代理类的对象
            
            Human human = (Human) ManProxy.getProxyInstance(man);//返回一个代理类的对象
            human.info();//通过代理类的对象嗲用重写的抽象的方法
            
            System.out.println();
            human.fly();
    复制代码
    复制代码
    interface Human {
        void info();
        void fly();
    }
    
    class SuperMan implements Human {
        @Override
        public void info() {
            System.out.println("我是超人!");
        }
    
        @Override
        public void fly() {
            System.out.println("I believe I can fly!");
        }
    }
    
    class HumanUtil {
        public void preAction() {
            System.out.println("=============preAction()============");
        }
    
        public void postAction() {
            System.out.println("=============postAction()============");
        }
    }
    
    class ManInvocationHandler implements InvocationHandler {
        Object object;
    
        public void setObject(Object object) {
            this.object = object;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            HumanUtil h = new HumanUtil();
    
            h.preAction();
            Object returnVal = method.invoke(object, args);
            h.postAction();
    
            return returnVal;
        }
    }
    
    //动态的创建一个代理类的对象
    class ManProxy {
        public static Object getProxyInstance(Object object) {
            ManInvocationHandler handler = new ManInvocationHandler();
            handler.setObject(object);
            
            return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), handler);
        }
    }
    复制代码
    博客地址:https://blog.csdn.net/xiang__liu,https://www.cnblogs.com/xiang--liu/
  • 相关阅读:
    C++类构造函数初始化列表(转)
    Linux可重入函数和线程安全的区别与联系(转)
    Splinter自动登录
    VBA添加下拉菜单
    批处理自动备份并生成日志文件
    VBA 格式化excel数据表 (数据分列)
    Python 调用outlook发送邮件(转 )
    Node.js 文件操作
    Node.js express模块 http服务
    将ejs模板文件的后缀换成html
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/13234072.html
Copyright © 2011-2022 走看看