Customize mapping request parameters and fields inside the DTO ?

无人久伴 提交于 2019-12-10 01:52:33

问题


I have the following class:

public class MyDTO { 

       private String kiosk;
       ...
}

and following url:

http://localhost:1234/mvc/controllerUrl?kiosk=false

and following controller method:

@RequestMapping(method = RequestMethod.GET, produces = APPLICATION_JSON)
@ResponseBody
public ResponseEntity<List<?>> getRequestSupportKludge(final MyDTO myDTO, BindingResult bindingResult) {
    ...
}

Now it is working nice and boolean field resolves properly.

Now url parameter has changed like this:

http://localhost:1234/mvc/controllerUrl?new_kiosk=false

I don't want to change parameter name inside the DTO. Is there way to say spring to understand that new_kiosk request parameter value should be put into kiosk field ?


回答1:


Apart from setting an additional setter you can hande the case by making a custom argument resolver. There's a few ways you can go about it, but there's already a well discussed post. If I were you I would focus on the jkee's answer. Follow it step by step, and than all you should do is annotate your DTO with something like,

public class MyDTO { 

       @ParamName("new_kiosk")
       private String kiosk;
       ...
}

Note that even if you can't change MyDTO class, you can still follow a custom resolver route. In this post I've answered how you can write a parameter type annotation. Combining the two post you can easily come up with an annotation e.g. @ParamMapper that would define the mapping from request to properties. Think of something like

 getRequestSupportKludge(@ParamMapper("new_kiosk;kiosk") MyDTO myDTO, BindingResult bindingResult)



回答2:


There different ways to do that.

If you can change MyDTO class the simplest way is to add a setter as suggested by M.Deinum :

public class MyDTO { 

       private String kiosk;
       ...
       public void setNew_kiosk(String kiosk) {
           this.kiosk = kiosk;
       }
}

That way, you can process http://localhost:1234/mvc/controllerUrl?kiosk=false as well as http://localhost:1234/mvc/controllerUrl?new_kiosk=false

If you are not allowed to do that (because the DTO is part of a library you are not allowed to change or ...), you can use a filter mapped to /mvc/controllerUrl, that would wrap the request with a custom HttpServlerRequestWrapper that will override following methods :

String  getParameter(String name)
Map<String,String[]>    getParameterMap()
Enumeration<String>     getParameterNames()
String[]    getParameterValues(String name)

calling the underlying request methods and processing the special parameter name. Example :

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;
}

This will be much harder to write and test, so only go that way if you cannot modify MyDTO class.

You could also try to use a custom implementation of WebBindingInitializer. From Spring Framework Reference Manual :

To externalize data binding initialization, you can provide a custom implementation of the WebBindingInitializer interface, which you then enable by supplying a custom bean configuration for an AnnotationMethodHandlerAdapter, thus overriding the default configuration.

Beware : the recommended usage of that is to register custom editors for a whole application - not your use case. And Spring Framework is oftern described as easy to extend but not to override. Caveat emptor ...

Summary : try to use method 1, if you cannot, then use method2, and only try method3 if you have other reasons to use a custom WebBindingInitializer



来源:https://stackoverflow.com/questions/30053709/customize-mapping-request-parameters-and-fields-inside-the-dto

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!