gpt4 book ai didi

spring - 使用 RestController 接受字符串和 XML 数据

转载 作者:行者123 更新时间:2023-12-02 20:17:24 25 4
gpt4 key购买 nike

我想创建 REST 服务器,它接受 XML 请求和纯文本到不同的 Controller 中。我尝试实现这个:

@SpringBootApplication
public class Application extends SpringBootServletInitializer implements WebMvcConfigurer {

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

private BasicAuthenticationInterceptor basicAuthenticationInterceptor;

@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.removeIf(converter -> converter instanceof MappingJackson2XmlHttpMessageConverter);
converters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter);
converters.add(new MappingJackson2XmlHttpMessageConverter(
((XmlMapper) createObjectMapper(Jackson2ObjectMapperBuilder.xml()))
.enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION)));
converters.add(new MappingJackson2HttpMessageConverter(createObjectMapper(Jackson2ObjectMapperBuilder.json())));
}

private ObjectMapper createObjectMapper(Jackson2ObjectMapperBuilder builder) {
builder.indentOutput(true);
builder.modules(new JaxbAnnotationModule());
builder.serializationInclusion(JsonInclude.Include.NON_NULL);
builder.defaultUseWrapper(false);
return builder.build();
}

@Autowired
public void setBasicAuthenticationInterceptor(BasicAuthenticationInterceptor basicAuthenticationInterceptor) {
this.basicAuthenticationInterceptor = basicAuthenticationInterceptor;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(basicAuthenticationInterceptor);
}
}

检查 XML 格式是否正确:

@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
PaymentTransaction response;
if (ex.getMessage().contains("Required request body")) {
response = new PaymentTransaction(PaymentTransaction.Response.failed_response, 350,
"Invalid XML message: No XML data received", "XML request parsing failed!");
} else {
response = new PaymentTransaction(PaymentTransaction.Response.failed_response, 351,
"Invalid XML message format", null);
}
return ResponseEntity.badRequest().body(response);
}
}

Controller 类:

@RestController()
public class HomeController {

@Autowired
public HomeController(Map<String, MessageProcessor> processors, Map<String, ReconcileProcessor> reconcileProcessors,
@Qualifier("defaultProcessor") MessageProcessor defaultProcessor,
AuthenticationService authenticationService, ClientRepository repository,
@Value("${request.limit}") int requestLimit) {
// Here I receive XML
}

@GetMapping(value = "/v1/*")
public String message() {
return "REST server";
}

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

@PostMapping(value = "/v1/notification")
public ResponseEntity<String> handleNotifications(@RequestBody Map<String, String> keyValuePairs) {
// Here I receive key and value in request body
}

@PostMapping(value = "/v1/summary/by_date/{token}", consumes = { MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE })
public PaymentResponses handleReconcile(@PathVariable("token") String token, @RequestBody Reconcile reconcile,
HttpServletRequest request) throws Exception {
// Here I receive XML
}

@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public static class UnauthorizedException extends RuntimeException {
UnauthorizedException(String message) {
super(message);
}
}
}

正如您所看到的,在某些方法中我收到 XML,而在其他方法中我收到 key=value&.....

形式的字符串

如何配置 Spring 以接受这两种类型?我还应该将 Rest Controller 拆分为不同的文件吗?

编辑:

示例 XML 请求:

<?xml version="1.0" encoding="UTF-8"?>
<payment_transaction>
<transaction_type>authorize</transaction_type>
<transaction_id>2aeke4geaclv7ml80</transaction_id>
<amount>1000</amount>
<currency>USD</currency>
<card_number>22</card_number>
<shipping_address>
<first_name>Name</first_name>
</shipping_address>
</payment_transaction>

示例 XML 响应:

<?xml version="1.0" encoding="UTF-8"?>
<payment_response>
<transaction_type>authorize</transaction_type>
<status>approved</status>
<unique_id>5f7edd36689f03324f3ef531beacfaae</unique_id>
<transaction_id>asdsdlddea4sdaasdsdsa4dadasda</transaction_id>
<code>500</code>
<amount>101</amount>
<currency>EUR</currency>
</payment_response>

