以纯文本格式获取XML

时间:2018-11-23 17:14:00

标签: java spring rest spring-restcontroller spring-rest

我有Spring Rest API的这个端点:

@PostMapping(value = "/v1/", consumes = { MediaType.APPLICATION_XML_VALUE,
            MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_XML_VALUE,
                    MediaType.APPLICATION_JSON_VALUE })
    public PaymentResponse handleMessage(@RequestBody PaymentTransaction transaction, HttpServletRequest request) throws Exception {

    // get here plain XML  

}

XML模型。

@XmlRootElement(name = "payment_transaction")
@XmlAccessorType(XmlAccessType.FIELD)
public class PaymentTransaction {
    public enum Response {
        failed_response, successful_response
    }

    @XmlElement(name = "transaction_type")
    public String transactionType;
    .........
}

如何获取纯XML文本中的XML请求?

我也尝试过使用Spring拦截器: 我尝试了这段代码:

@SpringBootApplication
@EntityScan("org.plugin.entity")
public class Application extends SpringBootServletInitializer implements WebMvcConfigurer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    ........

    @Bean
    public RestTemplate rsestTemplate() {
        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
        RestTemplate restTemplate = new RestTemplate(
                new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
        restTemplate.setInterceptors(interceptors);
        return restTemplate;
    } 
}

记录组件:

@Component
public class RestTemplateHeaderModifierInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
            throws IOException {

        StringBuilder sb = new StringBuilder();
        sb.append("[ ");
        for (byte b : body) {
            sb.append(String.format("0x%02X ", b));
        }
        sb.append("]");

        System.out.println("!!!!!!!!!!!!!!!");
        System.out.println(sb.toString());      

        ClientHttpResponse response = execution.execute(request, body);

        InputStream inputStream = response.getBody();

        String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

        System.out.println("!!!!!!!!!!!!!!!");
        System.out.println(result);

        return response;
    }
}

但是没有任何内容打印到控制台中。知道我错了吗?此组件可能未注册?

5 个答案:

答案 0 :(得分:3)

除非像我想念的那样,否则要像下面这样从HttpServletRequest获取它不容易。我认为不需要使用拦截器等。

@PostMapping(value = "/v1/", consumes = { MediaType.APPLICATION_XML_VALUE,
            MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_XML_VALUE,
                    MediaType.APPLICATION_JSON_VALUE })
    public PaymentResponse handleMessage(HttpServletRequest request) throws Exception {

    String str, wholeXML = "";
    try {
        BufferedReader br = request.getReader();
        while ((str = br.readLine()) != null) {
            wholeXML += str;
        }
    System.out.println(wholeXML);
    //Here goes comment question, to convert it into PaymentTransaction
   JAXBContext jaxbContext = JAXBContext.newInstance(PaymentTransaction.class);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

    StringReader reader = new StringReader(wholeXML);
    PaymentTransaction paymentTransaction = (PaymentTransaction) unmarshaller.unmarshal(reader);
}

答案 1 :(得分:0)

我们遇到了同样的问题,并在生产中使用了该解决方案。这与框架无关(在我的书中总是有好处)且简单。

仅使用它而不将其指定为XML。然后,如果您想在xml中添加新行,请阅读请求行并通过\n将其加入。如果没有,请通过""或其他任何方式加入他们。假设您正在使用javax.servlet.http.HttpServletRequest

示例:

@PostMapping(value = "/v1")
    public PaymentResponse handleMessage(HttpServletRequest request) throws Exception {

    final InputStream xml = request.getInputStream();
    final String xmlString = new BufferedReader(new InputStreamReader(xml))
          .lines()
          .collect(Collectors.joining("\n"));
   // do whatever you please with it

}

并且您有一个简单的xml字符串。

答案 2 :(得分:0)

为使控制器以纯XML字符串的形式接收请求正文,只需将@RequestBody参数类型更改为String:

@PostMapping(value = "/v1/", consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
public PaymentResponse handleMessage(@RequestBody String xmlOrJson, HttpServletRequest request) throws Exception {
    ...

使用上述映射,如果客户端已提交xml,您将看到原始XML。否则,如果客户端已提交json,您将看到原始JSON。确保检查请求的“ Content-Type”标头以了解您要处理的类型。

请参见https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestbody

答案 3 :(得分:0)

我们已经在生产中使用spring-mvc-logger已有一段时间了。它被编写为Servlet过滤器,因此可以作为独立包装添加到MVC端点。

尽管我们将<url-pattern>下的<filter-mapping>限制为有用的端点,但设置几乎完全与自述文件中的readme.md所述相同。

即使不完全是您想要的,这里的代码库还是一个不错的小例子。特别注意过滤器中需要的请求/响应包装。 (这是为了避免IllegalStateException: getReader(), getInputStream() already called被两次调用时发生的getReader()

答案 4 :(得分:0)

您已创建List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();,但未向其中添加RestTemplateHeaderModifierInterceptor对象。

您可以在Application中以相同的方式自动接线,如下所示:

@Autowired 
ClientHttpRequestInterceptor clientHttpRequestInterceptor;

interceptors.add(clientHttpRequestInterceptor);

代码如下:

class Application {
...
@Autowired 
ClientHttpRequestInterceptor clientHttpRequestInterceptor;
@Bean
    public RestTemplate rsestTemplate() {
        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
        RestTemplate restTemplate = new RestTemplate(
                new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
interceptors.add(clientHttpRequestInterceptor);
        restTemplate.setInterceptors(interceptors);
        return restTemplate;
    } 
 ...
}

希望有帮助