知識點
- 處理文件上傳
- 使用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會自動進行推斷而不需要設置。