【问题标题】:Spring boot convert request XML to JSONSpring Boot 将请求 XML 转换为 JSON
【发布时间】:2018-08-09 19:37:46
【问题描述】:

我遇到一种情况,我们的一个应用程序即将停用。但是,已经创建了另一个应用程序(在 Spring Boot 中)。问题是,上游系统向我们发送了一个 XML 请求,而新应用程序只使用 JSON。但是,上游系统现在没有足够的带宽在停用的最后期限发生之前更改其代码以与我们的新 JSON 服务保持一致,因此我需要创建一个 XML JSON 包装器。


我的问题:

spring boot 可以通过哪些方式处理这种情况?例如,在 Controller 类中验证首先查看请求是否为 XML,然后将其转换为 JSON 请求,该请求将访问我的新服务。这种情况还有哪些其他选择?


@Validated
@RestController
@RequestMapping(path="/ccc")
public class CustomerCommGatewayInterface {
    @Autowired
    CCCatewayService gatewayService;

    @RequestMapping(method=RequestMethod.POST, value="/comm-history")
    public HistoryResponse getCustomerCommunicationHistory(@Valid 
          @RequestBody HistoryRequest request) {
        return gatewayService.getHistory(request);
    }
}

POJO 类

public class ServiceRequest {

    @NotNull(message = "{error.application.id.invalid}")
    @NotBlank(message = "{error.application.id.invalid}")
    private String applicationId;

    @NotNull(message = "{error.requestTypes.null}")
    @RequestTypes(acceptedValues={"Stuff", "More stuff"})
    private List<String> requestTypes;

    @Pattern(regexp = "(Retrieve)|(Contacts)|(Documents)$", message = "{error.subService.invalid}")
    private String subService;

    @Pattern(regexp = "(\\d{1,10})", message = "{error.customer.id.invalid}")
    private String customerId;

    @Pattern(regexp = "(\\d{5})", message = "{error.account.number.invalid}")
    private String accountNumber;

    @Pattern(regexp = "(\\d{10})", message = "{error.mtn.invalid}")
    private String number;

    @EmailId()
    private String emailAddress;

    private String category;
    private String categoryKeyword;
    private String preOrderNumber;
    private String requestCategory;
    private String channelType;
    private String ecpdId;
    private String subscriberId;
    private String returnCountLimit;

    @Pattern(regexp = "((0?[1-9]|1[012])/(0?[1-9]|[12][0-9]|3[01])/(19|20)\\d\\d)|(^()$)", message = "{error.date.invalid}")
    private String startDate;

    @Pattern(regexp = "((0?[1-9]|1[012])/(0?[1-9]|[12][0-9]|3[01])/(19|20)\\d\\d)|(^()$)", message = "{error.date.invalid}")
    private String endDate;
    private String includeDismissedCards;

    ...

    //getters and setters
}

【问题讨论】:

  • 应该像提供一个接受 xml 而不是 application/json 的相同端点一样简单
  • @DaisyDay 是的,但我想知道是否有另一种方法而不是创建另一个子服务。
  • 据我所知,您需要 2 个不同的端点。如果可能的话,您需要一个可以接受任何东西(安全风险)的端点,并且您需要一些复杂的类转换来确定发送给您的内容。我认为这会是一团糟。

标签: java spring-boot


【解决方案1】:

您不需要新的端点定义。单个端点可以根据Content-Type请求头读取多种请求体类型,并根据Accept请求头写入不同响应体类型。

Spring 将使用已注册的转换器 bean 转换请求正文,例如MappingJackson2HttpMessageConverter。转换器 bean 基于 Content-Type 请求标头选择。如果您将端点限制为仅支持 JSON,则转换不会是动态的,例如通过使用@RequestMapping(consumes = "application/json") 注释@Controller

如果您配置支持 XML 的其他转换器,例如org.springframework.http.converter.xml.MarshallingHttpMessageConverter 请求正文将作为 XML 处理,前提是 Marshaller bean 配置为将 XML 映射到正确的 POJO 类型。根据类 javadoc:

默认情况下,此转换器支持 text/xml 和 application/xml。这可以通过设置 supportedMediaTypes 属性来覆盖。

【讨论】:

  • 如果您这样做,请注意 XXE 安全风险并将其关闭!
  • @DaisyDay 你混淆了特定的解析器功能(XEE 可以用XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES=false 阻止)和用于处理请求的 Spring 胶水代码。见stackoverflow.com/a/28418763/1602555
  • 谢谢,我已经尝试过了,但我得到了 org.springframework.web.HttpMediaTypeNotSupportedException。我已经更新了我的问题以包括我的控制器和 pojo 类
猜你喜欢
  • 2019-01-20
  • 2018-12-12
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 2022-11-09
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
相关资源
最近更新 更多