此类代码不多但也不容小觑,它是对ServletRequestDataBinder的一个增强,它用于把URI template variables参数添加进来用于绑定。它会去从request的HandlerMapping.class.getName() + ".uriTemplateVariables";这个属性里查找到值出来用于绑定~~~
比如我们熟悉的@PathVariable它就和这相关:它负责把参数从url模版中解析出来,然后放在attr上,最后交给ExtendedServletRequestDataBinder进行绑定~~~
介于此:我觉得它还有一个作用,就是定制我们全局属性变量用于绑定~
向此属性放置值的地方是:AbstractUrlHandlerMapping.lookupHandler() --> chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables)); --> preHandle()方法 -> exposeUriTemplateVariables(this.uriTemplateVariables, request); -> request.setAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
// @since 3.1 public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder { ... // 沿用父类构造 //本类的唯一方法 @Override @SuppressWarnings("unchecked") protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) { // 它的值是:HandlerMapping.class.getName() + ".uriTemplateVariables"; String attr = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; // 注意:此处是attr,而不是parameter Map<String, String> uriVars = (Map<String, String>) request.getAttribute(attr); if (uriVars != null) { uriVars.forEach((name, value) -> { // 若已经存在确切的key了,不会覆盖~~~~ if (mpvs.contains(name)) { if (logger.isWarnEnabled()) { logger.warn("Skipping URI variable '" + name + "' because request contains bind value with same name."); } } else { mpvs.addPropertyValue(name, value); } }); } } }可见,通过它我们亦可以很方便的做到在每个ServletRequest提供一份共用的模版属性们,供以绑定~
此类基本都沿用父类的功能,比较简单,此处就不写Demo了(Demo请参照父类)~
说明:ServletRequestDataBinder一般不会直接使用,而是使用更强的子类ExtendedServletRequestDataBinder
WebExchangeDataBinder它是Spring5.0后提供的,对Reactive编程的Mono数据绑定提供支持,因此暂略~
data binding from URL query params or form data in the request data to Java objects MapDataBinder它位于org.springframework.data.web是和Spring-Data相关,专门用于处理target是Map<String, Object>类型的目标对象的绑定,它并非一个public类~
它用的属性访问器是MapPropertyAccessor:一个继承自AbstractPropertyAccessor的私有静态内部类~(也支持到了SpEL哦)
WebRequestDataBinder它是用于处理Spring自己定义的org.springframework.web.context.request.WebRequest的,旨在处理和容器无关的web请求数据绑定,有机会详述到这块的时候,再详细说~
如何注册自己的PropertyEditor来实现自定义类型数据绑定?通过前面的分析我们知道了,数据绑定这一块最终会依托于PropertyEditor来实现具体属性值的转换(毕竟request传进来的都是字符串嘛~)
一般来说,像String, int, long会自动绑定到参数都是能够自动完成绑定的,因为前面有说,默认情况下Spring是给我们注册了N多个解析器的:
public class PropertyEditorRegistrySupport implements PropertyEditorRegistry { @Nullable private Map<Class<?>, PropertyEditor> defaultEditors; private void createDefaultEditors() { this.defaultEditors = new HashMap<>(64); // Simple editors, without parameterization capabilities. // The JDK does not contain a default editor for any of these target types. this.defaultEditors.put(Charset.class, new CharsetEditor()); this.defaultEditors.put(Class.class, new ClassEditor()); ... // Default instances of collection editors. // Can be overridden by registering custom instances of those as custom editors. this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class)); this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class)); this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class)); this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class)); this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class)); ... // 这里就部全部枚举出来了 } }