问题
so currently I'm working on a project where we have product objects which in turn contain "Origin" objects (containing region: String
and country: String
).
What I'm trying to do is a RestController which takes in an optional Origin object and does something with it (e.g. logs it).
This is what I have right now:
@GetMapping("search")
public Page<Wine> getProductByStuff(
@RequestParam(required = false) Origin origin,
/* other attributes */) {
log.info(origin); // it has a proper toString method.
}
There are two problem with this approach. First of all, when I send a request like:
http://[...]/search?origin={"region":"blah","country":"UK"}
or even the html converted string like:
http://[...]/search?origin={%22region%22:%22blah%22%44%22country%22:%22UK%22}
... it says
Invalid character found in the request target [/api/products/search?origin={%22region%22:%22blah%22%44%22country%22:%22DE%22}]. The valid characters are defined in RFC 7230 and RFC 3986.
Afaik the only valid characters Tomcat has that I need are {}. All others I've replaced with the html encoded chars and it still doesn't work.
What I did to prevent this:
@Component
public class TomcatWebServerCustomizer
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
TomcatConnectorCustomizer a = null;
factory.addConnectorCustomizers(connector -> {
connector.setAttribute("relaxedPathChars", "<>[\\]^`{|},\"");
connector.setAttribute("relaxedQueryChars", "<>[\\]^`{|},\"");
});
}
}
(See this, which is, by the way, deprecated (at least connector.setAttribute).)
This produced:
MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type '[censored].backend.model.Origin'.
My questions are:
- (How) is it possible to configure Tomcat/Spring so that they can actually accept json in the url params?
- How would I format it in e.g. Postman so that it would work? Currently I'm just converting special characters by hand in the params tab of Postman.
回答1:
- Here is what you need to do if you want to send it as json query param.
@RestController
public class OriginController {
@GetMapping("/search")
public void getOrigin(@RequestParam(value = "origin", required = false)
Origin origin) {
System.out.println(origin);
}
}
- Register a converter
@Component
public class StringToOriginConverter implements
Converter<String, Origin> {
ObjectMapper objectMapper = new ObjectMapper();
@Override
public Origin convert(String source) {
try {
return objectMapper.readValue(source, Origin.class);
} catch (JsonProcessingException e) {
//You could throw some exception here instead for custom error
return null;
}
}
}
- Sending from
postman
Note
My answer is not debating whether you should use POST
or GET
as it is not what you have asked. It is just providing one option if you want to send some payload as query param
回答2:
As mentioned, don't use JSON as a path parameter.
Directly use path parameters, and convert to Origin
object.
@GetMapping("search")
public Page<Wine> getProductByStuff(
@RequestParam(required = false) String region,
@RequestParam(required = false) String country, /* other attributes */) {
Origin origin = new Origin(region, country);
log.info(origin); // it has a proper toString method.
}
来源:https://stackoverflow.com/questions/63092675/how-to-send-json-with-get-params-via-spring-boot-tomcat