Spring中的Interceptor 攔截器 專題



spring-webmvc-4.3.14.RELEASE.jar

org.springframework.web.servlet.DispatcherServlet#doDispatch 

 

    /**
     * Process the actual dispatching to the handler.
     * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
     * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
     * to find the first that supports the handler class.
     * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
     * themselves to decide which methods are acceptable.
     * @param request current HTTP request
     * @param response current HTTP response
     * @throws Exception in case of any kind of processing failure
     */
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);

                // Determine handler for the current request.
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                applyDefaultViewName(processedRequest, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we're processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }

 

 攔截器的preHandle

                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }


攔截器的postHandle

                mappedHandler.applyPostHandle(processedRequest, response, mv);

 

攔截器的afterCompletion

        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }

 

 

這三個方法的執行流程:

發起請求,進入攔截器鏈,運行所有攔截器的preHandle方法.
當preHandle方法返回false時,(后面的攔截器就不再執行了)從當前攔截器往回執行所有攔截器的afterCompletion方法(當前這個攔截器的afterCompletion不會被執行。此時所有的preHandle和postHandle都執行完畢),再退出攔截器鏈。

當preHandle方法全為true時,執行下一個攔截器的preHandle,直到所有攔截器的preHandle執行完。
再運行被攔截的Controller。然后進入攔截器鏈,運行所有攔截器的postHandle方法(執行順序與preHandle的順序相反。在postHandle中,有機會修改ModelAndView),
完后從最后一個攔截器往回執行所有攔截器的afterCompletion方法(執行順序與preHandle的順序相反,與postHandle相同。用於清理資源).
當有攔截器拋出異常時,會從當前攔截器往回執行所有攔截器的afterCompletion方法


preHandle方法:
返回true,映射處理器執行鏈將繼續執行;
當返回false時,DispatcherServlet處理器認為攔截器已經處理完了請求(這個請求已經被攔截了:http請求的status是200,但response什么也沒有),而不繼續執行執行鏈中的其它攔截器和處理器。

實現org.springframework.web.servlet.HandlerInterceptor接口的攔截器:

MyInterceptor1
MyInterceptor2
MyInterceptor3

package com.tangcheng.learning.web.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author tangcheng
 * 2018/03/06
 */
@Slf4j
public class MyInterceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info(">>>MyInterceptor1>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)");
        return true;// 只有返回true才會繼續向下執行,返回false取消當前請求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
            modelAndView) throws Exception {
        log.info(">>>MyInterceptor1>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).");
        if (modelAndView != null) {
            log.info("ViewName:{}", modelAndView.getViewName());
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception
            ex) throws Exception {
        log.info(">>>MyInterceptor1>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)");
    }
}

 

 

package com.tangcheng.learning.web.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author tangcheng
 * 2018/03/06
 */
@Slf4j
public class MyInterceptor2 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info(">>>MyInterceptor2>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)");
        return true;// 只有返回true才會繼續向下執行,返回false取消當前請求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
            modelAndView) throws Exception {
        log.info(">>>MyInterceptor2>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).");
        if (modelAndView != null) {
            log.info("ViewName:{}", modelAndView.getViewName());
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception
            ex) throws Exception {
        log.info(">>>MyInterceptor2>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)");
    }
}

 

package com.tangcheng.learning.web.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author tangcheng
 * 2018/03/06
 */
@Slf4j
public class MyInterceptor3 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info(">>>MyInterceptor3>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)");
        return true;// 只有返回true才會繼續向下執行,返回false取消當前請求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
            modelAndView) throws Exception {
        log.info(">>>MyInterceptor3>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).");
        if (modelAndView != null) {
            log.info("ViewName:{}", modelAndView.getViewName());
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception
            ex) throws Exception {
        log.info(">>>MyInterceptor3>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)");

    }
}

 

Spring boot下的配置:

package com.tangcheng.learning.web.config;

