SpringMVC核心技術(shù)
請求重定向和轉(zhuǎn)發(fā)
當(dāng)處理器對請求處理完畢后,向其它資源進(jìn)行跳轉(zhuǎn)是,有兩種跳轉(zhuǎn)方式:請求轉(zhuǎn)發(fā)與重定向。而根據(jù)索要跳轉(zhuǎn)的資源類型,又可分為兩類:跳轉(zhuǎn)到頁面與跳轉(zhuǎn)到其他處理器。
注意:對于請求轉(zhuǎn)發(fā)的頁面,可以是WEB-INF中頁面,而重定向的頁面,是不能為WEB-INF中的,因為重定向相當(dāng)于用戶再次發(fā)出一次請求,而用戶不能直接訪問WEB-INF中的資源。

SpringMVC框架把原來Servlet中的請求轉(zhuǎn)發(fā)和重定向操作進(jìn)行了封裝,現(xiàn)在可以使用簡單的方式實現(xiàn)轉(zhuǎn)發(fā)和重定向。
forward:表示轉(zhuǎn)發(fā),實現(xiàn)request.getRequestDispathcer("xx.jsp").forward();
redirect:表示重定向,實現(xiàn)response.sendRediect("xxx.jsp");
請求轉(zhuǎn)發(fā)
處理器方法返回 ModelAndView 時,需在 setViewName()指定的視圖前添加 forward:,且此時的視圖不再與視圖解析器一同工作,這樣可以在配置了解析器時指定不同位置的視圖。視圖頁面必須寫出相對于項目根的路徑。forward 操作不需要視圖解析器。處理器方法返回 String,在視圖路徑前面加入 forward: 視圖完整路徑。
@RequestMapping(value = "/some",produces = "text/plain;charset=utf-8")
public ModelAndView testForward(String name,Integer age){
ModelAndView mv = new ModelAndView();
mv.addObject("name",name);
mv.addObject("age",age);
mv.setViewName("forward:/WEB-INF/view/show.jsp");
return mv;
}
請求重定向
在處理器方法返回的視圖字符串的前面添加 redirect:,則可實現(xiàn)重定向跳轉(zhuǎn)。
@RequestMapping(value = "/other")
public ModelAndView testRedirect(String name,Integer age){
ModelAndView mv = new ModelAndView();
mv.addObject("name",name);
mv.addObject("age",age);
mv.setViewName("redirect:/other.jsp");
return mv;
}
異常處理
使用注解@ExceptionHandler 可以將一個方法指定為異常處理方法。該注解只有一個可選屬性 value,為一個 Class<?>數(shù)組,用于指定該注解的方法所要處理的異常類,即所要匹配的異常。而被注解的方法,其返回值可以是 ModelAndView、String,或 void,方法名隨意,方法參數(shù)可以是 Exception 及其子類對象、HttpServletRequest、HttpServletResponse 等。系統(tǒng)會自動為這些方法參數(shù)賦值。對于異常處理注解的用法,也可以直接將異常處理方法注解于 Controller 之中。
代碼演示
第一步:自定義兩個異常類
public class MyException extends Exception {
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
public class AgeException extends MyException {
public AgeException() {
super();
}
public AgeException(String message) {
super(message);
}
}
public class NameException extends MyException {
public NameException() {
super();
}
public NameException(String message) {
super(message);
}
}
第二步:在controller方法中拋出異常
@RequestMapping(value = "exception")
public ModelAndView askForException(String name,Integer age) throws MyException {
ModelAndView mv = new ModelAndView();
if(!"zs".equals(name)){
throw new NameException("姓名不正確!?。?);
}
if (age == null || age > 80){
throw new AgeException("年齡太大了?。?!");
}
mv.addObject("name",name);
mv.addObject("age",age);
mv.setViewName("show");
return mv;
第三步:定義三個異常響應(yīng)頁面
nameError.jsp
<br/>
提示信息:${msg}
<br/>
系統(tǒng)信息:${ex.message}
ageError.jsp
<br/>
提示信息:${msg}
<br/>
系統(tǒng)信息:${ex.message}
otherError.jsp
<br/>
提示信息:${msg}
<br/>
系統(tǒng)信息:${ex.message}
第四步:定義全局異常處理類
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = NameException.class)
public ModelAndView nameException(Exception ex){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","姓名不是zs");
mv.addObject("ex",ex);
mv.setViewName("nameError");
return mv;
}
@ExceptionHandler(value = AgeException.class)
public ModelAndView ageException(Exception ex){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","年齡超過80歲啦");
mv.addObject("ex",ex);
mv.setViewName("ageError");
return mv;
}
@ExceptionHandler
public ModelAndView otherException(Exception ex){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","未知異常");
mv.addObject("ex",ex);
mv.setViewName("otherError");
return mv;
}
}
第五步:在spring配置controller和handler的注解掃描
<!--開啟Controller注解掃描-->
<context:component-scan base-package="school.xauat.controller"></context:component-scan>
<!--配置視圖解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--開啟注解驅(qū)動-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--開啟ControllerAdvice注解掃描-->
<context:component-scan base-package="school.xauat.handler"></context:component-scan>
SpringMVC攔截器
SpringMVC 中的 Interceptor 攔截器是非常重要和相當(dāng)有用的,它的主要作用是攔截指定的用戶請求,并進(jìn)行相應(yīng)的預(yù)處理與后處理。其攔截的時間點在“處理器映射器根據(jù)用戶提交的請求映射出了所要執(zhí)行的處理器類,并且也找到了要執(zhí)行該處理器類的處理器適配器,在處理器適配器執(zhí)行處理器之前”。當(dāng)然,在處理器映射器映射出所要執(zhí)行的處理器類時,已經(jīng)將攔截器與處理器組合為了一個處理器執(zhí)行鏈,并返回給了中央調(diào)度器。
定義攔截器類
public class myInterceptor implements HandlerInterceptor {
private Long beginTime;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle方法執(zhí)行");
beginTime = System.currentTimeMillis();
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle方法執(zhí)行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion方法執(zhí)行");
Long endTime = System.currentTimeMillis();
System.out.println("程序執(zhí)行時間" + (endTime - beginTime) + "ms");
}
}
在springMVC配置文件注冊攔截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="school.xauat.handler.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
自定義攔截器,需要實現(xiàn) HandlerInterceptor 接口。而該接口中含有三個方法:
preHandle(request,response, Object handler):
該方法在處理器方法執(zhí)行之前執(zhí)行。其返回值為 boolean,若為 true,則緊接著會執(zhí)行處理器方法,且會將 afterCompletion()方法放入到一個專門的方法棧中等待執(zhí)行。
postHandle(request,response, Object handler,modelAndView):
該方法在處理器方法執(zhí)行之后執(zhí)行。處理器方法若最終未被執(zhí)行,則該方法不會執(zhí)行。由于該方法是在處理器方法執(zhí)行完后執(zhí)行,且該方法參數(shù)中包含 ModelAndView,所以該方法可以修改處理器方法的處理結(jié)果數(shù)據(jù),且可以修改跳轉(zhuǎn)方向。
afterCompletion(request,response, Object handler, Exception ex):
當(dāng) preHandle()方法返回 true 時,會將該方法放到專門的方法棧中,等到對請求進(jìn)行響應(yīng)的所有工作完成之后才執(zhí)行該方法。即該方法是在中央調(diào)度器渲染(數(shù)據(jù)填充)了響應(yīng)頁面之后執(zhí)行的,此時對 ModelAndView 再操作也對響應(yīng)無濟(jì)于事。
afterCompletion 最后執(zhí)行的方法,清除資源,例如在 Controller 方法中加入數(shù)據(jù)
攔截器中方法和處理器方法的執(zhí)行順序如下圖

