• SpringMVC拦截器Interceptor


    SpringMVC拦截器(Interceptor)实现对每一个请求处理前后进行相关的业务处理,类似与servlet中的Filter。

    SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor来实现的。

    在SpringMVC中定义一个Interceptor非常简单,主要有4种方式:

    1)实现Spring的HandlerInterceptor接口;

    2)继承实现了HandlerInterceptor接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter;

    3)实现Spring的WebRequestInterceptor接口;

    4)继承实现了WebRequestInterceptor的类;

    实现了拦截器之后,我们可以通过重写WebMvcConfigurerAdapter的addInterceptors方法来注册自己的拦截器。

    我们这里只通过实现HandlerInterceptor接口的方式给出实例。实例中使用拦截器实现两个功能

    1)计算每一次请求的处理时间

    2)并对特定时间和特定用户(数据在codis中)的请求进行拒绝

     1、HandlerInterceptor接口

    public interface HandlerInterceptor {
        boolean preHandle(HttpServletRequest request, 
                          HttpServletResponse response, 
                          Object handler) throws Exception;
    
        void postHandle(HttpServletRequest request, 
                        HttpServletResponse response, 
                        Object handler, ModelAndView modelAndView) throws Exception;
    
        void afterCompletion(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler, Exception ex) throws Exception;
    }
    • preHandle():预处理回调方法,若方法返回值为true,请求继续(调用下一个拦截器或处理器方法);若方法返回值为false,请求处理流程中断,不会继续调用其他的拦截器或处理器方法,此时需要通过response产生响应;
    • postHandle():后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时可以通过modelAndView对模型数据进行处理或对视图进行处理
    • afterCompletion():整个请求处理完毕回调方法,即在视图渲染完毕时调用

    HandlerInterceptor有三个方法需要实现,但大部分时候可能只需要实现其中的一个方法,HandlerInterceptorAdapter是一个实现了HandlerInterceptor的抽象类,它的三个实现方法都为空实现(或者返回true),继承该抽象类后可以仅仅实现其中的一个方法。

    2、实现拦截器

    package com.xiaoju.dqa.sentinel.monitor.interceptor;
    
    
    import com.xiaoju.dqa.sentinel.common.client.redis.CodisClient;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Calendar;
    import java.util.Set;
    
    
    public class AuthInterceptor implements HandlerInterceptor {
    
        protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @Autowired
        private CodisClient codisClient;
    
        /*
        *   视图函数执行成功后执行
        * */
        @Override
        public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
                throws Exception {
        }
    
        /*
        *   在视图函数之后执行
        *   本函数的作用:计算处理时间
        * */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
                throws Exception {
            long startTime = (Long) request.getAttribute("startTime");
            request.removeAttribute("startTime");
            logger.info("处理时间: {}", System.currentTimeMillis() - startTime);
        }
    
        /*
        *   在视图函数之前执行
        *   返回true, 继续执行视图函数
        *   返回false, 终止请求流程
        *   本函数的作用,:拒绝特定时间sentinel:forbidden:hours; 特定用户的sentinel:forbidden:users请求, 并记录startTime
        * */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            boolean going = true;
            long startTime = System.currentTimeMillis();
            request.setAttribute("startTime", startTime);
            Calendar ca = Calendar.getInstance();
            String  currentHour = String.valueOf(ca.get(Calendar.HOUR_OF_DAY));
            try {
                boolean isForbidHour = codisClient.sismember("sentinel:forbidden:hours", currentHour);
                if (isForbidHour) {
                    Set<String> forbiddenUsers = codisClient.smembers("sentinel:forbidden:users");
                    if (forbiddenUsers != null) {
                        for (Cookie cookie : request.getCookies()) {
                            if("username".equals(cookie.getName()) && forbiddenUsers.contains(cookie.getValue())) {
                                logger.info("[拦截器] 禁止访问. 时间:{}, 用户:{}", currentHour, cookie.getValue());
                                going = false;
                            }
                        }
                    }
                }
            } catch (Exception e) {
                logger.info("[拦截器] 有问题", e);
            }
            return going;
        }
    }
    

      

      

    3、注册拦截器

     这里预先生成了@bean - authInterceptor是为了让AuthInterceptor类中的codisClient的注入成功,否则即使自动注入了codisClient也无法注入成功。

    package com.xiaoju.dqa.sentinel.configuration;
    
    import com.xiaoju.dqa.sentinel.monitor.interceptor.AuthInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    
    @Configuration
    public class WebInterceptorConfig extends WebMvcConfigurerAdapter {
    
        @Bean
        public AuthInterceptor authInterceptor() {
            return new AuthInterceptor();
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 多个拦截器组成一个拦截器链
            // addPathPatterns 用于添加拦截规则
            // excludePathPatterns 用户排除拦截
            registry.addInterceptor(authInterceptor()).addPathPatterns("/**").excludePathPatterns("/sentinel/monitor/**");
            super.addInterceptors(registry);
        }
    
    }
    

      

     

  • 相关阅读:
    ListView 分页显示(转载+修改)下
    ListView 分页显示(转载+修改)上
    Android_开发片段(Part 1)
    JSCH执行linux命令
    linux运行wkhtmltopdf
    Apache HttpClient
    JDK自带的URLConnection
    java poi读取excel
    CXF webservice完整例子
    Oracle 常用初始化命令
  • 原文地址:https://www.cnblogs.com/kangoroo/p/7652484.html
Copyright © 2020-2023  润新知