在出站网关上使用 RestTemplate 进行基本身份验证

Basic Authentication with RestTemplate on outbound gateway

一直在拉我剩下的一点点头发,试图让它发挥作用。

问题 1:

我正在对 Spring 控制器执行 JSON POST。我将 Authentication header 作为参数传递给 int:gateway。然后调用 int-http:outbound-gateway。我可以看到 header 以及与远程应用程序的握手,但我从 org.apache.http.impl.client.DefaultHttpClient 得到了 400 Bad Request。我能够使用单独的客户端直接验证和执行请求(即没有 SI)。

我使用 this 解决方案中提到的组件失败。我哪里出错了?

我不喜欢的是对 DefaultHttpClient 的引用,正如其他帖子中提到的那样,它似乎已被弃用。不确定这里有什么选择。我在某处看到提到使用 OkHttp 客户端,但我不确定如何将其与 SI 联系起来。

问题 2:

returns 下面的服务是 ResponseEntity<?>,因为我无法将其转换为域特定类型 (CustSyncResponseVO)。在将 RestTemplate 与 SI 一起使用时,我是否应该期待这种行为,或者我是否可以对 outbound-gateway 响应执行转换?

如有任何帮助,我们将不胜感激!

环境

控制器

@RequestMapping(value = "/customerSync", method = RequestMethod.POST)
public @ResponseBody CustSyncResponseVO syncCustomer(@RequestBody CustSyncRequestVO customerSyncRequest, 
        @RequestHeader(value = "Authorization") String authorization ) {
    CustSyncResponseVO customerSyncResponse = null;

    customerSyncResponse = customerService.deliver(customerSyncRequest, authorization);

    return customerSyncResponse;
}

服务

package com.uscs.crm.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;

import com.uscs.crm.integration.CustomerGateway;
import com.uscs.crm.model.CustLinkRequestVO;
import com.uscs.crm.model.CustSyncRequestVO;
import com.uscs.crm.model.CustSyncResponseVO;

@Service
public class CustomerServiceImpl implements CustomerService {

    private static Logger logger = LoggerFactory.getLogger(CustomerServiceImpl.class);

    @Autowired
    private CustomerGateway customerGateway;

    @Override
    public CustSyncResponseVO deliver(CustSyncRequestVO custSyncRequest, @Header(value="Authorization") String authorization) {
        CustSyncResponseVO custSyncResponse = null;     
        //custSyncResponse = customerGateway.deliver(custSyncRequest);
        ResponseEntity<?> responseEntity = null;
        try {
             responseEntity = customerGateway.deliver(custSyncRequest, authorization);
        } catch (Exception e) {
            logger.error("Unable to sync customer request to eWM" , e);
        } 

        return custSyncResponse;
    }


    @Override
    public CustSyncResponseVO link(CustLinkRequestVO linkRequest) {
        throw new UnsupportedOperationException("To be implemented");
    }

}

网关

package com.uscs.crm.integration;

import org.springframework.http.ResponseEntity;
import org.springframework.messaging.handler.annotation.Header;

import com.uscs.crm.model.CustSyncRequestVO;

public interface CustomerGateway {
    public static final String HTTP_AUTHORIZATION = "Authorization"; 

    public ResponseEntity<?> deliver(CustSyncRequestVO customer, @Header(HTTP_AUTHORIZATION) String authorization);

}

配置

<context:component-scan base-package="com.uscs.**"/> 

<!-- Authorization scope for accessing restful service.  Since we want this template to be used for everything, we are setting up it with defaults --> 
<bean id="authScope" class="org.apache.http.auth.AuthScope">
    <constructor-arg name="host"><null /></constructor-arg>
    <constructor-arg><value>-1</value> </constructor-arg>
    <constructor-arg><null /></constructor-arg>
    <constructor-arg><null /></constructor-arg>
</bean>

<bean id="httpComponentsMessageSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
    <property name="credentials">
        <bean class="org.apache.http.auth.UsernamePasswordCredentials">
            <constructor-arg name="userName"><value>xxxxxx</value></constructor-arg>
            <constructor-arg name="password"><value>xxxxxx</value></constructor-arg>
        </bean>
    </property>
    <property name="authScope" ref="authScope"/>
</bean>

<bean id="clientHttpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
    <property name="httpClient" value="#{httpComponentsMessageSender.httpClient}"/>
</bean>

<bean id="restTemplate" name="restTemplate" class="org.springframework.web.client.RestTemplate" autowire-candidate="true">
      <constructor-arg ref="clientHttpRequestFactory" />
  <property name="messageConverters"> 
      <list> 
          <bean  class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
          <bean class="org.springframework.http.converter.FormHttpMessageConverter"/> 
          <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
      </list> 
  </property>
</bean>

<int:channel id="syncCustomers"/>
<int:channel id="replySyncCustomers"/>

