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“并发送"状态机"获取。
正文到此结束