zoukankan      html  css  js  c++  java
  • 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中写 

    大功告成!!!
  • 相关阅读:
    写一个函数的程序,判断是否是浮点数
    写一个函数,输入一个数,随机生成N条邮箱
    day4-python基础知识 <元组&&集合>
    day4-python基础知识<文件操作>
    程序--用户登录--<while循环>
    程序--<猜数字小游戏>--for
    使用ajax后提交事件后禁用按钮,事件执行完毕后,重新启用按钮
    ajax在弹出对话框中实现一个UpdateProgress进度条控件源代码
    运算符的结合性
    匿名方法
  • 原文地址:https://www.cnblogs.com/coder-lzh/p/8647967.html
Copyright © 2011-2022 走看看