當(dāng)有多個攔截器時

攔截器過濾器的區(qū)別
攔截器和過濾器的區(qū)別
1、過濾器是Servlet中的對象。攔截器是框架中的對象
2、過濾器是實現(xiàn)Filter接口的對象。攔截器是實現(xiàn)HandlerInterceptor接口
3、過濾器用來設(shè)置request和response的參數(shù)、屬性。
4、過濾器是在攔截器之前先執(zhí)行的
5、過濾器是Tomcat服務(wù)器中創(chuàng)建的對象,攔截器是springmvc容器中創(chuàng)建的對象
6、過濾器是一個執(zhí)行時間點,攔截器有三個執(zhí)行時間點
7、過濾器可以處理jsp、js、html等,攔截器是側(cè)重攔截對controller的對象,如果你的請求不能被中央調(diào)度器接受,這個請求就不會執(zhí)行攔截內(nèi)容
SpringMVC執(zhí)行流程理解

SpringMVC執(zhí)行流程分析
(1)瀏覽器提交請求到中央調(diào)度器
(2)中央調(diào)度器直接將請求轉(zhuǎn)給處理器映射器。
(3)處理器映射器會根據(jù)請求,找到處理該請求的處理器,并將其封裝為處理器執(zhí)行鏈后返回給中央調(diào)度器。
(4)中央調(diào)度器根據(jù)處理器執(zhí)行鏈中的處理器,找到能夠執(zhí)行該處理器的處理器適配器。
(5)處理器適配器調(diào)用執(zhí)行處理器。
(6)處理器將處理結(jié)果及要跳轉(zhuǎn)的視圖封裝到一個對象 ModelAndView 中,并將其返回給處理器適配器。
(7)處理器適配器直接將結(jié)果返回給中央調(diào)度器。
(8)中央調(diào)度器調(diào)用視圖解析器,將 ModelAndView 中的視圖名稱封裝為視圖對象。
(9)視圖解析器將封裝了的視圖對象返回給中央調(diào)度器
(10)中央調(diào)度器調(diào)用視圖對象,讓其自己進(jìn)行渲染,即進(jìn)行數(shù)據(jù)填充,形成響應(yīng)對象。
(11)中央調(diào)度器響應(yīng)瀏覽器。
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Spring數(shù)據(jù)庫多數(shù)據(jù)源路由配置過程圖解
這篇文章主要介紹了Spring數(shù)據(jù)庫多數(shù)據(jù)源路由配置過程圖解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06
Java基礎(chǔ)詳解之集合框架工具Collections
這篇文章主要介紹了Java基礎(chǔ)詳解之集合框架工具Collections,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-04-04
Java深入了解數(shù)據(jù)結(jié)構(gòu)之哈希表篇
哈希表是一種根據(jù)關(guān)鍵碼去尋找值的數(shù)據(jù)映射結(jié)構(gòu),該結(jié)構(gòu)通過把關(guān)鍵碼映射的位置去尋找存放值的地方,說起來可能感覺有點復(fù)雜,我想我舉個例子你就會明白了,最典型的的例子就是字典2022-01-01
MyBatis查詢數(shù)據(jù),賦值給List集合時,數(shù)據(jù)缺少的問題及解決
這篇文章主要介紹了MyBatis查詢數(shù)據(jù),賦值給List集合時,數(shù)據(jù)缺少的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01

