SpringMVC 教程 - Model,Data Bind

418 阅读2分钟
原文链接: www.codemore.top
Model

注解@ModelAttribute可以用来:

  • 应用在@RequestMapping方法的参数,创建或者访问model中的对象,并且通过WebDataBinder绑定request的参数。
  • 作为@Controller,@ControllerAdvice类的方法级别的注解,在调用@RequestMapping方法前初始化Model
  • 标记一个@RequestMapping的方法返回一个model属性

一个controller可以有多个@ModelAttribute注解修饰的方法。这些方法都会在@RequestMapping方法调用之前调用。@ModelAttribute方法同样可以通过@ControllerAdvice共享。 @ModelAttribute方法的函数签名非常的灵活。除了@ModelAttribute和其他与请求体无关的参数类型外,它和@RequestMapping支持的参数类型一样多。 下面就是一个使用@ModelAttribute方法的例子:

@ModelAttribute
public void populateModel(@RequestParam String number, Model model) {
    model.addAttribute(accountRepository.findAccount(number));
    // add more ...
}

如果只添加一个属性,可以省了model

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

@ModelAttribute同样可以应用在@RequestMapping的方法上,这样方法的返回值就会被认为是一个modle的属性。如果返回值不是String,@ModelAttribute并不是必要的,因为这个是HTML controller的默认行为。@ModelAttribute同样可以定制model属性名:

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

@Controller,@ControllerAdvice类可以有多个@InitBinder用来初始化WebDataBinder实例,它可以用来:

  • 将请求参数(例如,查询或者form数据)绑定到model对象中
  • 将String类型的请求值,例如:请求参数,路径变量,header,cookie和其他类型转换为controller方法参数类型。
  • 渲染HTML的时候,将model对象格式化为String值

@InitBinder方法可以注册controller指定的java.bean.PropertyEditor或者Spring的ConverterFormatter组件。另外,通过MVC配置,可以通过FormattingConversionService注册全局的ConverterFormatter@InitBinder方法和@RequestMapping一样支持多种类型,除了@ModelAttribute。一般用法是声明一个WebDataBinder对象用来注册,返回void值。下面是这种用法:

@Controller
public 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));
    }

    // ...
}

同样的注册Formatter

@Controller
public class FormController {

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

    // ...
}