spring mvc高級(jí)技術(shù)包括但不限于web.xml配置、異常處理、跨重定向請(qǐng)求傳遞數(shù)據(jù)
1、web.xml文件的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<!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)
- 特定的 spring異常會(huì)自動(dòng)映射為指定的http狀態(tài)碼
- 異常上可以添加@responsestatus注解,將異常映射為某一個(gè)http狀態(tài)碼
- 在方法上可以添加@exceptionhandler注解,使其用來處理異常
1)特定的 spring異常會(huì)自動(dòng)映射為指定的http狀態(tài)碼
如果在控制器中拋出了異常,該異常不在列表中,又沒有指定http狀態(tài)碼,則默認(rèn)為狀態(tài)碼為500
2)異常上可以添加@responsestatus注解,將異常映射為某一個(gè)http狀態(tài)碼
1
2
3
4
5
6
7
8
9
10
|
@controller public class hellocontroller { @requestmapping ( "/home" ) public string home(){ system.out.println( "執(zhí)行home" ); throw new myexception(); // return "home"; //返回一個(gè)字符串,即邏輯視圖名 } } |
1
2
3
4
5
6
7
|
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
修改自定義異常
1
2
3
4
5
6
7
8
9
|
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注解,使其用來處理異常
該方式是按照處理請(qǐng)求的方式處理異常,@exceptionhandler注解的方法返回值為字符串表示邏輯視圖名
1
2
3
4
5
|
package com.cn.exception; public class myexception2 extends runtimeexception{ } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@controller public class hellocontroller { @requestmapping ( "/home" ) public string home(){ system.out.println( "執(zhí)行home" ); throw new myexception2(); // return "home"; //返回一個(gè)字符串,即邏輯視圖名 } @exceptionhandler (myexception2. class ) public string handlemexception(){ system.out.println( "處理異常邏輯" ); return "fail" ; } } |
訪問http://localhost:8080/home,后臺(tái)輸出
瀏覽器頁面
@exceptionhandler注解的方法可以處理同一個(gè)控制器中所有處理器方法所拋出的異常(注解指定的異常),注解定義如下
1
2
3
4
5
6
|
@target ({elementtype.method}) @retention (retentionpolicy.runtime) @documented public @interface exceptionhandler { class <? extends throwable>[] value() default {}; } |
spring也支持為控制器添加通知,那么該通知對(duì)于所有的控制器中所有的處理器方法拋出的異常都起作用,實(shí)現(xiàn)如下
@controlleradvice 所標(biāo)注的類會(huì)被組件掃描實(shí)例化,交給容器管理。最為實(shí)用的一個(gè)場(chǎng)景是將所有@exceptionhandler標(biāo)注的方法收集到一個(gè)類中,這樣所有的控制器異常就能在一個(gè)地方進(jìn)行一致處理。以下handleexception類定義表明在控制器中的處理器拋出myexception2類的異常,就會(huì)被handlemexception方法處理,最終跳轉(zhuǎn)fail.jsp頁面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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、跨重定向請(qǐng)求傳遞數(shù)據(jù)
如果是forward轉(zhuǎn)發(fā)請(qǐng)求,那么處理器方法業(yè)務(wù)處理完成后,該方法所指定的模型數(shù)據(jù)會(huì)復(fù)制到請(qǐng)求中,作為請(qǐng)求的一部分,轉(zhuǎn)發(fā)到下一個(gè)處理器,下一個(gè)處理器可以從請(qǐng)求中獲取上一個(gè)處理的模型數(shù)據(jù);
如果是redirect重新向,原始請(qǐng)求就結(jié)束了,并且會(huì)重新發(fā)起一個(gè)get請(qǐng)求。因此原始請(qǐng)求中的模型數(shù)據(jù)也就消失了,在請(qǐng)求到達(dá)下一個(gè)處理器,沒有任何的模型數(shù)據(jù),需要模型數(shù)據(jù)必須自己處理。
針對(duì)重定向傳遞數(shù)據(jù),有兩種方案:
- 使用url模板以路徑變量和/或查詢參數(shù)的形式傳遞數(shù)據(jù)
- 使用flash屬性傳遞數(shù)據(jù)
1)使用url模板以路徑變量和/或查詢參數(shù)的形式傳遞數(shù)據(jù)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@controller public class hellocontroller { @requestmapping ( "/home2" ) public string home2(model model){ model.addattribute( "id" , "12324131343256" ); model.addattribute( "name" , "pick" ); return "redirect:home3/{id}" ; //含有redirect的字符串,表示重定向到另一個(gè)處理器; //如果含有forward的字符串,表示轉(zhuǎn)向到另一個(gè)處理器 } @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í),模型中的數(shù)據(jù)填充到了路徑變量中,路徑變量中沒有的key,則以查詢參數(shù)的形式賦在url之后,組成了新的url訪問。
2)使用flash屬性傳遞數(shù)據(jù)
重定向時(shí)候,采用1)中的方式傳遞數(shù)據(jù),僅僅能夠傳遞簡(jiǎn)單的數(shù)據(jù),不能傳遞對(duì)象。如何將對(duì)象也能傳遞到下一個(gè)處理器呢?可以將要傳遞到下一個(gè)處理器的數(shù)據(jù)放入用戶會(huì)話中,然后在下一個(gè)處理器從會(huì)話的取出來,并刪除會(huì)話中的該數(shù)據(jù)。然而,spring提供了將數(shù)據(jù)發(fā)送為flash屬性的功能,不需要我們管理這些數(shù)據(jù),flash屬性會(huì)一致攜帶這些數(shù)據(jù)直到下一次請(qǐng)求才消失。
spring提供redirectattributes是model接口的子接口,除了提供model的所有功能,還提供了幾個(gè)方法用來設(shè)置flash屬性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@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( "傳遞的對(duì)象:" + model.getflashattributes().get( "user" )); } return "home" ; } } |
異常測(cè)試
在controller、service、dao中任意一處需要手動(dòng)拋出異常。
如果是程序中手動(dòng)拋出的異常,在錯(cuò)誤頁面中顯示自定義的異常信息,如果不是手動(dòng)拋出異常說明是一個(gè)運(yùn)行時(shí)異常,在錯(cuò)誤頁面只顯示“未知錯(cuò)誤”。
在商品修改的controller方法中拋出異常 .
在service接口中拋出異常:
如果與業(yè)務(wù)功能相關(guān)的異常,建議在service中拋出異常。
與業(yè)務(wù)功能沒有關(guān)系的異常,建議在controller中拋出。
上邊的功能,建議在service中拋出異常。
總結(jié):
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。
原文鏈接:https://www.cnblogs.com/shixiemayi/p/9569338.html