Spring 5.2.2 WebFlux 之 註解控制器(Model)

一、Modeljava

    你能夠使用@ModelAttribute註解:react

  • @RequestMapping方法中的方法參數上建立或訪問模型中的對象,並經過WebDataBinder將其綁定到請求。typescript

  • 做爲@Controller@ControllerAdvice類中的方法級註解,有助於在調用任何@RequestMapping方法以前初始化模型。微信

  • @RequestMapping方法返回值標記爲 model attributecookie

    

    討論@ModelAttribute方法,或前面列表中的第二項(上一篇Spring 5.2.2 WebFlux 之帶註解的控制器(方法參數、返回值等詳細內容))。一個控制器能夠有任意數量的@ModelAttribute方法。全部這些方法都在同一個控制器中的@RequestMapping方法以前調用。@ModelAttribute方法也能夠經過@ControllerAdvice在控制器之間共享。app

    @ModelAttribute方法具備靈活的方法簽名。它們支持許多與@RequestMapping方法相同的參數(除了@ModelAttribute自己和任何與請求正文相關的參數)。框架

如下示例使用@ModelAttribute方法:異步

@ModelAttributepublic void populateModel(@RequestParam String number, Model model) { model.addAttribute(accountRepository.findAccount(number));    // 更多 ...}

如下示例僅添加一個屬性:性能

@ModelAttributepublic Account addAccount(@RequestParam String number) { return accountRepository.findAccount(number);}

   若是沒有明顯指定名稱,則根據類型選擇默認名稱。始終能夠經過使用重載的addAttribute 方法或經過@ModelAttribute上的name屬性(用於返回值)來指定顯式名稱。ui

   Spring WebFluxSpring MVC不一樣,它在模型中明確支持reactive 類型(例如Mono<Account>io.reactivex.Single<Account>)。若是不使用封裝聲明@ModelAttribute參數,則能夠透明地將此類異步模型屬性解析(並更新模型)爲其在@RequestMapping調用時的實際值,以下例所示:

@ModelAttributepublic void addAccount(@RequestParam String number) { Mono<Account> accountMono = accountRepository.findAccount(number); model.addAttribute("account", accountMono);}
@PostMapping("/accounts")public String handle(@ModelAttribute Account account, BindingResult errors) { // ...}

     此外,任何具備reactive 類型封裝的模型屬性都會在視圖呈現以前解析爲其實際值(以及更新的模型)。

     你還能夠將@ModelAttribute用做@RequestMapping方法的方法級註解,在這種狀況下,@RequestMapping方法的返回值將解釋爲模型屬性。這一般不是必需的,由於這是HTML控制器中的默認行爲,除非返回值是一個字符串,不然會被解釋爲視圖名稱。@ModelAttribute還能夠幫助自定義模型屬性名稱,以下例所示:

@GetMapping("/accounts/{id}")@ModelAttribute("myAccount")public Account handle() { // ... return account;}

二、DataBinder

    @Controller@ControllerAdvice類能夠有@InitBinder方法來初始化WebDataBinder的實例。這些反過來又用於:

  • 將請求參數(即表單數據或查詢)綁定到模型對象。

  • 將基於String 的請求值(如請求參數、路徑變量、頭、cookie等)轉換爲控制器方法參數的目標類型。

  • 呈現HTML表單時,將模型對象值格式化爲String 值。

@InitBinder方法能夠註冊特定於控制器的java.bean.PropertyEditor或Spring  Converter Formatter 程序組件。此外,你能夠使用WebFlux Java配置在全局共享的FormattingConversionService中註冊Converter Formatter 程序類型。

       @InitBinder方法支持許多與@RequestMapping方法相同的參數,但@ModelAttribute(command object)參數除外。一般,它們是用WebDataBinder參數聲明的,用於註冊和void返回值。如下示例使用@InitBinder註解:

@Controllerpublic class FormController {
@InitBinder public void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); }
// ...}

或者,當經過共享FormattingConversionService使用基於Formatter程序的設置時,能夠重用相同的方法並註冊特定於控制器的Formatter 程序實例,以下例所示:

@Controllerpublic class FormController {
@InitBinder protected void initBinder(WebDataBinder binder) { binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd")); }
// ...}

三、管理異常

    @Controller@ControllerAdvice類能夠有@ExceptionHandler方法來處理來自控制器方法的異常。如下示例包括這樣一個處理程序方法:

@Controllerpublic class SimpleController {
// ...
@ExceptionHandler public ResponseEntity<String> handle(IOException ex) { // ... }}

    異常能夠與正在傳播的頂級異常(即引起的直接IOException )匹配,也能夠與頂級封裝異常中的直接緣由匹配(例如,IllegalStateException中封裝的IOException )。

     爲了匹配異常類型,最好將目標異常聲明爲方法參數,如前面的示例所示。或者,註解聲明能夠縮小異常類型以匹配。咱們一般建議在參數簽名中儘量具體,並在@ControllerAdvice上聲明主頂級異常映射,並按相應的順序進行優先級排序。

      WebFlux中的@ExceptionHandler方法支持與@RequestMapping方法相同的方法參數和返回值,但與請求正文和@ModelAttribute相關的方法參數除外。

   Spring WebFlux中對@ExceptionHandler方法的支持是由@RequestMapping方法的HandlerAdapter 提供的。

REST API異常

     REST服務的一個常見需求是在響應主體中包含錯誤詳細信息。Spring框架不會自動這樣作,由於響應體中錯誤詳細信息的表示是特定於應用程序的。可是,@RestController能夠使用帶有ResponseEntity返回值的@ExceptionHandler方法來設置響應的狀態和主體。這些方法也能夠在@ControllerAdvice類中聲明以全局應用它們。

   請注意,Spring WebFlux沒有Spring MVC ResponseEntityExceptionHandler,由於WebFlux只引起ResponseStatusException (或其子類),這些不須要轉換爲HTTP狀態代碼。

四、Controller Advice

     一般,@ExceptionHandler@InitBinder@ModelAttribute方法應用於聲明它們的@Controller類(或類層次結構)中。若是你但願這樣的方法更全局地(跨控制器)應用,能夠在一個用@ControllerAdvice@RestControllerAdvice註解的類中聲明它們。

     @ControllerAdvice@Component註解,這意味着能夠經過組件掃描將這些類註冊爲Spring bean@RestControllerAdvice是一個組合註解,它同時使用@ControllerAdvice@ResponseBody進行註解,這實際上意味着@ExceptionHandler方法經過消息轉換(相對於視圖解析或模板呈現)呈現到響應體。

    啓動時,@RequestMapping@ExceptionHandler方法的基礎結構類檢測用@ControllerAdvice註解的Spring bean,而後在運行時應用它們的方法。全局@ExceptionHandler方法(來自@ControllerAdvice)應用於本地方法(來自@Controller)以後。相比之下,全局@ModelAttribute@InitBinder方法應用於本地方法以前。

    默認狀況下,@ControllerAdvice方法應用於每一個請求(即,全部控制器),但能夠經過使用註解上的屬性將其縮小到控制器的子集,以下例所示:

// 以@RestController註解的全部控制器爲目標@ControllerAdvice(annotations = RestController.class)public class ExampleAdvice1 {}
// 針對特定包中的全部控制器@ControllerAdvice("org.example.controllers")public class ExampleAdvice2 {}
// 將全部可分配給特定類的控制器做爲目標@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})public class ExampleAdvice3 {}

     上例中的選擇器是在運行時評估的,若是普遍使用,可能會對性能產生負面影響。

歡迎關注和轉發Spring中文社區(加微信羣,能夠關注後加我微信):
















本文分享自微信公衆號 - Spring中文社區(gh_81d233bb13a4)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索