在 DTO 中自定义映射请求参数和字段?
Customize mapping request parameters and fields inside the DTO ?
我有以下 class:
public class MyDTO {
private String kiosk;
...
}
和以下 url:
http://localhost:1234/mvc/controllerUrl?kiosk=false
和以下控制器方法:
@RequestMapping(method = RequestMethod.GET, produces = APPLICATION_JSON)
@ResponseBody
public ResponseEntity<List<?>> getRequestSupportKludge(final MyDTO myDTO, BindingResult bindingResult) {
...
}
现在它运行良好,布尔字段正确解析。
现在url参数已经改成这样:
http://localhost:1234/mvc/controllerUrl?new_kiosk=false
我不想更改 DTO 中的参数名称。有没有办法说 spring 来理解 new_kiosk
请求参数值应该放在 kiosk
字段中?
除了设置额外的 setter 之外,您还可以通过制作自定义参数解析器来处理这种情况。有几种方法可以解决这个问题,但已经有一个很好的讨论 post。如果我是你,我会专注于 jkee 的回答。一步一步地跟着它,你应该做的就是用类似
的东西注释你的DTO
public class MyDTO {
@ParamName("new_kiosk")
private String kiosk;
...
}
请注意,即使您无法更改 MyDTO
class,您仍然可以遵循自定义解析器路由。在此 post 中,我已经回答了如何编写参数类型注释。结合这两个 post 你可以很容易地想出一个注释,例如@ParamMapper
将定义从请求到属性的映射。想像
getRequestSupportKludge(@ParamMapper("new_kiosk;kiosk") MyDTO myDTO, BindingResult bindingResult)
有不同的方法可以做到这一点。
如果可以更改 MyDTO
class 最简单的方法是按照 M.Deinum 的建议添加 setter :
public class MyDTO {
private String kiosk;
...
public void setNew_kiosk(String kiosk) {
this.kiosk = kiosk;
}
}
这样,您可以处理 http://localhost:1234/mvc/controllerUrl?kiosk=false
以及 http://localhost:1234/mvc/controllerUrl?new_kiosk=false
如果您不被允许这样做(因为 DTO 是库的一部分,您不能更改或...),您可以使用映射到 /mvc/controllerUrl
的过滤器,这将换行具有自定义 HttpServlerRequestWrapper
的请求将覆盖以下方法:
String getParameter(String name)
Map<String,String[]> getParameterMap()
Enumeration<String> getParameterNames()
String[] getParameterValues(String name)
调用底层请求方法并处理特殊参数名称。示例:
String[] getParameterValues(String name) {
String[] values = req.getParameterValues(name); // req is the wrapped request
if ("kiosk".equals(name) && (values == null) { // will accept both names
values = req.getParameterValues("new_kiosk"); // try alternate name
}
return values;
}
这将更难编写和测试,所以只有在您无法修改 MyDTO
class.
时才这样做
您也可以尝试使用 WebBindingInitializer
的自定义实现。来自 Spring Framework Reference Manual :
要外部化数据绑定初始化,您可以提供 WebBindingInitializer
接口的自定义实现,然后通过为 AnnotationMethodHandlerAdapter
提供自定义 bean 配置来启用它,因此覆盖默认配置。
注意:建议的用法是为整个应用程序注册自定义编辑器 - 而不是您的用例。 Spring 框架通常被描述为 易于扩展但不易覆盖 。买者自负...
总结:尝试使用方法1,如果不能,则使用方法2,只有在有其他原因使用自定义时才尝试方法3 WebBindingInitializer
我有以下 class:
public class MyDTO {
private String kiosk;
...
}
和以下 url:
http://localhost:1234/mvc/controllerUrl?kiosk=false
和以下控制器方法:
@RequestMapping(method = RequestMethod.GET, produces = APPLICATION_JSON)
@ResponseBody
public ResponseEntity<List<?>> getRequestSupportKludge(final MyDTO myDTO, BindingResult bindingResult) {
...
}
现在它运行良好,布尔字段正确解析。
现在url参数已经改成这样:
http://localhost:1234/mvc/controllerUrl?new_kiosk=false
我不想更改 DTO 中的参数名称。有没有办法说 spring 来理解 new_kiosk
请求参数值应该放在 kiosk
字段中?
除了设置额外的 setter 之外,您还可以通过制作自定义参数解析器来处理这种情况。有几种方法可以解决这个问题,但已经有一个很好的讨论 post。如果我是你,我会专注于 jkee 的回答。一步一步地跟着它,你应该做的就是用类似
的东西注释你的DTOpublic class MyDTO {
@ParamName("new_kiosk")
private String kiosk;
...
}
请注意,即使您无法更改 MyDTO
class,您仍然可以遵循自定义解析器路由。在此 post 中,我已经回答了如何编写参数类型注释。结合这两个 post 你可以很容易地想出一个注释,例如@ParamMapper
将定义从请求到属性的映射。想像
getRequestSupportKludge(@ParamMapper("new_kiosk;kiosk") MyDTO myDTO, BindingResult bindingResult)
有不同的方法可以做到这一点。
如果可以更改 MyDTO
class 最简单的方法是按照 M.Deinum 的建议添加 setter :
public class MyDTO {
private String kiosk;
...
public void setNew_kiosk(String kiosk) {
this.kiosk = kiosk;
}
}
这样,您可以处理 http://localhost:1234/mvc/controllerUrl?kiosk=false
以及 http://localhost:1234/mvc/controllerUrl?new_kiosk=false
如果您不被允许这样做(因为 DTO 是库的一部分,您不能更改或...),您可以使用映射到 /mvc/controllerUrl
的过滤器,这将换行具有自定义 HttpServlerRequestWrapper
的请求将覆盖以下方法:
String getParameter(String name)
Map<String,String[]> getParameterMap()
Enumeration<String> getParameterNames()
String[] getParameterValues(String name)
调用底层请求方法并处理特殊参数名称。示例:
String[] getParameterValues(String name) {
String[] values = req.getParameterValues(name); // req is the wrapped request
if ("kiosk".equals(name) && (values == null) { // will accept both names
values = req.getParameterValues("new_kiosk"); // try alternate name
}
return values;
}
这将更难编写和测试,所以只有在您无法修改 MyDTO
class.
您也可以尝试使用 WebBindingInitializer
的自定义实现。来自 Spring Framework Reference Manual :
要外部化数据绑定初始化,您可以提供 WebBindingInitializer
接口的自定义实现,然后通过为 AnnotationMethodHandlerAdapter
提供自定义 bean 配置来启用它,因此覆盖默认配置。
注意:建议的用法是为整个应用程序注册自定义编辑器 - 而不是您的用例。 Spring 框架通常被描述为 易于扩展但不易覆盖 。买者自负...
总结:尝试使用方法1,如果不能,则使用方法2,只有在有其他原因使用自定义时才尝试方法3 WebBindingInitializer