我在xml中有一个spring集成路由,它将进行Web服务调用(multipart / formdata)并需要以JSON格式返回响应。问题是我没有找到任何带有响应的多部分请求的良好样本SI路由。任何帮助都非常感谢。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">
<bean id="byteArrayHttpMessageConverter"
class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
</bean>
<bean id="formHttpMessageConverter"
class="org.springframework.http.converter.FormHttpMessageConverter">
</bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
<bean id="headerMapper"
class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<property name="inboundHeaderNames" value="*" />
<property name="outboundHeaderNames" value="*" />
<property name="userDefinedHeaderPrefix" value="" />
</bean>
<int:channel id="http.request.submit.withfiles" />
<int:channel id="http.response.submit.withfiles" />
<int:channel id="http.router.route1.process.submit.withfiles" />
<int:channel id="http.router.route2.process.submit.withfiles" />
<int-http:inbound-gateway id="http.gateway.inbound.submit.withfiles"
supported-methods="POST" header-mapper="headerMapper"
request-channel="http.request.submit.withfiles"
reply-channel="http.response.submit.withfiles" path="/v1.0/file">
<int-http:request-mapping consumes="multipart/form-data"
produces="application/json" />
<int-http:header name="routingCode" expression="headers['routingCode']" />
</int-http:inbound-gateway>
<int:header-value-router input-channel="http.request.submit.withfiles"
header-name="routingCode" default-output-channel="http.router.route2.process.submit.withfiles">
<int:mapping value="AB"
channel="http.router.route1.process.submit.withfiles" />
<int:mapping value="AC"
channel="http.router.route2.process.submit.withfiles" />
<int:mapping value="AD"
channel="http.router.route2.process.submit.withfiles" />
<int:mapping value="AE"
channel="http.router.route2.process.submit.withfiles" />
<int:mapping value="AF"
channel="http.router.route2.process.submit.withfiles" />
</int:header-value-router>
<int-http:outbound-gateway
id="http.gateway.outbound.route1.submit.withfiles" header-mapper="headerMapper"
request-channel="http.router.route1.process.submit.withfiles"
reply-channel="http.response.submit.withfiles"
url="http://localhost:8080/myapplication1/file"
http-method-expression="headers.http_requestMethod"
expected-response-type="java.lang.String" charset="UTF-8"
reply-timeout="50000" />
<int-http:outbound-gateway
id="http.gateway.outbound.route2.submit.withfiles" header-mapper="headerMapper"
request-channel="http.router.route2.process.submit.withfiles"
reply-channel="http.response.submit.withfiles"
url="http://localhost:8081/myapplication2/file"
http-method="POST" charset="UTF-8" expected-response-type="java.lang.String"
reply-timeout="50000">
</int-http:outbound-gateway>
错误讯息:
02-Sep-2015 13:36:07.300 SEVERE [http-nio-8080-exec-13] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [springServlet] in context with path [/my-switcher] threw exception [Request processing failed; nested exception is org.springframework.messaging.MessageHandlingException: HTTP request execution failed for URI [http://localhost:8081/myapplication2/file]; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.integration.http.multipart.UploadedMultipartFile["inputStream"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.integration.http.multipart.UploadedMultipartFile["inputStream"])] with root cause
com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.integration.http.multipart.UploadedMultipartFile["inputStream"])
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:575)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:666)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:129)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2240)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
at org.springframework.http.converter.FormHttpMessageConverter.writePart(FormHttpMessageConverter.java:331)
at org.springframework.http.converter.FormHttpMessageConverter.writeParts(FormHttpMessageConverter.java:311)
at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:301)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:240)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:87)
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:774)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:567)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:466)
at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:422)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:99)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:286)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:245)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:95)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:188)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:286)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:150)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:42)
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:331)
at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:302)
at org.springframework.integration.http.inbound.HttpRequestHandlingEndpointSupport.actualDoHandleRequest(HttpRequestHandlingEndpointSupport.java:492)
at org.springframework.integration.http.inbound.HttpRequestHandlingEndpointSupport.doHandleRequest(HttpRequestHandlingEndpointSupport.java:389)
at org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway.handleRequest(HttpRequestHandlingMessagingGateway.java:103)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:51)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1517)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1474)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
更多详情:
实际的webservice(http://localhost:8081/myapplication2/file)执行多部分表单上载并将json消息返回给调用应用程序。所以我期望从这个SI路由是http-outbound网关将调用上面的webservice并做一个postupload并返回一个json响应。
答案 0 :(得分:2)
目前不支持代理这样的multipart/form-data
请求。
问题是Spring MVC已将原始表单数据转换为MultipartHttpInputMessage
;它由入站网关进一步转换为MultiValueMap
,其中文件部分是UploadedMultipartFile
个实例。
出站网关不知道如何处理此对象;它不是转换器。
您可以尝试添加转换器,将有效负载中的UploadedMultiPartFile
元素转换为Resource
(s),或者编写自定义MessageConverter
并将其注入出站网关。
我们看到越来越多的HTTP&#34;代理&#34;方案,所以请打开一个新功能&#39; JIRA issue
更好的是,考虑contributing解决方案!
修改
这是另一项工作 - 它更有效率。实际上,我们希望在入站网关中禁用多部分解码,并将多部分请求不变地传递给出站。
以下是如何做到的......
删除多部分解析器bean
添加自定义&#34; pass-thru&#34;多部分转换器到入站网关......
public class PassThroughMultiPartConverter implements HttpMessageConverter<byte[]> {
@Override
public boolean canRead(Class<?> clazz, MediaType mediaType) {
if (!(byte[].class.isAssignableFrom(clazz))) {
return false;
}
if (mediaType != null) {
return MediaType.APPLICATION_FORM_URLENCODED.includes(mediaType)
|| MediaType.MULTIPART_FORM_DATA.includes(mediaType);
}
else {
return false;
}
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
public List<MediaType> getSupportedMediaTypes() {
return Collections.singletonList(MediaType.MULTIPART_FORM_DATA);
}
@Override
public byte[] read(Class<? extends byte[]> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileCopyUtils.copy(inputMessage.getBody(), baos);
return baos.toByteArray();
}
@Override
public void write(byte[] t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
throw new UnsupportedOperationException();
}
}
<int-http:inbound-gateway
...
request-payload-type="byte[]"
message-converters="converter"
merge-with-default-converters="false" />
<bean id="converter" class="foo.PassThroughMultiPartConverter" />
答案 1 :(得分:0)
谢谢Gary。
到目前为止,我通过更换&#39; http出站网关方式解决了这个问题。与服务激活者&#39;并通过服务激活器中引用的类中的REST模板调用Web服务。
<int:service-activator id="serviceactivator"
input-channel="http.router.process.submit.withfiles"
output-channel="http.response.submit.withfiles"
ref="multipartReceiver" method="receive"
requires-reply="true" >
</int:service-activator>