import com.tangcheng.learning.web.interceptor.MyInterceptor1;
import com.tangcheng.learning.web.interceptor.MyInterceptor2;
import com.tangcheng.learning.web.interceptor.MyInterceptor3;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @author tangcheng
 * 2018/03/06
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    /**
     * MyInterceptor2中的preHandle返回false如下執行情況。並且相關rest請求頁面不會正常響應,即頁面會白屏
     * c.t.learning.interceptor.MyInterceptor1  : >>>MyInterceptor1>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
     * c.t.learning.interceptor.MyInterceptor2  : >>>MyInterceptor2>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
     * c.t.learning.interceptor.MyInterceptor1  : >>>MyInterceptor1>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        super.addInterceptors(registry);
        registry.addInterceptor(new MyInterceptor1());
        registry.addInterceptor(new MyInterceptor2());
        registry.addInterceptor(new MyInterceptor3());
    }
}


Controller層代碼:

package com.tangcheng.learning.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author tangcheng
 * 2018/03/06
 */
@Controller
public class IndexController {

    @RequestMapping("/")
    public String index() {
        return "index";
    }

}

 

報錯時的執行日志:
有個奇怪的現象,攔截器會被同一線程連續調用兩次,為什么呢?【升級Spring Boot版本從1.5.9.RELEASE1.5.10.RELEASE后連續調用兩次的問題消失了.Tomcat版本升級到了8.5

2018-03-06 11:21:45.342  INFO 18208 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-03-06 11:21:45.343  INFO 18208 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2018-03-06 11:21:45.358  INFO 18208 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 15 ms
2018-03-06 11:21:45.366  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.366  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.366  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.372  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.372  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : ViewName:index
2018-03-06 11:21:45.372  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.372  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : ViewName:index
2018-03-06 11:21:45.372  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.372  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : ViewName:index
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : ViewName:index
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : ViewName:index
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : ViewName:index
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 11:21:45.377  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 11:21:45.381 ERROR 18208 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] threw exception

javax.servlet.ServletException: Circular view path [index]: would dispatch back to the current handler URL [/index] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
    at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:205) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:145) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1286) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1041) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:467) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:392) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:168) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1286) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1041) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]

2018-03-06 11:21:45.385  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 11:21:45.385  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 11:21:45.385  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 11:21:45.385 ERROR 18208 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Circular view path [index]: would dispatch back to the current handler URL [/index] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)] with root cause

javax.servlet.ServletException: Circular view path [index]: would dispatch back to the current handler URL [/index] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
    at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:205) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:145) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1286) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1041) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:467) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:392) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:168) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1286) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1041) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]

2018-03-06 11:21:45.389  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.389  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.389  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 11:21:45.420  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.420  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.420  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 11:21:45.420  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 11:21:45.420  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 11:21:45.420  INFO 18208 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)

 

升級到Spring Boot1.5.10.RELEASE后的日志打印情況:

2018-03-06 18:26:59.988  INFO 23388 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-03-06 18:26:59.988  INFO 23388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2018-03-06 18:27:00.003  INFO 23388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 14 ms
2018-03-06 18:27:00.013  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 18:27:00.013  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 18:27:00.013  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 18:27:00.019  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 18:27:00.020  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : ViewName:index
2018-03-06 18:27:00.020  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 18:27:00.020  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : ViewName:index
2018-03-06 18:27:00.020  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 18:27:00.020  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : ViewName:index
2018-03-06 18:27:00.029  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 18:27:00.029  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 18:27:00.029  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 18:27:00.031  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 18:27:00.031  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 18:27:00.031  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>preHandle在請求處理之前進行調用(Controller方法調用之前)
2018-03-06 18:27:00.037  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 18:27:00.037  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : ViewName:error
2018-03-06 18:27:00.037  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 18:27:00.037  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : ViewName:error
2018-03-06 18:27:00.037  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>postHandle請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后).
2018-03-06 18:27:00.037  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : ViewName:error
2018-03-06 18:27:00.046  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor3     : >>>MyInterceptor3>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 18:27:00.046  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor2     : >>>MyInterceptor2>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)
2018-03-06 18:27:00.046  INFO 23388 --- [nio-8080-exec-1] c.t.l.web.interceptor.MyInterceptor1     : >>>MyInterceptor1>>>>>>>afterCompletion.在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)

 

 

spring mvc DispatcherServlet詳解之interceptor和filter的區別

http://www.cnblogs.com/softidea/p/7426072.html

Spring Boot實現一個監聽用戶請求的攔截器
http://www.cnblogs.com/softidea/p/5987764.html

 

 

1.配置攔截器

在springMVC.xml配置文件增加:

<mvc:interceptors>
  <!-- 日志攔截器 -->
  <mvc:interceptor>
   <mvc:mapping path="/**" />
   <mvc:exclude-mapping path="/static/**" />
   <bean class="攔截器java代碼路徑" />
  </mvc:interceptor>
