有 Java 编程相关的问题?

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

java获取纯文本格式的XML

我有一个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) 个答案

  1. # 1 楼答案

    从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);
    }
    
  2. # 2 楼答案

    您已经创建了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;
        } 
     ...
    }
    

    希望有帮助

  3. # 3 楼答案

    我们也遇到了同样的问题,并在生产中使用了这种解决方案。这并不依赖于框架(在我的书中总是一个优点),而且很简单

    只需使用它,而不用将其指定为XML。然后阅读请求行并通过\n连接它们,如果您想在xml中有新行的话。如果没有,请通过""或任何你喜欢的方式加入他们。这假定您正在使用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字符串

  4. # 4 楼答案

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

    我们的设置几乎与自述文件中描述的完全相同。尽管我们将<filter-mapping>下的<url-pattern>限制为只包含有用的端点,但md仍然存在

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

  5. # 5 楼答案

    为了让控制器以普通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。确保检查请求的“内容类型”标题,以了解要处理的类型

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