zoukankan      html  css  js  c++  java
  • SpringMVC拦截器使用

    源码地址

    拦截器interceptor

    拦截器是URL请求的第一道门,所有请求会先经过拦截器interceptor,然后再进入controller
    下面,记录一种通过注解方法拦截所有需要登录才能发起的请求,并且把非法请求重定向到登录界面

    xml文件基本配置

    <!--配置拦截器, 多个拦截器,顺序执行 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
            <mvc:mapping path="/**" />
            <!--resource不拦截-->
            <mvc:exclude-mapping path="/asset/**"/>
            <mvc:exclude-mapping path="/assets/**"/>
            <!--聊天室websocket不拦截-->
            <mvc:exclude-mapping path="/sockjs/websocket"/>
            <mvc:exclude-mapping path="/websocket"/>
            <bean class="com.iss.blog.interceptor.AccessControlInterceptor"/>
        </mvc:interceptor>
        <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
    </mvc:interceptors>
    <!-- 静态资源访问(不拦截此目录下的东西的访问)  -->
    <mvc:resources location="/asset/"  mapping="/asset/**" />
    <mvc:resources location="/assets/"  mapping="/assets/**" />
    

    关键实现HandlerInterceptorAdapter

    public abstract class AbstractInterceptor extends HandlerInterceptorAdapter {
        /**
         * 是否有 PublicPage注解
         * @param handlerMethod
         * @return
         */
        protected  boolean isPublicPage(HandlerMethod handlerMethod){
            if (handlerMethod==null)
                return false;
            PublicPage publicPage = handlerMethod.getMethodAnnotation(PublicPage.class);
            if (publicPage!=null){
                return true;
            }
            return false;
        }
        /**
         * 某个请求是否ajax请求
         * @param request
         * @return
         */
        protected boolean isAjaxRequest(HttpServletRequest request){
            String requestType = request.getHeader("X-Requested-With");
            if("XMLHttpRequest".equals(requestType)){
                System.out.println("is AJAX request");
                return true;
            }else{
                System.out.println("is not AJAX request");
                return false;
            }
        }
    }
    
    
        public class AccessControlInterceptor extends AbstractInterceptor {
        /**
         * 下面这段话参考了某片文章,由于找不回原文,所以参考链接不贴
         * 在业务处理器处理请求之前被调用
         * 如果返回false
         *     从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
         * 如果返回true
         *    执行下一个拦截器,直到所有的拦截器都执行完毕
         *    再执行被拦截的Controller
         *    然后进入拦截器链,
         *    从最后一个拦截器往回执行所有的postHandle()
         *    接着再从最后一个拦截器往回执行所有的afterCompletion()
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            if (handler instanceof  HandlerMethod &&isPublicPage((HandlerMethod) handler)){
                return true;
            }
            if(没有登录){
                PrintWriter out = response.getWriter();
                out.append(
                        "{'resultCode':1012,'resultMessage':'错误的请求'}"
                );
                if (!isAjaxRequest(request)) {
                //这里把请求转发给登录界面
                    request.getRequestDispatcher("/login").forward(request, response);
                }
                return false;
            }else
                return true;
        }
    
        /**
         * 在业务处理器处理请求执行完成后,生成视图之前执行的动作
         * 可在modelAndView中加入数据,比如当前时间
         */
        @Override
        public void postHandle(HttpServletRequest request,
                               HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {
        }
    
        /**
         * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
         *
         * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
         */
        @Override
        public void afterCompletion(HttpServletRequest request,
                                    HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
    
        }
    }
    

    定义的注解

    @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface PublicPage {
        String value() default "";
    }
    

    这样,在@RequestMapping上加上@PublicPage就代表,这样路由不需要登录就可以请求到,否则需要登录后才能请求到
    比如登录页面:

    @PublicPage
    @RequestMapping("/login")
    public  String loginPage(){
        return "frontend/account/login";
    }
    

    必须为ajax请求才可以访问

     @RequestMapping(value = "/registerValidate",headers = { "X-Requested-With=XMLHttpRequest" })
    
  • 相关阅读:
    看淘宝营销api 文档有感
    创业公司如何做好数据驱动的开发工作
    docker 常见错误总结
    从npm 角度理解 mvn 的 pom.xml
    best practices for designing web api
    我对自动化测试的一些认识
    Docker学习笔记
    Docker命令学习
    JVM学习笔记三:垃圾收集器与内存分配策略
    JVM学习笔记二:JVM参数
  • 原文地址:https://www.cnblogs.com/chenjingquan/p/8973540.html
Copyright © 2011-2022 走看看