七、Spring MVC高級技術

知識點

  • 處理文件上傳
  • 使用flash屬性
  • 在控制器中處理異常

關鍵詞

  • 控制器通知 (Controller Advice)

7.1 處理異常

Spring提供了多種方式將異常轉換爲響應:

  • 特定的Spring異常將會自動映射爲指定的HTTP狀態碼
  • 異常上可以添加@RequestStatus註解,從而將其映射爲某一個HTTP狀態碼
  • 在方法上可以添加@ExceptionHandler註解,使其用來處理異常

最簡單的方式就是第二種,映射。

7.1.1 將異常映射爲HTTP狀態碼

在默認情況下,Spring會將自身的一些異常自動轉化爲合適的狀態碼。

Spring異常 HTTP狀態碼
BindException 400-Bad Request
ConversionNotSupportedException 500-Internal Server Error
HttpMessageNotReadableException 400-Bad Request
HttpMessageNotWriteableException 500-Internal Server Error
HttpRequestMethodNotSupportedException 405-Method Not Allowed
MethodArgumentNotValidException 400-Bad Request
MissingServletRequestParameterException 400-Bad Request
MissingServletRequestPartException 400-Bad Request
NoSuchRequestHandlingMethodException 404-Not Found
TypeMismatchException 400-Bad Request
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Spittle Not Found")
public class .....

7.2 爲控制器添加通知

控制器通知是任意帶有@ControllerAdvice註解的類,這個類包含以下的方法:

  • @ExceptionHandler 註解標註的fangfa
  • @InitBinder註解標註的方法
  • @ModelAttribute註解標註的方法
    以上這些方法會自動運用到整個應用程序所有控制器中帶有@RequestMapping註解的方法上。
// 寫一個控制器異常處理類
package test
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
// 定義控制器類
@ControllerAdvice
public class AppWideExceptionHandler {
	// 定義處理異常的方法
	@ExceptionHandler(DuplicateSpittleException.class)
	public String duplicateSpittleHandler() {
		return "error/duplicate";
	}
}

如果任何地方拋出DuplicateSpittleException,則會調用duplicateSpittleHandler方法來處理異常。

7.5 跨重定向請求傳遞數據

在5.4說了重定向的基礎功能,Spring還爲其提供了其他的輔助功能。

Q:正在發起重定向功能的方法該如何發送數據給重定向的目標方法呢?

當一個處理器方法完成之後,該方法所指定的模型數據將會複製到請求中,並作爲請求中的屬性,請求會轉發到視圖上進行渲染。因爲控制器方法和視圖所處理的是同一個請求,所以在轉發中請求屬性能夠得以保存。

以上是請求的處理內容,但是重定向不同。
當控制器返回的結果是重定向的話,原始的請求就結束了,並且會發起新的一個GET請求。原始請求中帶有的參數也會一起消失,在新請求屬性中,沒有任何來自模型的數據,必須通過方法內獲取後,賦值到重定向的結果中,作爲新請求的數據。

重定向傳遞數據的兩種方法:

  • 使用URL模板以路徑變量和/或查詢參數的形式傳遞數據。
  • 通過flash屬性發送數據。

第一種方法

	@RequestMapping(value="/register",method=POST)
	public String executeRegister(Spittr spittr,Model model) {\
		spitterRepository.save(spittr);
		model.addAttribute("username",spitter.getUsername());
		// 假設有一個POJO類爲spittr,且有一個變量爲Username,並生成一個getUsername()的方法
		// 5.4中的寫法
		// return "redirect:/home/" + spittr.getUsername()
		return "redirect:/home/{username}";

	}

將username作爲佔位符填充到URL模板中,而不是直接連接字符串,在佔位符中重新轉義編碼,提升了一定的安全性。

例2:

	@RequestMapping(value="/register",method=POST)
	public String executeRegister(Spittr spittr,Model model) {\
		spitterRepository.save(spittr);
		model.addAttribute("username",spitter.getUsername());
		model.addAttribute("userId",spitter.getId());
		// 假設有一個POJO類爲spittr,且有一個變量爲Username,並生成一個getUsername()的方法
		// 5.4中的寫法
		// return "redirect:/home/" + spittr.getUsername()
		return "redirect:/home/{username}";
	}

新增userId,但是在重定向路徑中並沒有userId的佔位符,重定向後它會被加載到尾部,假設ID=47,生成
/home/lihua?userId=47。有沒有對這個url比較熟悉,?後面的內容就是這樣子加上去的。

該方法的侷限性:在於它只可以發送簡單的值,比如字符串或者數字等,沒辦法處理更爲複雜的值。處理複雜的值就是flash方法存在的意義。

第二章方法--flash

如果要發送實際的對象等,Spring會將胯重定向存活的數據放到會話中,提供將數據發送爲flash屬性的功能,按照定義,flash屬性會一直攜帶這些數據直到下一次請求。提供RedirectAttributes設置flash屬性的方法。該模塊不僅包含了Model的所有功能,還提供幾個方法設置flash屬性。

	@RequestMapping(value="/register",method=POST)
	public String executeRegister(Spittr spittr,RedirectAttributes model) {\
		spitterRepository.save(spittr);
		model.addAttribute("username",spitter.getUsername());
		// 假設有一個POJO類爲spittr,且有一個變量爲Username,並生成一個getUsername()的方法
		// 5.4中的寫法
		// return "redirect:/home/" + spittr.getUsername();
		model.addFlashAttribute("spitter",spitter);
		return "redirect:/home/{username}";

	}

"spitter"爲key,後面spitter爲值,而flash會自動進行推斷而不需要設置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章