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";
}
攔截器
基本概念
- 攔截器(
interceptor)是springmvc中的一個組件,是運行在DispatcherServlet之后,運行在Controller之前的 - 攔截器可以決定對某些符合條件的進行
攔截或者放行,所以,通常用于對一些具有相同運行條件的功能進行約束
使用攔截器
自定義攔截器類
- 創(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的配置文件中配置
- 配置攔截的路徑:
<mvc:mapping path=""/>可以使用通配符*比如:/**匹配所有的路徑,/user/*只能匹配/user的子路徑 - 配置不攔截的路徑 :
<mvc:exclude-mapping path=""/>可以配置多個 - 配置攔截器類(
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>
其中實現的方法
-
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)- 該方法在
controller處理請求之前執(zhí)行 - 如果返回的
false,則會中斷處理流程,不會執(zhí)行后續(xù)的攔截器和處理器,返回true會執(zhí)行后續(xù)的攔截器和處理器 - 可以自行設計邏輯返回
false或者true
- 該方法在
-
public void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView)- 處理器執(zhí)行之后,視圖處理之前調用,此時可以通過對
ModelAndView對數據和視圖進行處理 - 當然需要
prehandler方法返回true才會執(zhí)行
- 處理器執(zhí)行之后,視圖處理之前調用,此時可以通過對
-
public void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)- 所有的請求處理完畢之后調用,比如性能監(jiān)控中,我們可以在此記錄結束時間和消耗時間,還可以進行一些資源處理
- 當然需要
prehandler方法返回true才會執(zhí)行
演示登錄檢查
- 登錄檢查: 當涉及到用戶信息的修改,查看什么的,必須要驗證是否登錄,因此需要設計攔截器驗證登錄
- 先設定登錄數據,即: 在
login.jsp中添加登錄按鈕,登錄完成之后,需要自己定義一個標記存儲在session中,比如用戶的id或者用戶的對象 - 我們使用用戶的
id作為標記驗證是否已經的登錄,如果用戶登錄成功,會在session中添加一個uid的屬性 - 用戶退出登錄使用
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ū)別)
- 攔截器是springmvc中,僅僅當使用
springmvc才可以使用攔截器,過濾器是Java EE體系中的,無論使用哪種框架都可以使用過濾器 - 攔截器在
DispatcherServlet之后,在處理器之前執(zhí)行,過濾器在DispatcherServlet之前執(zhí)行 - 過濾器會在所有的
servlet之前執(zhí)行(所有的請求都會執(zhí)行),而攔截器會在springmvc中DispatcherServlet之后執(zhí)行,所以過濾器在項目中可以過濾任何請求(只要是配置了對應的路徑),而攔截器只會在DispatcherServlet處理的請求的基礎之上進行攔截
總結
- 當多種請求都需要做相同或者極為相似的任務時,可以使用攔截器
- 開發(fā)好攔截器,那么需要在
springmvc的配置文件中配置 - 在
<mvc:interceptors>可以有如果若干個<mvc:interceptor>,即是配置若干個攔截器,配置的多個攔截器將會形成攔截器鏈,如果配置多個攔截器對同一個路徑都會攔截,那么會按照配置的節(jié)點順序執(zhí)行。