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