<int:gateway id="customerGateway" service-interface="com.uscs.crm.integration.CustomerGateway" 
        default-request-channel="syncCustomers" default-reply-channel="replySyncCustomers" />

<int:object-to-json-transformer input-channel="syncCustomers" output-channel="outboundRequestChannel" content-type="application/json" />    

<int-http:outbound-gateway request-channel="outboundRequestChannel" reply-channel="replySyncCustomers"
              url="http://voorhees148.uscold.com:9595/web/customerSync/createCustomer"
              http-method="POST"
              rest-template="restTemplate"
              expected-response-type="com.uscs.crm.model.CustSyncResponseVO" 
              mapped-request-headers="Authorization, HTTP_REQUEST_HEADERS"/>

从 SI 登录

10:07:03.981 [http-nio-8080-exec-1] DEBUG o.a.h.i.conn.DefaultClientConnection - Sending request: POST /web/customerSync/createCustomer HTTP/1.1
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "POST /web/customerSync/createCustomer HTTP/1.1[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "Accept: application/json, application/*+json[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "Authorization: Basic aHFyc2luZ2g6UGFzc3dvcmQxMjM=[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "Content-Type: application/json[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "Content-Length: 431[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "Host: voorhees148.uscold.com:9595[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "Connection: Keep-Alive[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "User-Agent: Apache-HttpClient/4.3.5 (java 1.5)[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> "[\r][\n]"
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - >> POST /web/customerSync/createCustomer HTTP/1.1
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - >> Accept: application/json, application/*+json
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - >> Authorization: Basic aHFyc2luZ2g6UGFzc3dvcmQxMjM=
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - >> Content-Type: application/json
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - >> Content-Length: 431
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - >> Host: voorhees148.uscold.com:9595
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - >> User-Agent: Apache-HttpClient/4.3.5 (java 1.5)
10:07:03.981 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  >> ""{\"legacyNo\":\"867530\",\"customerType\":\"24\",\"customerName\":\"Test Customer\",\"addr1\":\"123 Main Street\",\"addr2\":\"\",\"addr3\":\"\",\"city\":\"Podunk\",\"state\":\"MI\",\"zip\":\"48158\",\"country\":\"US\",\"phoneNumber\":\"8563334444\",\"contactName\":\"Jeb A. Dyah\",\"contactType\":\"123\",\"contactPhone\":\"8561112222\",\"contactFax\":\"8567778888\",\"contactEmail\":\"jeb@podunk.com\",\"actionCode\":\"CREATE\"}""
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "HTTP/1.1 400 Bad Request[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "X-Powered-By: Servlet/3.0[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Content-Type: text/html;charset=ISO-8859-1[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "$WSEP: [\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Content-Language: en-US[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Set-Cookie: JSESSIONID=0000yf8BRdBUc8w-OZldE5UDJSt:cd3aeb2b-d5ea-4ef6-8a84-9b912f76478c; Path=/; HttpOnly[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Transfer-Encoding: chunked[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Connection: Close[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Date: Sun, 20 Dec 2015 15:07:06 GMT[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Expires: Thu, 01 Dec 1994 16:00:00 GMT[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Cache-Control: no-cache="set-cookie, set-cookie2"[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "[\r][\n]"
10:07:06.576 [http-nio-8080-exec-1] DEBUG o.a.h.i.conn.DefaultClientConnection - Receiving response: HTTP/1.1 400 Bad Request
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << HTTP/1.1 400 Bad Request
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << X-Powered-By: Servlet/3.0
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << Content-Type: text/html;charset=ISO-8859-1
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << $WSEP: 
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << Content-Language: en-US
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << Set-Cookie: JSESSIONID=0000yf8BRdBUc8w-OZldE5UDJSt:cd3aeb2b-d5ea-4ef6-8a84-9b912f76478c; Path=/; HttpOnly
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << Transfer-Encoding: chunked
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << Connection: Close
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << Date: Sun, 20 Dec 2015 15:07:06 GMT
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << Expires: Thu, 01 Dec 1994 16:00:00 GMT
10:07:06.576 [http-nio-8080-exec-1] DEBUG org.apache.http.headers - << Cache-Control: no-cache="set-cookie, set-cookie2"
10:07:06.577 [http-nio-8080-exec-1] DEBUG o.a.h.c.p.ResponseProcessCookies - Cookie accepted [JSESSIONID="0000yf8BRdBUc8w-OZldE5UDJSt:cd3aeb2b-d5ea-4ef6-8a84-9b912f76478c", version:0, domain:voorhees148.uscold.com, path:/, expiry:null]
10:07:06.577 [http-nio-8080-exec-1] DEBUG o.s.web.client.RestTemplate - POST request for "http://voorhees148.uscold.com:9595/web/customerSync/createCustomer" resulted in 400 (Bad Request); invoking error handler
10:07:06.608 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "2b[\r][\n]"
10:07:06.608 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "Error 400: SRVE0295E: Error reported: 400[\r][\n]"
10:07:06.608 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "[\r][\n]"
10:07:06.608 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "0[\r][\n]"
10:07:06.608 [http-nio-8080-exec-1] DEBUG org.apache.http.wire -  << "[\r][\n]"
10:07:06.608 [http-nio-8080-exec-1] DEBUG o.a.h.i.conn.DefaultClientConnection - Connection 0.0.0.0:45624<->192.168.56.1:9595 closed
10:07:06.608 [http-nio-8080-exec-1] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection released: [id: 0][route: {}->http://voorhees148.uscold.com:9595][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
10:07:06.608 [http-nio-8080-exec-1] DEBUG o.s.i.g.GatewayProxyFactoryBean$MethodInvocationGateway - failure occurred in gateway sendAndReceive: HTTP request execution failed for URI [http://voorhees148.uscold.com:9595/web/customerSync/createCustomer]; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request
10:07:47.894 [http-nio-8080-exec-1] ERROR c.u.crm.service.CustomerServiceImpl - Unable to sync customer request to eWM
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:641) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:597) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:572) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:493) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:382) ~[spring-integration-http-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:99) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:231) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:154) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:102) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:105) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:150) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:45) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:42) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:97) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:38) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.messaging.core.AbstractMessagingTemplate.convertSendAndReceive(AbstractMessagingTemplate.java:79) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.core.AbstractMessagingTemplate.convertSendAndReceive(AbstractMessagingTemplate.java:70) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:412) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceive(MessagingGatewaySupport.java:386) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:422) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:382) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:373) ~[spring-integration-core-4.2.4.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at com.sun.proxy.$Proxy54.deliver(Unknown Source) ~[na:na]
    at com.uscs.crm.service.CustomerServiceImpl.deliver(CustomerServiceImpl.java:29) ~[classes/:na]
    at com.uscs.crm.controller.HelloController.syncCustomer(HelloController.java:35) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_67]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_67]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_67]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_67]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:871) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.7.0_67]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.7.0_67]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at java.lang.Thread.run(Unknown Source) [na:1.7.0_67]
10:07:51.692 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
10:07:51.693 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
10:07:51.693 [http-nio-8080-exec-1] DEBUG o.s.b.c.w.OrderedRequestContextFilter - Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@5f525ba5

EDIT1:

远程应用程序日志似乎表明将请求解组为预期类型时出现问题:

nested exception is org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class com.uscs.ewms.mdm.vo.customer.synchronizer.CustomerCreateSyncSubRequestVO] from JSON String; no single-String constructor/factory method (AbstractHandlerExceptionResolver.java:132)

远程应用程序中的控制器和请求类型

@RequestMapping(value = "/createCustomer", method = RequestMethod.POST, consumes = CONTENTTYPE_APPLICATION_JSON, produces = CONTENTTYPE_APPLICATION_JSON)
public @ResponseBody
CustomerSyncResponseVO createCustomer(HttpServletRequest request, @RequestBody CustomerCreateSyncSubRequestVO customerCreateSyncRequestVO, Principal principal) {

...

}

public class CustomerCreateSyncSubRequestVO {

@JsonProperty("legacyNo")
private String legacyNo;

...

}

远程 CustomerCreateSyncSubRequestVO 中没有默认构造函数,但是当我将 HTTP POST 直接发送到没有 SI 的远程应用程序时,这从 JSON 中解组没有问题中间。我觉得通过 outbound-gateway 发送的双引号 JSON "string" 导致了问题,因为 400 Bad Request 暗示无效 JSON。我来自 SI 网关的请求 object 确实有一个没有任何其他注释的默认构造函数:

package com.uscs.crm.model;

public class CustSyncRequestVO {

    private String legacyNo;
...
    public CustSyncRequestVO() {

    }
}

好吧,这是似乎对我有用的解决方案:

之前:

<bean id="restTemplate" name="restTemplate" class="org.springframework.web.client.RestTemplate" autowire-candidate="true">
      <constructor-arg ref="clientHttpRequestFactory" />
  <property name="messageConverters"> 
      <list> 
          <bean  class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
          <bean class="org.springframework.http.converter.FormHttpMessageConverter"/> 
          <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
      </list> 
  </property>
</bean> 

之后

<bean id="restTemplate" name="restTemplate" class="org.springframework.web.client.RestTemplate" autowire-candidate="true">
      <constructor-arg ref="clientHttpRequestFactory" />
  <property name="messageConverters"> 
      <list> 
          <bean class="org.springframework.http.converter.FormHttpMessageConverter"/> 
          <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
          <bean  class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
      </list> 
  </property>
</bean>

这解决了我在原文 post 中提到的两个问题。消息转换器的顺序很重要。

我在 this post 中找到了解决方案。