原创

SpringBoot学习示例——HandlerInterceptor使用场景及作用

1. 什么是HandlerInterceptor

HandlerInterceptor类似Servlet开发中的过滤器Filter,而它属于spring中的拦截器。
说到spring中的aop,大家都熟悉面向切面编程开发的思想,过滤器和拦截器都属于面向切面编程的具体实现。

1、Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。

2、Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。

3、Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。

2. HandlerInterceptor配置方式

分为两步。
第一步,先将继承了HandlerInterceptor的自定义拦截器使用@Componet修饰,放入到IOC中。

package com.ruoyi.intercepter;

import com.ruoyi.ShieldProcessor;
import com.ruoyi.ShieldResponse;
import com.ruoyi.utils.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class ShieldIntercepter implements HandlerInterceptor {

    private static final int SUCCESS = 1;

    private String shieldforbidenurl = "/shield/shieldforbiden.html";

    private ShieldProcessor processor;

    public void setProcessor(ShieldProcessor processor) {
        this.processor = processor;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        ShieldResponse br = processor.process(request);
        String requestUri = request.getRequestURI();
        log.info("enter ShieldIntercepter , requestUri:{}",requestUri);
        if(br.getCode() == SUCCESS || shieldforbidenurl.equals(requestUri)) {
            return true;
        }
        String errorMsg = String.format("第%s次被限制!", br.getLimitCount());
        log.warn(errorMsg);
        if(RequestUtil.isAjax(request)) {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.write(initErrorResp(errorMsg));
            writer.flush();
            writer.close();
            return false;
        }
        request.setAttribute("errorMsg", errorMsg);
        request.setAttribute("expire", TimeUnit.MILLISECONDS.toSeconds(br.getExpire()));
        request.getRequestDispatcher("/shield/shieldforbiden.html").forward(request, response);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    private String initErrorResp(String errMsg){

        String result = "{"+ "\"errMsg\":\"" + errMsg + "\",\"status\":" + "\"FAIL\"" +"}";
        return result.toString();
    }
}

第二步,继承一个,然后将拦截器按照规定的方式引入到spring中。

@Component
public class BitTechShieldWebMvcConfig  extends WebMvcConfigurerAdapter {
    @Autowired
    private ShieldIntercepter shieldIntercepter;

    public void setShieldIntercepter(ShieldIntercepter shieldIntercepter) {
        this.shieldIntercepter = shieldIntercepter;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(shieldIntercepter);
    }
}

3. 应用场景

HandlerInterceptor就像是服务的aop模块一样,而这里它就是一个web请求的aop逻辑,在这里能做到类似AOP切面编程所做的事情,对于一些与外部角色交互的问题场景大部分都能使用HandlerInterceptor解决。

权限检查:登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。

日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)。

性能监控:记录url的进入时间点和结束的时间点,这两个时间点的差就是接口的RT,从而反映出web服务的性能。

完整的demo项目,请关注公众号“前沿科技bot“并发送"状态机"获取。

alt

正文到此结束
本文目录