Springmvc中的轉發(fā)重定向和攔截器

Springmvc中的轉發(fā)重定向和攔截器

可變參數

可變參數在設計方法時,使用數據類型...來聲明參數類型,例如:public static void function(int... numbers)
在實現方法體時,可變參數是作為數組來處理

public class Test {
    
    public static void main(String[] args) {
        System.out.println(Test.sum(1,2,3));
        System.out.println(Test.sum(1,2,3,4,54));
    }

    public static int sum(int... numbers){
        int sum=0;
        
        for(int i=0;i<numbers.length;i++){
            sum+=numbers[i];
        }
        return sum;
    }
}

注意: 每個方法中,最多只允許存在1個可變參數,并且,如果存在可變參數,那么必須是最后一個參數

轉發(fā)和重定向

  • 在控制器內部處理請求的方法中,默認返回字符串時的處理方式是轉發(fā),轉發(fā)的值是view組件的名稱,比如return "login",實質上會根據視圖解析器(ViewResolver)得到最終負責顯示的頁面,而通過return redirect:路徑這樣的語法表示重定向,在redirect:右側的內容是路徑,這個路徑通常使用相對的路徑,是以當前客戶端的地址欄中的路徑為標準進行參考,例如當前的地址為:http://localhost:8080/Project/user/reg.do,然后return "redirect:login.do",則會重定向到http://localhost:8080/Project/user/login.do,如果return "redirect:/main/index.do"或者return "redirect:../main/index.do",則會重定向到http://localhost:8080/Project/main/index.do

forward:

  • 默認的方式,但是也是可以使用return "forward:login"
  • 返回的一定是一個view,經過視圖解析器之后會轉發(fā)到指定的視圖

redirect:

  • 重定向 : return "redirect:login.do"
  • 返回的是一個Controller方法的路徑,而不是一個view,這個不會經過視圖解析器,而是直接跳轉

實例

@RequestMapping(value="/handle_reg.do", method=RequestMethod.POST)
    public String handleReg(User user,ModelMap map) {
        try {
            userService.reg(user);
            System.out.println("注冊成功!");
            return "redirect:login.do";  //重定向到login.do這個控制方法,login.do對應的就是轉發(fā)到login.jsp
        } catch (UsernameConflictException e) {
            System.out.println(e.getMessage());
            map.put("errorMessage", e.getMessage());
            return "error";
        }
    }
    
    @RequestMapping(value="login.do")
    public String handleLogin() {
        return "login";
    }

攔截器

基本概念

  1. 攔截器(interceptor)是springmvc中的一個組件,是運行在DispatcherServlet之后,運行在Controller之前的
  2. 攔截器可以決定對某些符合條件的進行攔截或者放行,所以,通常用于對一些具有相同運行條件的功能進行約束

使用攔截器

自定義攔截器類

  1. 創(chuàng)建一個攔截類(DemoInterceptor),實現HandlerInterceptor接口
public class DemoInterceptor implements HandlerInterceptor {

    /**
     * 處理器執(zhí)行之前調用
     * @param request  HttpServletRequest對象,可以獲取請求參數等等
     * @param response HttpServletResponse對象
     * @param Handler  攔截器的Controller對象
     * @return 如果返回false,就會中斷處理流程,不會處理后續(xù)的攔截器和Controller。如果返回true,則會執(zhí)行后續(xù)的攔截器和處理器
     */
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        
        System.out.println("DemoInterceptor的PreHandler執(zhí)行");
        return true;
    }

    /**
     * 處理器執(zhí)行之后調用,跳轉到指定視圖之前調用
     * @param request  HttpServletRequest對象
     * @param response HttpServletResponse對象
     * @param Handler  攔截器的Controller對象
     * @param modelAndView  ModelAndView對象,其中存放的是處理結果和視圖的信息
     */
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        /**
         * 1. 可以自己設計邏輯,例如某些情況下返回false,返回true
         * 2. 返回true表示執(zhí)行后續(xù)的處理器和攔截器,返回false會中斷處理流程
         */
        System.out.println("handler:"+handler);
        System.out.println("DemoInterceptor的PostHandler執(zhí)行");
        //設置視圖的名稱,那么執(zhí)行完成之后就會條跳轉到index.jsp頁面
        //modelAndView.setViewName("index");  
    }
    
    /**
     * 請求處理完成之后調用
     */
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("DemoInterceptor的afterCompletion執(zhí)行");

    }

}

