先說說為什么要使用springMVC的全局攔截器,比如 當我們在訪問接口的時候,我們一般都會先判斷這個用戶是否登陸,我們就要在每個接口的前面都要判斷一下,想想是不是很蛋疼,那工作量。。。
這時候,我們需要一個攔截器,他的作用就是,在每個請求的時候會先被它攔截,同時,還會得到request、response、請求url等等參數。
是不是很炫酷
話不多說,直接上代碼
這個類是springMVC給我們實現的,只需要繼承 HandlerInterceptorAdapter 類就可以了
HttpInterceptor.java

package com.mmall.controller.common.interceptor; import com.google.common.collect.Maps; import com.mmall.common.Const; import com.mmall.common.ServerResponse; import com.mmall.pojo.User; import com.mmall.util.CookieUtil; import com.mmall.util.JsonUtil; import com.mmall.util.RedisShardedPoolUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.method.HandlerMethod; 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.Arrays; import java.util.Iterator; import java.util.Map; /** * Created by 敲代碼的卡卡羅特 */ public class AuthorityInterceptor implements HandlerInterceptor { private Logger logger = LoggerFactory.getLogger(AuthorityInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //請求controller中的方法名 HandlerMethod handlerMethod = (HandlerMethod)handler; //解析HandlerMethod String methodName = handlerMethod.getMethod().getName(); String className = handlerMethod.getBean().getClass().getSimpleName(); StringBuffer requestParamBuffer = new StringBuffer(); Map paramMap = request.getParameterMap(); Iterator it = paramMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String mapKey = (String) entry.getKey(); String mapValue = ""; //request的這個參數map的value返回的是一個String[] Object obj = entry.getValue(); if (obj instanceof String[]){ String[] strs = (String[])obj; mapValue = Arrays.toString(strs); } //只是得到請求參數然后拼接成字符串 requestParamBuffer.append(mapKey).append("=").append(mapValue); } //對於攔截器中攔截manage下的login.do的處理,對於登錄不攔截,直接放行 if(StringUtils.equals(className,"UserManageController") && StringUtils.equals(methodName,"login")){ logger.info("權限攔截器攔截到請求,className:{},methodName:{}",className,methodName);//如果是攔截到登錄請求,不打印參數,因為參數里面有密碼,全部會打印到日志中,防止日志泄露 return true; } logger.info("權限攔截器攔截到請求,className:{},methodName:{},param:{}",className,methodName,requestParamBuffer); // User user = (User)request.getSession().getAttribute(Const.CURRENT_USER); User user = null; String loginToken = CookieUtil.readLoginToken(request); if(StringUtils.isNotEmpty(loginToken)){ String userJsonStr = RedisShardedPoolUtil.get(loginToken); user = JsonUtil.string2Obj(userJsonStr,User.class); } if(user == null || (user.getRole().intValue() != Const.Role.ROLE_ADMIN)){ //返回false.即不會調用到controller里的方法 response.reset();//geelynote 這里要添加reset,否則報異常 getWriter() has already been called for this response response.setCharacterEncoding("UTF-8");//geelynote 這里要設置編碼,否則會亂碼 // response.setContentType("text/html;charset=utf-8"); response.setContentType("application/json;charset=UTF-8");//geelynote 這里要設置返回值類型,因為全部是json接口。 PrintWriter out = response.getWriter(); //上傳由於富文本的控件要求,要特殊處理返回值,這里面區分是否登錄以及是否有權限 if(user == null){ if(StringUtils.equals(className,"ProductManageController") && (StringUtils.equals(methodName,"richtextImgUpload") )){ Map resultMap = Maps.newHashMap(); resultMap.put("success",false); resultMap.put("msg","請登錄管理員"); out.print(JsonUtil.obj2String(resultMap)); }else{ out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("攔截器攔截,用戶未登錄"))); } }else{ if(StringUtils.equals(className,"ProductManageController") && (StringUtils.equals(methodName,"richtextImgUpload") )){ Map resultMap = Maps.newHashMap(); resultMap.put("success",false); resultMap.put("msg","無權限操作"); out.print(JsonUtil.obj2String(resultMap)); }else{ out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("攔截器攔截,用戶無權限操作"))); } } out.flush();//geelynote 這里要關閉流 out.close(); //geelynote return false;//這里雖然已經輸出,但是還會走到controller,所以要return false } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); } }
解釋一下上面的方法,一共需要實現三個方法。第一個方法意思是,每次請求之前先被它攔截到,然后返回true的時候繼續實現我們controller層的業務,接口完成之后會繼續到第二個方法,然后再到第三個方法。
那第二個方法和第三個方法有什么區別呢?????
第二個方法是controller層不報錯的情況下才會走這個方法,如果報錯就不走,但是第三個方法肯定會走。
方法里面的業務邏輯是我隨便寫的,可以忽略,就是得到request的url和參數。然后日志記錄下 然后判斷是否登陸,是否是管理員,然后會根據一些特殊的請求的url和方法做一些特殊的處理 比如說 請求登陸接口的時候就放行 等等~~~
最后,我們需要在spring-servlet.xml中聲明一下
<mvc:interceptors>
<!-- 定義在這里會攔截指定的請求url -->
<mvc:mapping path="/manage/**"/>
<bean class="com.mmall.common.HttpInterceptor" />
</mvc:interceptors>
注意一下:這里面你可以在攔截器里面寫具體攔截或者不攔截的方法也可以在spring-servlet.xml中寫
大功告成!!!