有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何通过Spring Boot/Tomcat发送带有GET参数的json?

所以目前我正在做一个项目,我们有产品对象,这些对象又包含“源”对象(包含region: Stringcountry: String

我想做的是一个RestController,它接收一个可选的原始对象,并对其执行一些操作(例如记录它)

这就是我现在拥有的:

@GetMapping("search")
    public Page<Wine> getProductByStuff(
            @RequestParam(required = false) Origin origin, 
            /* other attributes */) {
    log.info(origin); // it has a proper toString method.
}

这种方法有两个问题。首先,当我发送如下请求时:

http://[...]/search?origin={"region":"blah","country":"UK"}

甚至是html转换的字符串,比如:

http://[...]/search?origin={%22region%22:%22blah%22%44%22country%22:%22UK%22}

。。。上面写着

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.

好吧,Tomcat唯一需要的有效字符是{}。我用html编码的字符替换了所有其他字符,但仍然不起作用

我为防止这种情况所做的:

@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", "<>[\\]^`{|},\"");
        });
    }
}

(请参阅this,顺便说一句,它已被弃用(至少是connector.setAttribute)。)

这产生了:

MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type '[censored].backend.model.Origin'.

我的问题是:

  • (如何)可以配置Tomcat/Spring,以便它们可以在url参数中实际接受json吗
  • 我将如何在例如Postman中设置格式以使其工作?目前,我只是在邮递员的参数选项卡中手动转换特殊字符

共 (2) 个答案

  1. # 1 楼答案

    • 如果希望将其作为json查询参数发送,需要做以下操作
         @RestController
         public class OriginController {
    
          @GetMapping("/search")
          public void getOrigin(@RequestParam(value = "origin", required = false) 
                                Origin origin) {
            System.out.println(origin);
          }
    
         }
    
    • 注册转换器
        @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;
             }
    
           }
        }
    
    • postman发送 enter image description here

    注意

    我的答案不是争论你是否应该使用POSTGET,因为这不是你所要求的。如果您想将一些有效负载作为查询参数发送,那么它只提供了一个选项

  2. # 2 楼答案

    如上所述,不要将JSON用作路径参数

    直接使用路径参数,并转换为Origin对象

    @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.
    }