</mvc:interceptors>

說明:

1)mvc:mapping 攔截器路徑配置

2)mvc:exclude-mapping 攔截器不需要攔截的路徑

public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(userLoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns(
                        "/robots.txt");
}

http://www.68idc.cn/help/buildlang/ask/20150424325278.html

 

Since Spring 3, Java configuration (@Configuration) has been moved into spring-core and has caught my attention. This is a quick sample of how to convert an existing servlet.xml file into a java config file extending WebMvcConfigurerAdapter.

Beginning xml

sample-servlet.xml
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<? xml version = "1.0" encoding = "UTF-8" ?>
< beans xmlns = "http://www.springframework.org/schema/beans"
        xmlns:mvc = "http://www.springframework.org/schema/mvc"
        xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context = "http://www.springframework.org/schema/context"
        xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd" >
 
     <!-- Scan for spring annotated components -->
     < context:component-scan base-package = "com.luckyryan.sample" />
 
     <!-- Process annotations on registered beans like @Autowired... -->
     < context:annotation-config />
 
     <!-- This tag registers the DefaultAnnotationHandlerMapping and
          AnnotationMethodHandlerAdapter beans that are required for Spring MVC  -->
     < mvc:annotation-driven />
 
     <!-- Exception Resolver that resolves exceptions through @ExceptionHandler methods -->
     < bean class = "org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver" />
 
     <!-- View Resolver for JSPs -->
     < bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" >
         < property name = "prefix" value = "/WEB-INF/pages/" />
         < property name = "suffix" value = ".jsp" />
     </ bean >
 
     <!-- This tag allows for mapping the DispatcherServlet to "/" -->
     < mvc:default-servlet-handler />
 
     <!-- resources exclusions from servlet mapping -->
     < mvc:resources mapping = "/assets/**" location = "classpath:/META-INF/resources/webjars/" />
     < mvc:resources mapping = "/css/**" location = "/css/" />
     < mvc:resources mapping = "/img/**" location = "/img/" />
     < mvc:resources mapping = "/js/**" location = "/js/" />
 
</ beans >

1. Create the configuration class, I like to create a “config” package with a class named appConfig.java
2. Add @Configuration, this will let spring know this contains bean definitions.

appConfig.java
01
02
03
04
05
06
07
08
package com.luckyryan.sample.config;
 
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class appConfig {
 
}

3. Add @EnableWebMVC, this is the same as <mvc:annotation-driven/>

appConfig.java
01
02
03
04
05
@EnableWebMvc
@Configuration
public class appConfig {
 
}

4. Add @ComponentScan(basePackages = {“com.luckyryan.sample”}), this is the same as <context:component-scan base-package=”com.luckyryan.sample”/>

appConfig.java
01
02
03
04
05
06
@EnableWebMvc
@ComponentScan (basePackages = { "com.luckyryan.sample" })
@Configuration
public class appConfig {
 
}

5. Extend the class to use WebMvcConfigurerAdapter. This adds stub implementations from the WebMvcConfigurer interface which is used by @EnableWebMVC. It also gives us a chance to override resources and the default handler.

appConfig.java
01
02
03
04
05
06
@EnableWebMvc
@ComponentScan (basePackages = { "com.luckyryan.sample" })
@Configuration
public class appConfig extends WebMvcConfigurerAdapter {
 
}

6. Declare our static resources. I added cache to the java config but it’s not required.

appConfig.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
@EnableWebMvc
@ComponentScan (basePackages = { "com.luckyryan.sample" })
@Configuration
public class appConfig extends WebMvcConfigurerAdapter {
 
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
         registry.addResourceHandler( "/assets/**" ).addResourceLocations( "classpath:/META-INF/resources/webjars/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/css/**" ).addResourceLocations( "/css/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/img/**" ).addResourceLocations( "/img/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/js/**" ).addResourceLocations( "/js/" ).setCachePeriod( 31556926 );
     }
 
}

7. Set default servlet handler, this is the same as <mvc:default-servlet-handler/>

appConfig.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@EnableWebMvc
@ComponentScan (basePackages = { "com.luckyryan.sample" })
@Configuration
public class appConfig extends WebMvcConfigurerAdapter {
 
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
         registry.addResourceHandler( "/assets/**" ).addResourceLocations( "classpath:/META-INF/resources/webjars/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/css/**" ).addResourceLocations( "/css/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/img/**" ).addResourceLocations( "/img/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/js/**" ).addResourceLocations( "/js/" ).setCachePeriod( 31556926 );
     }
 
     @Override
     public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
         configurer.enable();
     }
 
     @Bean
     public InternalResourceViewResolver getInternalResourceViewResolver() {
         InternalResourceViewResolver resolver = new InternalResourceViewResolver();
         resolver.setPrefix( "/WEB-INF/pages/" );
         resolver.setSuffix( ".jsp" );
         return resolver;
     }
}

8. Add bean for InternalResourceViewResolver

appConfig.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.luckyryan.sample.config;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
 
@EnableWebMvc
@ComponentScan (basePackages = { "com.luckyryan.sample" })
@Configuration
public class appConfig extends WebMvcConfigurerAdapter {
 
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
         registry.addResourceHandler( "/assets/**" ).addResourceLocations( "classpath:/META-INF/resources/webjars/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/css/**" ).addResourceLocations( "/css/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/img/**" ).addResourceLocations( "/img/" ).setCachePeriod( 31556926 );
         registry.addResourceHandler( "/js/**" ).addResourceLocations( "/js/" ).setCachePeriod( 31556926 );
     }
 
     @Override
     public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
         configurer.enable();
     }
 
     @Bean
     public InternalResourceViewResolver getInternalResourceViewResolver() {
         InternalResourceViewResolver resolver = new InternalResourceViewResolver();
         resolver.setPrefix( "/WEB-INF/pages/" );
         resolver.setSuffix( ".jsp" );
         return resolver;
     }
}

9. Update the servlet declaration in web.xml for the new config class and annotation conf. Note: this replaces the need for <context:annotation-config/> which was not featured in the servlet.xml example.

web.xml
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
...
< servlet >
     < servlet-name >sample</ servlet-name >
     < servlet-class >org.springframework.web.servlet.DispatcherServlet</ servlet-class >
     < init-param >
         < param-name >contextClass</ param-name >
         < param-value >
             org.springframework.web.context.support.AnnotationConfigWebApplicationContext
         </ param-value >
     </ init-param >
     < init-param >
         < param-name >contextConfigLocation</ param-name >
         < param-value >
             com.luckyryan.sample.config.appConfig
         </ param-value >
     </ init-param >
</ servlet >
 
< servlet-mapping >
     < servlet-name >sample</ servlet-name >
     < url-pattern >/</ url-pattern >
</ servlet-mapping >
https://www.luckyryan.com/2013/02/07/migrate-spring-mvc-servlet-xml-to-java-config/

I am at a loss moving from Spring XML to Java-config

http://stackoverflow.com/questions/15438835/i-am-at-a-loss-moving-from-spring-xml-to-java-config

 

 SpringMVC 中的Interceptor 攔截器也是相當重要和相當有用的,它的主要作用是攔截用戶的請求並進行相應的處理。比如通過它來進行權限驗證,或者是來判斷用戶是否登陸,或者是像12306 那樣子判斷當前時間是否是購票時間。

一、定義Interceptor實現類

 

SpringMVC 中的Interceptor 攔截請求是通過HandlerInterceptor 來實現的。在SpringMVC 中定義一個Interceptor 非常簡單,主要有兩種方式,第一種方式是要定義的Interceptor類要實現了Spring 的HandlerInterceptor 接口,或者是這個類繼承實現了HandlerInterceptor 接口的類,比如Spring 已經提供的實現了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter ;第二種方式是實現Spring的WebRequestInterceptor接口,或者是繼承實現了WebRequestInterceptor的類。

(一)實現HandlerInterceptor接口

HandlerInterceptor 接口中定義了三個方法,我們就是通過這三個方法來對用戶的請求進行攔截處理的。

