您好,登錄后才能下訂單哦!
Spring MVC高級技術(shù)包括但不限于web.xml配置、異常處理、跨重定向請求傳遞數(shù)據(jù)
1、web.xml文件的配置
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springMvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
ContextLoaderListener是根容器,DispatcherServlet是子容器。父容器中管理的bean可以被子容器引用,反之,不行。它們都從各自的xml文件初始化自己的上下文
ContextLoaderListener如果未指定contextConfigLocation參數(shù),則默認(rèn)加載的配置文件為/WEB-INF/applicationContext.xml
DispatcherServlet如果未指定contextConfigLocation參數(shù),則根據(jù)<servlet-name>元素指定的名稱,在/WEB-INF/文件夾下尋找配置文件appServlet-servlet.xml
2、處理異常
Spring提供了多種方式將異常轉(zhuǎn)換為響應(yīng)
1)特定的 Spring異常會自動映射為指定的HTTP狀態(tài)碼
如果在控制器中拋出了異常,該異常不在列表中,又沒有指定HTTP狀態(tài)碼,則默認(rèn)為狀態(tài)碼為500
2)異常上可以添加@ResponseStatus注解,將異常映射為某一個HTTP狀態(tài)碼
@Controller public class HelloController { @RequestMapping("/home") public String home(){ System.out.println("執(zhí)行home"); throw new MyException(); // return "home"; //返回一個字符串,即邏輯視圖名 } }
package com.cn.Exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; public class MyException extends RuntimeException{ }
瀏覽器訪問 http://localhost:8080/home
修改自定義異常
package com.cn.Exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "拋出異常的原因") public class MyException extends RuntimeException{ }
瀏覽器訪問 http://localhost:8080/home
3)在方法上可以添加@ExceptionHandler注解,使其用來處理異常
該方式是按照處理請求的方式處理異常,@ExceptionHandler注解的方法返回值為字符串表示邏輯視圖名
package com.cn.Exception; public class MyException2 extends RuntimeException{ }
@Controller public class HelloController { @RequestMapping("/home") public String home(){ System.out.println("執(zhí)行home"); throw new MyException2(); // return "home"; //返回一個字符串,即邏輯視圖名 } @ExceptionHandler(MyException2.class) public String handleMException(){ System.out.println("處理異常邏輯"); return "fail"; } }
訪問http://localhost:8080/home,后臺輸出
瀏覽器頁面
@ExceptionHandler注解的方法可以處理同一個控制器中所有處理器方法所拋出的異常(注解指定的異常),注解定義如下
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ExceptionHandler { Class<? extends Throwable>[] value() default {}; }
spring也支持為控制器添加通知,那么該通知對于所有的控制器中所有的處理器方法拋出的異常都起作用,實現(xiàn)如下
@ControllerAdvice 所標(biāo)注的類會被組件掃描實例化,交給容器管理。最為實用的一個場景是將所有@ExceptionHandler標(biāo)注的方法收集到一個類中,這樣所有的控制器異常就能在一個地方進(jìn)行一致處理。以下HandleException類定義表明在控制器中的處理器拋出MyException2類的異常,就會被handleMException方法處理,最終跳轉(zhuǎn)fail.jsp頁面
package com.cn.advice; import com.cn.Exception.MyException2; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice public class HandleException { @ExceptionHandler(MyException2.class) public String handleMException(){ System.out.println("處理異常邏輯"); return "fail"; } }
3、跨重定向請求傳遞數(shù)據(jù)
如果是forward轉(zhuǎn)發(fā)請求,那么處理器方法業(yè)務(wù)處理完成后,該方法所指定的模型數(shù)據(jù)會復(fù)制到請求中,作為請求的一部分,轉(zhuǎn)發(fā)到下一個處理器,下一個處理器可以從請求中獲取上一個處理的模型數(shù)據(jù);
如果是redirect重新向,原始請求就結(jié)束了,并且會重新發(fā)起一個GET請求。因此原始請求中的模型數(shù)據(jù)也就消失了,在請求到達(dá)下一個處理器,沒有任何的模型數(shù)據(jù),需要模型數(shù)據(jù)必須自己處理。
針對重定向傳遞數(shù)據(jù),有兩種方案:
1)使用URL模板以路徑變量和/或查詢參數(shù)的形式傳遞數(shù)據(jù)
@Controller public class HelloController { @RequestMapping("/home2") public String home2(Model model){ model.addAttribute("id","12324131343256"); model.addAttribute("name","pick"); return "redirect:home3/{id}"; //含有redirect的字符串,表示重定向到另一個處理器; //如果含有forward的字符串,表示轉(zhuǎn)向到另一個處理器 } @RequestMapping("/home3/{id}") public String home3(@PathVariable String id, Model model){ System.out.println("傳遞的ID="+id); model.addAttribute(new User()); return "home"; } }
瀏覽器訪問localhost:8080/home2,抓包得訪問的url。從以下可以看出,處理器完成后重定向時,模型中的數(shù)據(jù)填充到了路徑變量中,路徑變量中沒有的key,則以查詢參數(shù)的形式賦在url之后,組成了新的url訪問。
2)使用flash屬性傳遞數(shù)據(jù)
重定向時候,采用1)中的方式傳遞數(shù)據(jù),僅僅能夠傳遞簡單的數(shù)據(jù),不能傳遞對象。如何將對象也能傳遞到下一個處理器呢?可以將要傳遞到下一個處理器的數(shù)據(jù)放入用戶會話中,然后在下一個處理器從會話的取出來,并刪除會話中的該數(shù)據(jù)。然而,spring提供了將數(shù)據(jù)發(fā)送為flash屬性的功能,不需要我們管理這些數(shù)據(jù),flash屬性會一致攜帶這些數(shù)據(jù)直到下一次請求才消失。
Spring提供RedirectAttributes是Model接口的子接口,除了提供Model的所有功能,還提供了幾個方法用來設(shè)置flash屬性。
@Controller public class HelloController { @RequestMapping("/home2") public String home2(RedirectAttributes model){ model.addAttribute("id","12324131343256"); model.addFlashAttribute("user",new User("liming","123456"));//設(shè)置flash屬性,也可以 model.addFlashAttribute(new User("liming","123456")) //則通過值得類型自行推斷出key為user return "redirect:home3/{id}"; } @RequestMapping("/home3/{id}") public String home3(@PathVariable String id, RedirectAttributes model){ System.out.println("傳遞的ID="+id); if (model.containsAttribute("user")) { System.out.println("傳遞的對象:" + model.getFlashAttributes().get("user")); } return "home"; } }
異常測試
在controller、service、dao中任意一處需要手動拋出異常。
如果是程序中手動拋出的異常,在錯誤頁面中顯示自定義的異常信息,如果不是手動拋出異常說明是一個運(yùn)行時異常,在錯誤頁面只顯示“未知錯誤”。
在商品修改的controller方法中拋出異常 .
在service接口中拋出異常:
如果與業(yè)務(wù)功能相關(guān)的異常,建議在service中拋出異常。
與業(yè)務(wù)功能沒有關(guān)系的異常,建議在controller中拋出。
上邊的功能,建議在service中拋出異常。
總結(jié):
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。