#spring mvc HandlerInterceptor拦截器
##spring-mvc.xml 配置
在 spring-mvc.xml 文件下增加
<mvc:interceptors>
<!—拦截器 拦截器执行顺序:先执行后定义的,排在第一位的最后执行—>
<mvc:interceptor>
<mvc:mapping path = ““ />//拦截的请求
<bean class = “" />//拦截处理器的全限定名
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path = “” /> //拦截的请求
<bean class = “” >//拦截处理器的权限定名
</mvc:interceptor>
</mvc:interceptors>
##定义处理器
拦截处理器 实现 HandlerInterceptor 接口
需要重写三个方法
- public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, object o ) throws Exception
// 请求预处理 在请求处理之前进行调用 返回true 才会进入处理器
- public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,Object o,ModelAndView modelAndView) throws Exception
// 将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用
- public void afterCompletion(HttpServletRequest httpServletRequest, HttpServleResponse httpServletResponse,Object o , Exception e) throws Exception
// 整个请求结束之后
##处理器代码
处理器:对接口处理进行计时,如果大于200ms则报警,如果有异常则报警
public class ApiResponseInterceptor extends BaseService implements HandlerInterceptor {
private static final ThreadLocal<Long> startTimeThreadLocal =
new NamedThreadLocal<Long>("ThreadLocal StartTime");
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
long beginTime = System.currentTimeMillis();//1、开始时间
startTimeThreadLocal.set(beginTime); //线程绑定变量(该数据只有当前请求的线程可见)
return true;
}
//TODO 500 报警
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
logger.error("api通过处理");
}
//TODO 判断时间
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)
long endTime = System.currentTimeMillis(); //2、结束时间
long handTime = endTime -beginTime;//时间大于200ms的接口报警
if(handTime > 200){
//发消息到报警群
String uri = httpServletRequest.getRequestURI();
logger.info(uri);
//线程异步处理
ThreadService service = SpringContextHolder.getBean(ThreadService.class);
// service.sendMessage(uri,handTime);
}
HandlerMethod method = (HandlerMethod)o;
logger.info(method.getReturnType().getParameterName());
// HttpServletResponseCopier copier = new HttpServletResponseCopier(httpServletResponse);
//copier.getCopy();
//如果出现异常,则进行报警
int status = httpServletResponse.getStatus();
if(status == 500){
//使用线程发送消息到钉钉
ThreadService service = SpringContextHolder.getBean(ThreadService.class);
service.sendMessageHttpFail(httpServletRequest.getRequestURI());
}
}
}
由于计时需要在 preHandlehe 和 postHandle 中进行计时,需要声明类变量。由于我们定义的是static,如果需要每个线程都的计时是独立的,那么我们需要使用ThreadLocal。
ThreadLocal 会对对每个线程提供一个变量的副本,变量在线程之间是不共享的(注意是不共享的,)。
This class provides thread-local variables. These variables differ from
- their normal counterparts in that each thread that accesses one (via its
- {@code get} or {@code set} method) has its own, independently initialized
- copy of the variable. {@code ThreadLocal} instances are typically private
- static fields in classes that wish to associate state with a thread (e.g.,
- a user ID or Transaction ID).
更多推荐
spring mvc HandlerInterceptor拦截器
发布评论