赞
踩
拦截器是Web中常见,重要的一种机制,用来对数据进行预处理等操作,本文主要是Spring对HandlerInterceptor这个接口进行解析,这个接口属于SpringMVC包中。
HandlerInterceptor,这个Handler可以认为就是Controller的方法,这个接口有三个方法,分别是:
其中:
- boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
- for (int i = 0; i < this.interceptorList.size(); i++) {
- HandlerInterceptor interceptor = this.interceptorList.get(i);
- if (!interceptor.preHandle(request, response, this.handler)) {
- triggerAfterCompletion(request, response, null);
- return false;
- }
- this.interceptorIndex = i;
- }
- return true;
- }
-
-
- void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
- for (int i = this.interceptorIndex; i >= 0; i--) {
- HandlerInterceptor interceptor = this.interceptorList.get(i);
- try {
- interceptor.afterCompletion(request, response, this.handler, ex);
- }
- catch (Throwable ex2) {
- logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Spring MVC
提供的特性,依赖于Spring MVC框架,而不依赖Servlet容器,Filter则是Servlet的特性,属于Servlet
的规范,并且依赖Servlet容器。filterChain.doFilter
进行分隔,而HandlerInterceptor将预处理和后处理逻辑拆分成两个方法,即preHandle、postHandle
方法。init和destroy
,而HandlerInterceptor则没有,但是HandlerInterceptor拥有afterCompletion
处理方法,无论有没有抛出异常,在DispatcherServlet请求处理的最后都会执行!通过的是责任链的设计模式,关键角色是HandlerExecutionChain,这个类里面有一个容器,管理了HandlerInterceptor接口。
注册Interceptor
- @Configuration
- public class HeaderParamExtInterceptorConfig implements WebMvcConfigurer {
-
- @Override
- public void addInterceptors(InterceptorRegistry registry){
- // 这个Interceptor实现了HandlerInterceptor接口
- registry.addInterceptor(new HeaderParamExtInterceptor()).order(-1);
- // 还可以制定拦截的路径
- registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
- registry.addInterceptor(new HeaderParamInterceptor()).addPathPatterns(new String[]{"/**"}).excludePathPatterns(new String[]{"*.js,*.gif,*.jpg,*.png,*.css,*.ico"});
-
-
- }
-
- }
示例代码,修改请求头
- public class HeaderParamExtInterceptor implements HandlerInterceptor {
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
-
- Map<String, String> headerParamsMap = new HashMap<>(16);
-
- ServletRequestAttributes servletReqAttr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
- if (servletReqAttr != null) {
- // 设置账户Id
- headerParamsMap.put(CommonConstants.HTTP_HEADER_X_ACCOUNT_ID, request.getHeader(CommonConstants.HTTP_HEADER_X_ACCOUNT_ID));
-
- }
-
- HeaderParamThreadLocalUtils.setHeaderParam(headerParamsMap);
-
- return true;
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
- @Nullable Exception ex) throws Exception {
- HeaderParamThreadLocalUtils.removeHeaderParam();
- }
-
- /**
- * 修改请求头信息
- */
- private void modifyHeaders(Map<String, String> headersTmp, HttpServletRequest request) {
- if (headersTmp == null || headersTmp.isEmpty()) {
- return;
- }
- Class<? extends HttpServletRequest> requestClass = request.getClass();
- try {
- Field request1 = requestClass.getDeclaredField("request");
- request1.setAccessible(true);
- Object o = request1.get(request);
- Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
- coyoteRequest.setAccessible(true);
- Object o1 = coyoteRequest.get(o);
- Field headers = o1.getClass().getDeclaredField("headers");
- headers.setAccessible(true);
- MimeHeaders o2 = (MimeHeaders)headers.get(o1);
- for (Map.Entry<String, String> entry : headersTmp.entrySet()) {
- o2.removeHeader(entry.getKey());
- o2.addValue(entry.getKey()).setString(entry.getValue());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- }
-
-
- public class HeaderParamThreadLocalUtils {
-
- private static ThreadLocal<Map<String, String>> headerParamThreadLocal = ThreadLocal.withInitial(HashMap::new);
-
- public static void setHeaderParam(Map<String, String> headerParam){
- if (!CollectionUtils.isEmpty(headerParam)){
- headerParamThreadLocal.set(headerParam);
- }
- }
-
- /**
- * 取当前线程对应http请求的请求头
- */
- public static Map<String, String> getHeaderParam(){
- return headerParamThreadLocal.get();
- }
-
- public static void removeHeaderParam(){
- headerParamThreadLocal.remove();
- }
-
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
druid中的代码
下面这段代码判断uri后缀是否包某个字符串,取之前的字符串进行处理
- if (uriStat == null) {
- int index = requestURI.indexOf(";jsessionid=");
- if (index != -1) {
- requestURI = requestURI.substring(0, index);
- uriStat = webAppStat.getURIStat(requestURI, false);
- }
- }
-
- // 这个方法可以获取正在处理的URI
- public String getRequestURI(HttpServletRequest request) {
- return (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。