示例通知请求:

uniqueid=23434&type=sale&status=33

示例通知响应:它应该仅返回 HTTP 状态 OK。

我使用:

    <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath />
</parent>

Java版本:“10.0.2”2018-07-17

关于我使用的 XML 生成:

@XmlRootElement(name = "payment_transaction")
public class PaymentTransaction {

public enum Response {
failed_response, successful_response
}

@XmlElement(name = "transaction_type")
public String transactionType;
@XmlElement(name = "transaction_id")
public String transactionId;
@XmlElement(name = "usage")

POM 配置:https://pastebin.com/zXqYhDH3

最佳答案

对于 Spring boot 2.0.4-RELEASE,看来你不需要做太多事情。

我做了这样的配置:

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//MyRequestBodyHttpMessageConverter converter = new MyRequestBodyHttpMessageConverter();
FormHttpMessageConverter converter = new FormHttpMessageConverter();
//MediaType utf8FormEncoded = new MediaType("application","x-www-form-urlencoded", Charset.forName("UTF-8"));
//MediaType mediaType = MediaType.APPLICATION_FORM_URLENCODED; maybe UTF-8 is not needed
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_FORM_URLENCODED));
//converter.setSupportedMediaTypes(Arrays.asList(utf8FormEncoded));
converters.add(converter);
MappingJackson2HttpMessageConverter conv1 = new MappingJackson2HttpMessageConverter();
conv1.getObjectMapper().registerModule(new JaxbAnnotationModule());
converters.add(conv1);

MappingJackson2XmlHttpMessageConverter conv = new MappingJackson2XmlHttpMessageConverter();
// required by jaxb annotations
conv.getObjectMapper().registerModule(new JaxbAnnotationModule());
converters.add(conv);
}
}

我用过你的 DTO:

@XmlRootElement(name = "payment_transaction")
public class PaymentTransaction {

@XmlElement(name = "transaction_type")
public String transactionType;
@XmlElement(name = "transaction_id")
public String transactionId;

public String getTransactionType() {
return transactionType;
}
public void setTransactionType(String transactionType) {
this.transactionType = transactionType;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
@Override
public String toString() {
return "PaymentTransaction [transactionType=" + transactionType
+ ", transactionId=" + transactionId + "]";
}
}

Controller :

@RestController
public class MyController {

/**
* https://stackoverflow.com/questions/34782025/http-post-request-with-content-type-application-x-www-form-urlencoded-not-workin/38252762#38252762
*/

@PostMapping(value = "/v1/{token}",
consumes = MediaType.APPLICATION_XML_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody PaymentTransaction handleMessage(@PathVariable("token") String token,
@RequestBody PaymentTransaction transaction, HttpServletRequest request) throws Exception {
System.out.println("handleXmlMessage");
System.out.println(transaction);
PaymentTransaction body = new PaymentTransaction();
body.setTransactionId(transaction.getTransactionId());
body.setTransactionType("received: " + transaction.getTransactionType());
return body;
}

@PostMapping(consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, value = "/v1/notification")
public ResponseEntity<String> handleNotifications(@ModelAttribute PaymentTransaction transaction) {
System.out.println("handleFormMessage");
System.out.println(transaction);
return new ResponseEntity<String>(HttpStatus.OK);
}
}

唯一要记住的主要事情是,用解析的数据填充 DTO 似乎是通过反射发生的:

供您输入

<payment_transaction>
<transaction_id>1</transaction_id>
<transaction_type>name</transaction_type>
</payment_transaction>

我收到此响应(请参阅我的 Controller ):

{
"transactionType": "received: null",
"transactionId": null
}

但是当我更改为 DTO 字段的名称时,它开始工作(根元素并不重要,有趣):

<payment_transaction>
<transactionId>1</transactionId>
<transactionType>name</transactionType>
</payment_transaction>

结果:

{
"transactionType": "received: name",
"transactionId": "1"
}

查询字符串也是如此。我不知道要更改什么才能让 spring 使用 @XmlRootElement/@XmlElement 中定义的名称解析 xml。

关于spring - 使用 RestController 接受字符串和 XML 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52118257/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com