springMVC的全局攔截器


先說說為什么要使用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");
    }

}
View Code
 
        

解釋一下上面的方法,一共需要實現三個方法。第一個方法意思是,每次請求之前先被它攔截到,然后返回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中寫 

大功告成!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM