springmvc-攔截器

1.css

Spring MVC 的處理器攔截器相似於 Servlet 開發中的過濾器 Filter,用於對處理器進行預處理和後處理。
用戶能夠本身定義一些攔截器來實現特定的功能。
談到攔截器,還要向你們提一個詞——攔截器鏈(Interceptor Chain)。攔截器鏈就是將攔截器按必定的順
序聯結成一條鏈。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其以前定義的順序被調用。
說到這裏,可能你們腦海中有了一個疑問,這不是咱們以前學的過濾器嗎?是的它和過濾器是有幾分類似,但
是也有區別,接下來咱們就來講說他們的區別:
過濾器是 servlet 規範中的一部分, 任何 java web 工程均可以使用。
攔截器是 SpringMVC 框架本身的,只有使用了 SpringMVC 框架的工程才能用。
過濾器在 url-pattern 中配置了/*以後,能夠對全部要訪問的資源攔截。
攔截器它是隻會攔截訪問的控制器方法,若是訪問的是 jsp, html,css,image 或者 js 是不會進行攔
截的。
它也是 AOP 思想的具體應用。
咱們要想自定義攔截器, 要求必須實現: HandlerInterceptor 接口。

2.做用過程html

攔截器的做用對象的controller,攔截器有個放行的功能,能夠在放行以前和以後編寫一些代碼java

預處理,在請求controller以前,會先通過攔截器web

後處理,在請求controller以後,跳轉某個頁面以前,會通過攔截器spring

攔截器鏈,也就是會有多個攔截器,好比第一個攔截器放行了,會再通過第二個攔截器...一直到沒有了,纔會執行controller,返回依然。spring-mvc

 

 

 演示

1、jsp頁面

1.index.jspmvc

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>攔截器</title>
</head>
<body>
    <h3>攔截器</h3>
    <a href="user/testInterceptor">測試攔截器</a>
</body>
</html>

2.跳轉成功頁面success.jsp,會有一個在控制檯輸出的代碼,方便演示app

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>跳轉成功</h3>
    <%System.out.println("run success.jsp...");%>
</body>
</html>

3.跳轉失敗的頁面error.jsp框架

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>跳轉失敗頁面</h3>
</body>
</html>

2、控制器

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/testInterceptor")
    public String testInterceptor(){
        System.out.println("run testInterceptor()...");
        return "success";
    }
}

3、攔截器

攔截器須要實現HandlerInterceptor類,這個類有三個方法jsp

1.preHandle()方法

這裏先演示第一個方法,也就是在controller執行以前的方法

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 預處理,controller執行以前執行這個方法
     * @param request
     * @param response
     * @param handler
     * @return true,表示放行,會執行這個方法的代碼,而後再執行下一個攔截器,若是沒有,則執行controller中的方法;
     *         false則表示不放行,也就是隻執行這個方法的代碼,不會執行controller中的方法,能夠經過request和response直接跳轉到某個頁面
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("run MyInterceptor1.preHandle()...");
//        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        return true;
    }
}

攔截器須要在springmvc.xml配置文件中配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.cong.controller"></context:component-scan>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!--配置攔截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--要攔截的具體的方法-->
            <mvc:mapping path="/user/*"/>
            <!--不要攔截的具體的方法-->
            <!--<mvc:exclude-mapping path=""/>-->
            <!--配置攔截器對象-->
            <bean class="com.cong.interceptor.MyInterceptor"/>
        </mvc:interceptor>
        <!--配置第二個攔截器要另外寫一個mvc:interceptor-->
        <!--<mvc:interceptor></mvc:interceptor>-->
    </mvc:interceptors>
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

結果,根據打印的內容,能夠看出,

先是執行了攔截器的preHandle()方法,而後放行,執行controller中的方法,最後跳轉到success.jsp頁面

 

 

若是, 將preHandle()方法的返回值設置爲false,那麼就是攔截器不容許經過,

也就是不會執行controller中的方法,再取消註釋,手動跳轉到error.jsp頁面

結果以下,根據控制檯的打印內容,

先是執行了攔截器的preHandle()方法,而後不放行,再也不執行controller中的方法,直接跳轉到error.jsp頁面

 

 

 2.postHandle()方法

在preHandle()的基礎上添加一個postHandle()方法

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 預處理,controller執行以前執行這個方法
     * @param request
     * @param response
     * @param handler
     * @return true,表示放行,執行下一個攔截器,若是沒有,則執行controller中的方法;
     *          false則表示不放行,能夠經過request和response直接跳轉到某個頁面
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("run MyInterceptor1.preHandle()...");
//        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        return true;
    }

    /**
     * 後處理的方法,當controller的方法執行完,要進行頁面跳轉了(也就是執行success.jsp),就會先這個方法
     * 也能夠直接進行頁面跳轉
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("run MyInterceptor1.postHandle()...");
//        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
    }
}

結果以下,也就是先執行了preHandle()方法,而後執行controller中的方法,再執行postHandle()方法,最後跳轉到success.jsp頁面

 

 

postHandle()沒有返回值,可是同樣能夠直接進行頁面跳轉,若是直接進行頁面跳轉,結果以下

也就是先執行了preHandle()方法,而後執行controller中的方法,再執行postHandle()方法,最後跳轉到error.jsp頁面

(雖然打印了run success.jsp...   但實際上並無跳轉到success。jsp)

 

 

 3.afterCompletion()方法

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 預處理,controller執行以前執行這個方法
     * @param request
     * @param response
     * @param handler
     * @return true,表示放行,執行下一個攔截器,若是沒有,則執行controller中的方法;
     *          false則表示不放行,能夠經過request和response直接跳轉到某個頁面
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("run MyInterceptor1.preHandle()...");
//        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        return true;
    }

    /**
     * 後處理的方法,當controller的方法執行完,要進行頁面跳轉了(也就是執行success.jsp),就會先這個方法
     * 也能夠直接進行頁面跳轉
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("run MyInterceptor1.postHandle()...");
        //request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
    }

    /**
     * success.jsp執行以後再執行的方法,通常用做釋放資源
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("run MyInterceptor1.afterCompletion()...");
    }
}

結果以下,也就是afterComplition()方法是在頁面跳轉以後再進行執行的

 

 在這裏,再寫一個攔截器

public class MyInterceptor2 implements HandlerInterceptor {
    /**
     * 預處理,controller執行以前執行這個方法
     * @param request
     * @param response
     * @param handler
     * @return true,表示放行,執行下一個攔截器,若是沒有,則執行controller中的方法;
     *          false則表示不放行,能夠經過request和response直接跳轉到某個頁面
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("run MyInterceptor2.preHandle()...");
//        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        return true;
    }

    /**
     * 後處理的方法,當controller的方法執行完,要進行頁面跳轉了(也就是執行success.jsp),就會通過這個方法
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("run MyInterceptor2.postHandle()...");
//        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
    }

    /**
     * success.jsp執行以後再執行的方法,通常用做釋放資源
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("run MyInterceptor2.afterCompletion()...");
    }
}

注入到容器中

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/user/*"/>
            <bean class="com.cong.interceptor.MyInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.cong.interceptor.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

執行的過程以下

相關文章
相關標籤/搜索