问题
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