为地图 and/or 嵌套对象自定义 Spring @RequestParam 反序列化
Customize Spring @RequestParam Deserialization for Maps and/or Nested Objects
@RestController
class MyController {
@RequestMapping(...)
public void test(Container container) { ... }
}
Spring 默认使用 Dot-Notation 反序列化嵌套的 @RequestParam:
class Container {
A a;
}
class A {
String val;
}
适用于:
http://.../myController?a.val=foo
但对于地图,它使用方括号表示法:
class Container {
Map<String, String> a;
}
适用于:
http://.../myController?a[val]=foo
当使用 JavaScript 时,HashMap 和嵌套对象之间当然没有区别,因此所有内容都将使用点 或 方括号进行序列化。
问题:
我如何/在哪里可以告诉 Spring(或 Spring Boot,如果这样更容易)为 both 使用圆点表示法(或方括号) , 嵌套对象 and Maps?
或者为什么 Spring 会在这些类型之间产生差异?
Spring 由于其自定义 DataBinder
子类 RelaxedDataBinder,Boot 支持使用点分隔路径来绑定映射。好消息是,它也是一个 DataBinder
,在 Spring MVC 中用于执行请求参数绑定。坏消息是插入您自己的活页夹并不简单,它需要是 WebDataBinder
。您可以通过声明您自己的名为 requestMappingHandlerAdapter
的 RequestMappingHandlerAdapter
bean 来插入一个。例如:
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdpter() {
return new RequestMappingHandlerAdapter() {
@Override
protected InitBinderDataBinderFactory createDataBinderFactory(
List<InvocableHandlerMethod> binderMethods)
throws Exception {
return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer()) {
@Override
protected ServletRequestDataBinder createBinderInstance(
final Object target, String objectName,
NativeWebRequest request) {
return new ServletRequestDataBinder(target) {
private RelaxedDataBinder relaxedBinder = new RelaxedDataBinder(target);
@Override
protected void doBind(MutablePropertyValues mpvs) {
this.relaxedBinder.bind(mpvs);
}
};
}
};
}
};
}
您可能希望重构它以避免使用多重嵌套匿名内部 类,但它有望说明一般方法。
@InitBinder
private void initBinder(WebDataBinder binder, ServletRequest request) {
new RelaxedDataBinder(binder.getTarget()).bind(new ServletRequestParameterPropertyValues(request));
}
这就是我逃脱惩罚的方式;控制器中委托给 RelaxedDataBinder
.
的方法
@RestController
class MyController {
@RequestMapping(...)
public void test(Container container) { ... }
}
Spring 默认使用 Dot-Notation 反序列化嵌套的 @RequestParam:
class Container {
A a;
}
class A {
String val;
}
适用于:
http://.../myController?a.val=foo
但对于地图,它使用方括号表示法:
class Container {
Map<String, String> a;
}
适用于:
http://.../myController?a[val]=foo
当使用 JavaScript 时,HashMap 和嵌套对象之间当然没有区别,因此所有内容都将使用点 或 方括号进行序列化。
问题:
我如何/在哪里可以告诉 Spring(或 Spring Boot,如果这样更容易)为 both 使用圆点表示法(或方括号) , 嵌套对象 and Maps?
或者为什么 Spring 会在这些类型之间产生差异?
Spring 由于其自定义 DataBinder
子类 RelaxedDataBinder,Boot 支持使用点分隔路径来绑定映射。好消息是,它也是一个 DataBinder
,在 Spring MVC 中用于执行请求参数绑定。坏消息是插入您自己的活页夹并不简单,它需要是 WebDataBinder
。您可以通过声明您自己的名为 requestMappingHandlerAdapter
的 RequestMappingHandlerAdapter
bean 来插入一个。例如:
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdpter() {
return new RequestMappingHandlerAdapter() {
@Override
protected InitBinderDataBinderFactory createDataBinderFactory(
List<InvocableHandlerMethod> binderMethods)
throws Exception {
return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer()) {
@Override
protected ServletRequestDataBinder createBinderInstance(
final Object target, String objectName,
NativeWebRequest request) {
return new ServletRequestDataBinder(target) {
private RelaxedDataBinder relaxedBinder = new RelaxedDataBinder(target);
@Override
protected void doBind(MutablePropertyValues mpvs) {
this.relaxedBinder.bind(mpvs);
}
};
}
};
}
};
}
您可能希望重构它以避免使用多重嵌套匿名内部 类,但它有望说明一般方法。
@InitBinder
private void initBinder(WebDataBinder binder, ServletRequest request) {
new RelaxedDataBinder(binder.getTarget()).bind(new ServletRequestParameterPropertyValues(request));
}
这就是我逃脱惩罚的方式;控制器中委托给 RelaxedDataBinder
.