在springmvc的配置文件中配置

  1. 配置攔截的路徑:<mvc:mapping path=""/> 可以使用通配符* 比如:/**匹配所有的路徑,/user/*只能匹配/user的子路徑
  2. 配置不攔截的路徑 : <mvc:exclude-mapping path=""/> 可以配置多個
  3. 配置攔截器類(bean) : <bean class="">

配置

  • 必須按照上面的順序配置,否則將會報錯
    <!-- 配置攔截器,其中可以配置多個攔截器 -->
    <mvc:interceptors>
        
        <mvc:interceptor>
        
            <!-- 配置攔截器的攔截路徑,攔截/user下的全部處理器方法映射
                比如:http://localhost:8080/Springmvc/user/login.do這個請求就會被攔截
             -->
            <mvc:mapping path="/user/*"/>
            
            <!-- 配置不被該攔截器攔截器的controller方法,這個是可選配置
                比如:http://localhost:8080/Springmvc/user/index.do將不會被攔截器
            -->
            <mvc:exclude-mapping path="/user/index.do"/> 
            <mvc:exclude-mapping path="/user/login.do"/>  
            
            <!-- 配置攔截器的bean,指定的是全類名 -->
            <bean class="cn.tedu.spring.interceptor.DemoInterceptor"></bean>
        </mvc:interceptor>
        
    </mvc:interceptors>

其中實現的方法

  1. public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)
    • 該方法在controller處理請求之前執(zhí)行
    • 如果返回的false,則會中斷處理流程,不會執(zhí)行后續(xù)的攔截器和處理器,返回true會執(zhí)行后續(xù)的攔截器和處理器
    • 可以自行設計邏輯返回false或者true
  2. public void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView)
    • 處理器執(zhí)行之后,視圖處理之前調用,此時可以通過對ModelAndView對數據和視圖進行處理
    • 當然需要prehandler方法返回true才會執(zhí)行
  3. public void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)
    • 所有的請求處理完畢之后調用,比如性能監(jiān)控中,我們可以在此記錄結束時間和消耗時間,還可以進行一些資源處理
    • 當然需要prehandler方法返回true才會執(zhí)行

演示登錄檢查

  1. 登錄檢查: 當涉及到用戶信息的修改,查看什么的,必須要驗證是否登錄,因此需要設計攔截器驗證登錄
  2. 先設定登錄數據,即: 在login.jsp中添加登錄按鈕,登錄完成之后,需要自己定義一個標記存儲在session中,比如用戶的id或者用戶的對象
  3. 我們使用用戶的id作為標記驗證是否已經的登錄,如果用戶登錄成功,會在session中添加一個uid的屬性
  4. 用戶退出登錄使用session.invalidate();清除session,并且重定向到登錄界面

自定義攔截器(LoginInterceptor)

  • 具體流程在prehandler方法中寫的很清楚
public class LoginInterceptor implements HandlerInterceptor{
    /*
     * 在處理器執(zhí)行之前調用(non-Javadoc)
     * 1. 獲取session
     * 2. 讀取session中的uid的值
     *      如果為null,表示沒有登錄,那么直接重定向到登錄界面,同時返回false,不需要執(zhí)行后面的流程了
     *      如果不為null,表示已經登錄了,那么直接返回true,繼續(xù)執(zhí)行后面的攔截器或者處理器
     */
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        HttpSession session=request.getSession();   //獲取session
        Object uid=session.getAttribute("uid");  //讀取session中的對象
        //如果uid存在,那么即可登錄完成
        if (uid!=null) {
            return true;   //返回true,登錄成功就需要執(zhí)行后續(xù)的流程
        }
        response.sendRedirect(request.getContextPath()+"/user/login.do");  //重定向到登錄界面
        return false;   //返回false,后面的流程也不用執(zhí)行了,直接中斷
    }

    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        
    }
}

springmvc中配置攔截器

  • 由于這里只是跳轉到用戶中心需要驗證登錄,那么只是匹配了user_center.do
<!-- 配置攔截器,其中可以配置多個攔截器 -->    
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/user/user_center.do"/>
            <bean class="cn.tedu.spring.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

多個攔截器的執(zhí)行順序

  • 根據在springmvc配置文件中配置的順序執(zhí)行,即是在<mvc:interceptors>下配置的攔截器的順序,如果對同一個路徑進行了攔截器,那么先配置的先攔截

攔截器和過濾器的區(qū)別(主要的區(qū)別)

  1. 攔截器是springmvc中,僅僅當使用springmvc才可以使用攔截器,過濾器是Java EE體系中的,無論使用哪種框架都可以使用過濾器
  2. 攔截器在DispatcherServlet之后,在處理器之前執(zhí)行,過濾器在DispatcherServlet之前執(zhí)行
  3. 過濾器會在所有的servlet之前執(zhí)行(所有的請求都會執(zhí)行),而攔截器會在springmvc中DispatcherServlet之后執(zhí)行,所以過濾器在項目中可以過濾任何請求(只要是配置了對應的路徑),而攔截器只會在DispatcherServlet處理的請求的基礎之上進行攔截

總結

  • 當多種請求都需要做相同或者極為相似的任務時,可以使用攔截器
  • 開發(fā)好攔截器,那么需要在springmvc的配置文件中配置
  • <mvc:interceptors>可以有如果若干個<mvc:interceptor>,即是配置若干個攔截器,配置的多個攔截器將會形成攔截器鏈,如果配置多個攔截器對同一個路徑都會攔截,那么會按照配置的節(jié)點順序執(zhí)行。
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,931評論 1 92
  • 對于java中的思考的方向,1必須要看前端的頁面,對于前端的頁面基本的邏輯,如果能理解最好,不理解也要知道幾點。 ...
    神尤魯道夫閱讀 896評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現,斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • “我無意放大世界的善意,也無意放大世界的惡意,只是依照比例,老實接受有晴有雨的天氣,世界與我,相互而已”
    ZWE閱讀 152評論 0 0
  • 15年前的今天我成為你的妻子,一路走來風風雨雨,有歡笑也有淚水,共同見證了我們點點滴滴的幸福。 我們相識...
    涓涓淺語閱讀 1,084評論 0 3

友情鏈接更多精彩內容