(1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顧名思義,該方法將在請求處理之前進行調用。SpringMVC 中的Interceptor 是鏈式的調用的,在一個應用中或者說是在一個請求中可以同時存在多個Interceptor 。每個Interceptor 的調用會依據它的聲明順序依次執行,而且最先執行的都是Interceptor 中的preHandle 方法,所以可以在這個方法中進行一些前置初始化操作或者是對當前請求的一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布爾值Boolean 類型的,當它返回為false 時,表示請求結束,后續的Interceptor 和Controller 都不會再執行;當返回值為true 時就會繼續調用下一個Interceptor 的preHandle 方法,如果已經是最后一個Interceptor 的時候就會是調用當前請求的Controller 方法。

(2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解釋我們知道這個方法包括后面要說到的afterCompletion 方法都只能是在當前所屬的Interceptor 的preHandle 方法的返回值為true 時才能被調用。postHandle 方法,顧名思義就是在當前請求進行處理之后,也就是Controller 方法調用之后執行,但是它會在DispatcherServlet 進行視圖返回渲染之前被調用,所以我們可以在這個方法中對Controller 處理之后的ModelAndView 對象進行操作。postHandle 方法被調用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會后執行,這和Struts2 里面的Interceptor 的執行過程有點類型。Struts2 里面的Interceptor 的執行過程也是鏈式的,只是在Struts2 里面需要手動調用ActionInvocation 的invoke 方法來觸發對下一個Interceptor 或者是Action 的調用,然后每一個Interceptor 中在invoke 方法調用之前的內容都是按照聲明順序執行的,而invoke 方法之后的內容就是反向的。

(3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,該方法也是需要當前對應的Interceptor 的preHandle 方法的返回值為true 時才會執行。顧名思義,該方法將在整個請求結束之后,也就是在DispatcherServlet 渲染了對應的視圖之后執行。這個方法的主要作用是用於進行資源清理工作的。

下面是一個簡單的代碼說明:

 

Java代碼
  1. import javax.servlet.http.HttpServletRequest;
  2. import javax.servlet.http.HttpServletResponse;
  3. import org.springframework.web.servlet.HandlerInterceptor;
  4. import org.springframework.web.servlet.ModelAndView;
  5. public class SpringMVCInterceptor implements HandlerInterceptor {
  6. /**
  7. * preHandle方法是進行處理器攔截用的,顧名思義,該方法將在Controller處理之前進行調用,SpringMVC中的Interceptor攔截器是鏈式的,可以同時存在
  8. * 多個Interceptor,然后SpringMVC會根據聲明的前后順序一個接一個的執行,而且所有的Interceptor中的preHandle方法都會在
  9. * Controller方法調用之前調用。SpringMVC的這種Interceptor鏈式結構也是可以進行中斷的,這種中斷方式是令preHandle的返
  10. * 回值為false,當preHandle的返回值為false的時候整個請求就結束了。
  11. */
  12. @Override
  13. public boolean preHandle(HttpServletRequest request,
  14. HttpServletResponse response, Object handler) throws Exception {
  15. // TODO Auto-generated method stub
  16. return false;
  17. }
  18. /**
  19. * 這個方法只會在當前這個Interceptor的preHandle方法返回值為true的時候才會執行。postHandle是進行處理器攔截用的,它的執行時間是在處理器進行處理之
  20. * 后,也就是在Controller的方法調用之后執行,但是它會在DispatcherServlet進行視圖的渲染之前執行,也就是說在這個方法中你可以對ModelAndView進行操
  21. * 作。這個方法的鏈式結構跟正常訪問的方向是相反的,也就是說先聲明的Interceptor攔截器該方法反而會后調用,這跟Struts2里面的攔截器的執行過程有點像,
  22. * 只是Struts2里面的intercept方法中要手動的調用ActionInvocation的invoke方法,Struts2中調用ActionInvocation的invoke方法就是調用下一個Interceptor
  23. * 或者是調用action,然后要在Interceptor之前調用的內容都寫在調用invoke之前,要在Interceptor之后調用的內容都寫在調用invoke方法之后。
  24. */
  25. @Override
  26. public void postHandle(HttpServletRequest request,
  27. HttpServletResponse response, Object handler,
  28. ModelAndView modelAndView) throws Exception {
  29. // TODO Auto-generated method stub
  30. }
  31. /**
  32. * 該方法也是需要當前對應的Interceptor的preHandle方法的返回值為true時才會執行。該方法將在整個請求完成之后,也就是DispatcherServlet渲染了視圖執行,
  33. * 這個方法的主要作用是用於清理資源的,當然這個方法也只能在當前這個Interceptor的preHandle方法的返回值為true時才會執行。
  34. */
  35. @Override
  36. public void afterCompletion(HttpServletRequest request,
  37. HttpServletResponse response, Object handler, Exception ex)
  38. throws Exception {
  39. // TODO Auto-generated method stub
  40. }
  41. }

 

 

(二)實現WebRequestInterceptor 接口

WebRequestInterceptor 中也定義了三個方法,我們也是通過這三個方法來實現攔截的。這三個方法都傳遞了同一個參數WebRequest ,那么這個WebRequest 是什么呢?這個WebRequest 是Spring 定義的一個接口,它里面的方法定義都基本跟HttpServletRequest 一樣,在WebRequestInterceptor 中對WebRequest 進行的所有操作都將同步到HttpServletRequest 中,然后在當前請求中一直傳遞。

(1 )preHandle(WebRequest request) 方法。該方法將在請求處理之前進行調用,也就是說會在Controller 方法調用之前被調用。這個方法跟HandlerInterceptor 中的preHandle 是不同的,主要區別在於該方法的返回值是void ,也就是沒有返回值,所以我們一般主要用它來進行資源的准備工作,比如我們在使用Hibernate 的時候可以在這個方法中准備一個Hibernate 的Session 對象,然后利用WebRequest 的setAttribute(name, value, scope) 把它放到WebRequest 的屬性中。這里可以說說這個setAttribute 方法的第三個參數scope ,該參數是一個Integer 類型的。在WebRequest 的父層接口RequestAttributes 中對它定義了三個常量:

SCOPE_REQUEST :它的值是0 ,代表只有在request 中可以訪問。

SCOPE_SESSION :它的值是1 ,如果環境允許的話它代表的是一個局部的隔離的session,否則就代表普通的session,並且在該session范圍內可以訪問。

SCOPE_GLOBAL_SESSION :它的值是2 ,如果環境允許的話,它代表的是一個全局共享的session,否則就代表普通的session,並且在該session 范圍內可以訪問。

(2 )postHandle(WebRequest request, ModelMap model) 方法。該方法將在請求處理之后,也就是在Controller 方法調用之后被調用,但是會在視圖返回被渲染之前被調用,所以可以在這個方法里面通過改變數據模型ModelMap 來改變數據的展示。該方法有兩個參數,WebRequest 對象是用於傳遞整個請求數據的,比如在preHandle 中准備的數據都可以通過WebRequest 來傳遞和訪問;ModelMap 就是Controller 處理之后返回的Model 對象,我們可以通過改變它的屬性來改變返回的Model 模型。

(3 )afterCompletion(WebRequest request, Exception ex) 方法。該方法會在整個請求處理完成,也就是在視圖返回並被渲染之后執行。所以在該方法中可以進行資源的釋放操作。而WebRequest 參數就可以把我們在preHandle 中准備的資源傳遞到這里進行釋放。Exception 參數表示的是當前請求的異常對象,如果在Controller 中拋出的異常已經被Spring 的異常處理器給處理了的話,那么這個異常對象就是是null 。

 

下面是一個簡單的代碼說明:

Java代碼
  1. import org.springframework.ui.ModelMap;
  2. import org.springframework.web.context.request.WebRequest;
  3. import org.springframework.web.context.request.WebRequestInterceptor;
  4. public class AllInterceptor implements WebRequestInterceptor {
  5. /**
  6. * 在請求處理之前執行,該方法主要是用於准備資源數據的,然后可以把它們當做請求屬性放到WebRequest中
  7. */
  8. @Override
  9. public void preHandle(WebRequest request) throws Exception {
  10. // TODO Auto-generated method stub
  11. System.out.println("AllInterceptor...............................");
  12. request.setAttribute("request", "request", WebRequest.SCOPE_REQUEST);//這個是放到request范圍內的,所以只能在當前請求中的request中獲取到
  13. request.setAttribute("session", "session", WebRequest.SCOPE_SESSION);//這個是放到session范圍內的,如果環境允許的話它只能在局部的隔離的會話中訪問,否則就是在普通的當前會話中可以訪問
  14. request.setAttribute("globalSession", "globalSession", WebRequest.SCOPE_GLOBAL_SESSION);//如果環境允許的話,它能在全局共享的會話中訪問,否則就是在普通的當前會話中訪問
  15. }
  16. /**
  17. * 該方法將在Controller執行之后,返回視圖之前執行,ModelMap表示請求Controller處理之后返回的Model對象,所以可以在
  18. * 這個方法中修改ModelMap的屬性,從而達到改變返回的模型的效果。
  19. */
  20. @Override
  21. public void postHandle(WebRequest request, ModelMap map) throws Exception {
  22. // TODO Auto-generated method stub
  23. for (String key:map.keySet())
  24. System.out.println(key + "-------------------------");;
  25. map.put("name3", "value3");
  26. map.put("name1", "name1");
  27. }
  28. /**
  29. * 該方法將在整個請求完成之后,也就是說在視圖渲染之后進行調用,主要用於進行一些資源的釋放
  30. */
  31. @Override
  32. public void afterCompletion(WebRequest request, Exception exception)
  33. throws Exception {
  34. // TODO Auto-generated method stub
  35. System.out.println(exception + "-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-=");
  36. }
  37. }

 

二、把定義的攔截器類加到SpringMVC的攔截體系中

 

1.在SpringMVC的配置文件中加上支持MVC的schema

Xml代碼
  1. xmlns:mvc="http://www.springframework.org/schema/mvc"
  2. xsi:schemaLocation=" http://www.springframework.org/schema/mvc
  3. http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"

下面是我的聲明示例:

Xml代碼
  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  3. xmlns:mvc="http://www.springframework.org/schema/mvc"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  6. http://www.springframework.org/schema/context
  7. http://www.springframework.org/schema/context/spring-context-3.0.xsd
  8. http://www.springframework.org/schema/mvc
  9. http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

這樣在SpringMVC的配置文件中就可以使用mvc標簽了,mvc標簽中有一個mvc:interceptors是用於聲明SpringMVC的攔截器的。

 

(二)使用mvc:interceptors標簽來聲明需要加入到SpringMVC攔截器鏈中的攔截器

Xml代碼
  1. <mvc:interceptors>
  2. <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 -->
  3. <bean class="com.host.app.web.interceptor.AllInterceptor"/>
  4. <mvc:interceptor>
  5. <mvc:mapping path="/test/number.do"/>
  6. <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 -->
  7. <bean class="com.host.app.web.interceptor.LoginInterceptor"/>
  8. </mvc:interceptor>
  9. </mvc:interceptors>

由上面的示例可以看出可以利用mvc:interceptors標簽聲明一系列的攔截器,然后它們就可以形成一個攔截器鏈,攔截器的執行順序是按聲明的先后順序執行的,先聲明的攔截器中的preHandle方法會先執行,然而它的postHandle方法和afterCompletion方法卻會后執行。

在mvc:interceptors標簽下聲明interceptor主要有兩種方式:

(1)直接定義一個Interceptor實現類的bean對象。使用這種方式聲明的Interceptor攔截器將會對所有的請求進行攔截。

(2)使用mvc:interceptor標簽進行聲明。使用這種方式進行聲明的Interceptor可以通過mvc:mapping子標簽來定義需要進行攔截的請求路徑。

經過上述兩步之后,定義的攔截器就會發生作用對特定的請求進行攔截了。

 

(三)使用JAVA代碼配置Interceptor

配置spring mvc的攔截器WebMvcConfigurerAdapter

public class WebAppConfig extends WebMvcConfigurerAdapter  

實現添加攔截器方法

public void addInterceptors(InterceptorRegistry registry){  
  
}  
registry.addInterceptor可以通過此方法添加攔截器, 可以是spring提供的或者自己添加的 

例子

復制代碼
public class WebAppConfig extends WebMvcConfigurerAdapter{    
    public static void main(String[] args) {  
        SpringApplication.run(WebAppConfig.class, args);  
    }   
      
    /** 
     * 配置攔截器 
     * @author lance 
     * @param registry 
     */  
    public void addInterceptors(InterceptorRegistry registry) {  
        registry.addInterceptor(new UserSecurityInterceptor()).addPathPatterns("/user/**");  
    }  
}  
  
UserSecurityInterceptor代碼  
public class UserSecurityInterceptor implements HandlerInterceptor {  
  
    @Override  
    public boolean preHandle(HttpServletRequest request,  
            HttpServletResponse response, Object handler) throws Exception {  
          
        return true;  
    }  
  
    @Override  
    public void postHandle(HttpServletRequest request,  
            HttpServletResponse response, Object handler,  
            ModelAndView modelAndView) throws Exception {  
    }  
  
    @Override  
    public void afterCompletion(HttpServletRequest request,  
            HttpServletResponse response, Object handler, Exception ex)  
            throws Exception {  
  
    }  
  
} 
復制代碼

 

http://www.cnblogs.com/hyl8218/p/6056817.html

 


免責聲明!

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



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