在 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