[英]Accept Strings and XML data from Ruby
我想創建一個REST Server,它接受來自Ruby代碼到不同控制器的XML請求和純文本。 我試圖實現這一點:
@SpringBootApplication
public class Application extends SpringBootServletInitializer implements WebMvcConfigurer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
..............
@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();
}
}
@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);
}
}
檢查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);
}
}
控制器類別:
@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&.....
形式的String。
如何配置Spring接受兩種類型? 還應該將Rest控制器拆分為不同的文件嗎?
編輯:
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年7月17日和Wildfly 13。
關於我使用的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
當在WildFly上作為WAR應用程序部署時,Spring Boot應用程序可能需要一些高級JDK反射API進行代理,包括在sun.reflect軟件包中。 為此,您的應用程序需要在其MANIFEST.MF文件中列出jdk.unsupported作為依賴項(有關此信息,請參閱WildFly Wiki)。
來源 -因此我首先應用了此方法。
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
<archive>
<manifestEntries>
<Dependencies>jdk.unsupported</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
接下來,我修復了日志記錄:我在此處應用了已接受答案的第一條注釋進行日志記錄,並將基本的logback.xml從此處添加到src / main / resources。
所以我的基本jboss-deployment-structure.xml是以下內容:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclude-subsystems>
<subsystem name="logging" />
</exclude-subsystems>
</deployment>
</jboss-deployment-structure>
從現在開始,在Wildfly控制台中,您可以看到發生了什么。
我以兩種分布測試了POC:
僅Servlet分發 (wildfly-servlet-13.0.0.Final.zip)
這與基本的jboss-deployment-structure.xml一起使用。
應用程序服務器分發 (wildfly-13.0.0.Final.zip)
在此服務器中,我必須添加org.reactivestreams模塊:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclude-subsystems>
<subsystem name="logging" />
</exclude-subsystems>
<dependencies>
<module name="org.reactivestreams"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
您必須將此文件放入src / main / webapp / WEB-INF目錄。
如果您需要使用與application / x-www-form-urlencoded不同的支持內容類型,則可以通過將適當的MessageConverter注冊到您的內容類型來實現。
在您的情況下,由於請求正文中的查詢字符串,FormHttpMessageConverter將是“適當的”,並且您必須將內容類型指定為MY_OTHER_CONTENT_TYPE常量:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FormHttpMessageConverter converter = new FormHttpMessageConverter();
MediaType utf8FormEncoded = new MediaType("application","x-www-form-urlencoded", Charset.forName("UTF-8"));
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_FORM_URLENCODED, MY_OTHER_CONTENT_TYPE));
converters.add(converter);
super.configureMessageConverters(converters);
}
但是使用的轉換器應該能夠處理它,因此您必須檢查轉換器的源(我這樣做了,如果是FormHttpMessageConverter,它應該以這種方式工作)我認為(或者您可以嘗試一下,如果它起作用,起作用)。 有時這並不是那么簡單 ,但是我希望對您來說它將以這種方式工作。
如果您無法解決,請給我們完整的示例,以解決有問題的請求 ,我將盡力使其正常運行。
去測試
請確保使用POST方法使用Content-Type:application / x-www-form-urlencoded標頭,並且您的參數正在請求正文中傳輸。 (我曾使用Boomerang Chrome插件進行測試,並在其中為發布請求定義了請求參數時,將其作為獲取參數添加到了請求URL中。這顯然導致了錯誤的結果。)
希望這些對您有所幫助。 如果沒有,請在應用正確的日志記錄設置后向我們顯示原因(請更新您的帖子,例外)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.