• spring mvc 拦截器


    配置:

    在mvc配置文件dispatcher-servlet里配置: 

    <mvc:interceptors>
        <!-- 定义在这个bean里的所有的都会拦截: -->
        <!--<bean></bean>-->
        <mvc:interceptor>
            <!-- 定义在这里会拦截指定的请求url -->
            <mvc:mapping path="  /manage/**  "/>
            <bean class="cn.it.controller.common.interceptor.AuthorityInterceptor"/>  //要创建这个拦截器
        </mvc:interceptor>
    </mvc:interceptors>

    其中<mvc: mapping path=" "/>
    /** 表示所有路径及里面的子路径
    /* 表示当前路径下的所有路径,不含子路径
    / 表示web项目的根目录的请求。

    例:
    <!--manage/a.do /manage/*-->
    <!--manage/b.do /manage/*-->
    <!--manage/product/save.do /manage/**-->
    <!--manage/order/detail.do /manage/**-->

    在对应包下建类:AuthorityInterceptor,并实现接口HandlerInterceptor。
    会实现三个方法:preHandle, postHandle, afterCompletion。当请求匹配到配置文件里的路径后,就会进入这个类。先执行preHandle方法,再执行controller对应的接口,再执行postHandle,最后执行afterCompletion。如果preHandle方法返回false,就不再执行controller对应的接口。

        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("preHandle");
            //请求中Controller中的方法名
            HandlerMethod handlerMethod = (HandlerMethod)handler;
            //解析HandlerMethod
            String methodName = handlerMethod.getMethod().getName();//拿到contoller里对应请求的方法名。
            String className = handlerMethod.getBean().getClass().getSimpleName();//拿到对应请求的controller的单纯的类名。如果不同包下有相同名就要拿全名了,用于区分。
            //解析参数,具体的参数key以及value是什么,我们打印日志
            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 = StringUtils.EMPTY;//StringUtils.EMPTY就是空字符串:""
                //request这个参数的map,里面的value返回的是一个String[]
                Object obj = entry.getValue();//返回string数组,其实就是参数的值。
                if(obj instanceof String[]){
                    String[] strs = (String[])obj;
                    mapValue = Arrays.toString(strs);//转成字符串。
                }
                requestParamBuffer.append(mapKey).append("=").append(mapValue);//最终结果是字符串,比如username=[admin]password=[admin]
            }
            if(StringUtils.equals(className,"UserManageController") && StringUtils.equals(methodName,"login")){//根据方法名和类名判断登录操作把它放过。解决拦截登录循环。
                log.info("权限拦截器拦截到请求,className:{},methodName:{}",className,methodName);
                //如果是拦截到登录请求,不打印参数,因为参数里面有密码,全部会打印到日志中,防止日志泄露
                return true;//放过去。
            }
            log.info("权限拦截器拦截到请求,className:{},methodName:{},param:{}",className,methodName,requestParamBuffer.toString());
            User user = null;
            String loginToken = CookieUtil.readLoginToken(request);//从request里拿到logintoken
            if(StringUtils.isNotEmpty(loginToken)){
                String userJsonStr = RedisShardedPoolUtil.get(loginToken);//根据logintoken从redis里拿到用户字符串
                user = JsonUtil.string2Obj(userJsonStr,User.class);//把用户字符串转成对象
            }
            if(user == null || (user.getRole().intValue() != Const.Role.ROLE_ADMIN)){//如果用户为空或不是管理员。
                //返回false.即不会调用controller里的方法
                response.reset();//这里要添加reset,否则报异常 getWriter() has already been called for this response.
                response.setCharacterEncoding("UTF-8");//因为脱离的springmvc的返回流程,所以这里要设置编码,否则会乱码。
                response.setContentType("application/json;charset=UTF-8");//这里要设置返回值的类型,因为全部是json接口。
                PrintWriter out = response.getWriter();
             out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("拦截器拦截,用户未登录或无权限。")));
                out.flush();//把流中的数据清空。
                out.close();//geelynote 这里要关闭
                return false;
            }
            return true;
        }

    解决拦截登录循环:

    方案一:比较简单:在配置里排除。

        <mvc:interceptors>
            <mvc:interceptor>
                <mvc:mapping path="/manage/**"/>
                <mvc:exclude-mapping path="/manage/user/login.do"/>
                <bean class="com.mmall.controller.common.interceptor.AuthorityInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>

    方案二:比较灵活:在拦截器里判断。

            if(StringUtils.equals(className,"UserManageController") && StringUtils.equals(methodName,"login")){//根据方法名和类名判断登录操作把它放过。解决拦截登录循环。
                log.info("权限拦截器拦截到请求,className:{},methodName:{}",className,methodName);
                //如果是拦截到登录请求,不打印参数,因为参数里面有密码,全部会打印到日志中,防止日志泄露
                return true;//放过去。
            }
  • 相关阅读:
    python基础--函数的命名空间and作用域
    MYSQL基础常识
    python基础--函数
    python基础--文件相关操作
    python基础--字符编码以及文件操作
    homebrew长时间停在Updating Homebrew 这个步骤
    python基础--数据类型的常用方法2
    python基础--数据类型的常用方法1
    python基础--定义装饰器(内置装饰器)
    angular创建组件
  • 原文地址:https://www.cnblogs.com/yigechengxuyuan/p/8385823.html
Copyright © 2020-2023  润新知