从原理层面掌握@InitBinder的使用【享学Spring MVC】 (3)

1、StringTrimmerEditor

public class StringTrimmerEditor extends PropertyEditorSupport { // 将属性对象用一个字符串表示,以便外部的属性编辑器能以可视化的方式显示。缺省返回null,表示该属性不能以字符串表示 //@Override //public String getAsText() { // Object value = getValue(); // return (value != null ? value.toString() : null); //} // 用一个字符串去更新属性的内部值,这个字符串一般从外部属性编辑器传入 // 处理请求的入参:test就是你传进来的值(并不是super.getValue()哦~) @Override public void setAsText(String text) throws IllegalArgumentException { text = text == null ? text : text.trim(); setValue(text); } }

说明:Spring内置有org.springframework.beans.propertyeditors.StringTrimmerEditor,默认情况下它并没有装配进来,若你有需要可以直接使用它的(此处为了演示,我就用自己的)。Spring内置注册了哪些?参照PropertyEditorRegistrySupport#createDefaultEditors方法
Spring的属性编辑器和传统的用于IDE开发时的属性编辑器不同,它们没有UI界面,仅负责将配置文件中的文本配置值转换为Bean属性的对应值,所以Spring的属性编辑器并非传统意义上的JavaBean属性编辑器

2、CustomDateEditor
关于这个属性编辑器,你也可以像我一样自己实现。本文就直接使用Spring提供了的,参见:org.springframework.beans.propertyeditors.CustomDateEditor

// @since 28.04.2003 // @see java.util.Date public class CustomDateEditor extends PropertyEditorSupport { ... @Override public void setAsText(@Nullable String text) throws IllegalArgumentException { ... setValue(this.dateFormat.parse(text)); ... } ... @Override public String getAsText() { Date value = (Date) getValue(); return (value != null ? this.dateFormat.format(value) : ""); } }

定义好后,如何使用呢?有两种方式:

API方式WebBindingInitializer ,关于它的使用,请参阅这里,本文略。
1. 重写initBinder注册的属性编辑器是全局的属性编辑器,对所有的Controller都有效(全局的)

@InitBinder注解方式

在Controller本类上使用@InitBinder,形如这样:

@Controller @RequestMapping public class HelloController { @InitBinder public void initBinder(WebDataBinder binder) { //binder.setDisallowedFields("name"); // 不绑定name属性 binder.registerCustomEditor(String.class, new StringTrimmerEditor()); // 此处使用Spring内置的CustomDateEditor DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); } @ResponseBody @GetMapping("/test/initbinder") public String testInitBinder(String param, Date date) { return param + ":" + date; } }

请求:/test/initbinder?param= ds&date=2019-12-12。结果为:ds:Thu Dec 12 00: 00: 00 CST 2019,符合预期。

注意,若date为null返回值为ds: null(因为我设置了允许为null)
但若你不是yyyy-MM-dd格式,那就抛错喽(格式化异常)

本例的@InitBinder方法只对当前Controller生效。要想全局生效,可以使用@ControllerAdvice/WebBindingInitializer
通过@ControllerAdvice可以将对于控制器的全局配置放置在同一个位置,注解了@ControllerAdvice的类的方法可以使用@ExceptionHandler,@InitBinder,@ModelAttribute等注解到方法上,这对所有注解了@RequestMapping的控制器内的方法有效(关于全局的方式本文略,建议各位自己实践~)。

@InitBinder的value属性的作用

获取你可能还不知道,它还有个value属性呢,并且还是数组

public @interface InitBinder { // 用于限定次注解标注的方法作用于哪个模型key上 String[] value() default {}; }

说人话:若指定了value值,那么只有方法参数名(或者模型名)匹配上了此注解方法才会执行(若不指定,都执行)。

@Controller @RequestMapping public class HelloController { @InitBinder({"param", "user"}) public void initBinder(WebDataBinder binder, HttpServletRequest request) { System.out.println("当前key:" + binder.getObjectName()); } @ResponseBody @GetMapping("/test/initbinder") public String testInitBinder(String param, String date, @ModelAttribute("user") User user, @ModelAttribute("person") Person person) { return param + ":" + date; } }

请求:/test/initbinder?param=fsx&date=2019&user.name=demoUser,控制台打印:

当前key:param 当前key:user

从打印结果中很清楚的看出了value属性的作用~

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjxyj.html