首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring Boot with AsyncRestTemplate Netty Client失败

Spring Boot with AsyncRestTemplate Netty Client失败
EN

Stack Overflow用户
提问于 2016-07-12 11:33:23
回答 0查看 2.4K关注 0票数 7

我有一个Spring Boot 1.3.6应用程序,开箱即用并使用嵌入式Tomcat服务器构建。这个应用程序只有一个端点执行非常简单的回显请求。

稍后,我使用AsyncRestTemplate定义了一个调用该简单端点的相应客户端,但是,如果我的客户端使用Netty4ClientHttpRequestFactory,则请求失败,否则请求成功。

我下面的例子是用Kotlin编写的,但它在Java中同样失败了,所以它与我用来实现它的语言无关。

服务器

代码语言:javascript
复制
@SpringBootApplication
open class EchoApplication {

    companion object {
       @JvmStatic fun main(args: Array<String>) {
          SpringApplication.run(EchoApplication::class.java, *args)
       }
    }

    @Bean
    open fun objectMapper(): ObjectMapper {
        return ObjectMapper().apply {
            dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
            registerModule(KotlinModule())
        }
    }

    @Bean
    open fun customConverters(): HttpMessageConverters {
        return HttpMessageConverters(listOf(MappingJackson2HttpMessageConverter(objectMapper())))
    }
}

我的端点如下所示:

代码语言:javascript
复制
@RestController
class EchoController {

    @RequestMapping(value="/foo", method = arrayOf(RequestMethod.PUT))
    fun echo(@RequestBody order: Order): Order {
        return order
    }

}

order数据类是

代码语言:javascript
复制
data class Order(val orderId: String)

注意:由于我使用Kotlin,我还添加了Kotlin Jackson Module以确保正确的构造函数反序列化。

客户端

然后,我继续创建一个调用此端点的客户端。

如果我在我的客户机中执行类似以下的操作,它将完美地工作,并且我会得到一个成功的回显响应。

代码语言:javascript
复制
    val executor = TaskExecutorAdapter(Executors.newFixedThreadPool(2))
    val restTemplate = AsyncRestTemplate(executor)
    restTemplate.messageConverters = listOf(MappingJackson2HttpMessageConverter(mapper))

    val promise = restTemplate.exchange(URI.create("http://localhost:8080/foo"), HttpMethod.PUT, HttpEntity(Order("b1254"), headers), Order::class.java)
    promise.addCallback(object : ListenableFutureCallback<ResponseEntity<Order>> {
        override fun onSuccess(result: ResponseEntity<Order>) {
            println(result.body)
        }

        override fun onFailure(ex: Throwable) {
            ex.printStackTrace()
            if(ex is HttpStatusCodeException){
                println(ex.responseBodyAsString)
            }
        }
    })

如上所述,上面的代码运行良好,并打印出一个成功的回显响应。

问题所在

但是如果我决定使用Netty客户端,那么我会收到400 Bad Request报告我没有传递body:

代码语言:javascript
复制
val nettyFactory = Netty4ClientHttpRequestFactory()
val restTemplate = AsyncRestTemplate(nettyFactory)

当我这样做的时候,我得到了一个HttpMessageNotReadableException,其中有一条消息说"Required request body is missing“。

我调试了Spring Boot代码,我看到当读取ServletInputStream时,它总是返回-1,就好像它是空的一样。

在我的gradle中,我添加了runtime('io.netty:netty-all:4.1.2.Final'),所以我现在使用的是Netty的最新版本。这个Netty版本在与我使用常规Spring (即不是Spring Boot)的其他项目中的端点交互时工作得很好。

为什么SimpleClientHttpRequestFactory运行正常,但Netty4ClientHttpRequestFactory却失败了?

我认为这可能与嵌入式Tomcat服务器有关,但是,如果我将此应用程序打包为war并将其部署到现有的Tomcat服务器中(即不使用嵌入式Tomcat服务器),问题仍然存在。所以,我猜是与Spring/Spring Boot相关的东西。

我的Spring Boot应用程序中是否缺少任何配置?关于如何让Netty客户端与Spring Boot一起工作,有什么建议吗?

EN

回答

页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38319599

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档