- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有一个 Spring Boot 1.3.6 应用程序,开箱即用并使用嵌入式 Tomcat 服务器。该应用程序有一个端点执行一个非常简单的回显请求。
后来我使用 AsyncRestTemplate
定义了一个调用该简单端点的相应客户端,但是如果我的客户端使用 Netty4ClientHttpRequestFactory
请求失败,否则它成功。
我下面的示例是在 Kotlin 中,但在 Java 中同样失败,因此它与我用来实现它的语言无关。
@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())))
}
}
我的端点如下所示:
@RestController
class EchoController {
@RequestMapping(value="/foo", method = arrayOf(RequestMethod.PUT))
fun echo(@RequestBody order: Order): Order {
return order
}
}
而订单数据类是
data class Order(val orderId: String)
注意:由于我使用 Kotlin,因此我还添加了 Kotlin Jackson Module以确保正确的构造函数反序列化。
然后我继续创建一个调用此端点的客户端。
如果我在我的客户端中执行以下操作,它会完美运行并且我会获得成功的回显响应。
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 报告我没有通过正文:
val nettyFactory = Netty4ClientHttpRequestFactory()
val restTemplate = AsyncRestTemplate(nettyFactory)
当我这样做时,我会收到一个 HttpMessageNotReadableException
消息,上面写着“缺少必需的请求正文”。
我调试了 Spring Boot 代码,发现当读取 ServletInputStream
时,它总是返回 -1,就好像它是空的一样。
在我的 gradle 中,我添加了 runtime('io.netty:netty-all:4.1.2.Final')
,所以我现在使用的是最新版本的 Netty .这个 Netty 版本在与我使用常规 Spring(即不是 Spring Boot)的其他项目中的端点交互时工作得很好。
为什么 SimpleClientHttpRequestFactory
工作正常,但 Netty4ClientHttpRequestFactory
失败了?
我认为这可能与嵌入式 Tomcat 服务器有关,但是,如果我将此应用程序打包为 war 并将其部署在现有的 Tomcat 服务器中(即不使用嵌入式服务器),问题仍然存在。所以,我猜是与 Spring/Spring Boot 有关的东西。
我的 Spring Boot 应用程序中是否缺少任何配置?有关如何使 Netty 客户端与 Spring Boot 一起工作的任何建议?
最佳答案
看起来客户端的序列化存在问题。因为这段代码完美运行:
restTemplate.exchange(
URI.create("http://localhost:8080/foo"),
HttpMethod.PUT,
HttpEntity("""{"orderId":"1234"}""", HttpHeaders().apply {
setContentType(MediaType.APPLICATION_JSON);
}),
Order::class.java
).addCallback(object : ListenableFutureCallback<ResponseEntity<Order>> {
override fun onSuccess(result: ResponseEntity<Order>) {
println("Result: ${result.body}")
}
override fun onFailure(ex: Throwable) {
ex.printStackTrace()
if (ex is HttpStatusCodeException) {
println(ex.responseBodyAsString)
}
}
})
我需要更精确地查看他的转换器中的 restTemplate,但现在你可以这样写这部分:
val mapper = ObjectMapper()
restTemplate.exchange(
URI.create("http://localhost:8080/foo"),
HttpMethod.PUT,
HttpEntity(mapper.writeValueAsString(Order("HELLO")), HttpHeaders().apply {
setContentType(MediaType.APPLICATION_JSON);
}),
Order::class.java
).addCallback(object : ListenableFutureCallback<ResponseEntity<Order>> {
override fun onSuccess(result: ResponseEntity<Order>) {
println("Result: ${result.body}")
}
override fun onFailure(ex: Throwable) {
ex.printStackTrace()
if (ex is HttpStatusCodeException) {
println(ex.responseBodyAsString)
}
}
})
如您所见,我不使用 KotlinModule,而且这段代码运行良好,所以显然配置 AsyncRestTemplate 本身存在问题。
关于java - 带有 AsyncRestTemplate Netty 客户端的 Spring Boot 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38319599/
有人可以解释一下 spring-boot-parent 和 spring-boot-starter-parent 之间的区别吗,正如我在下面附加的 GIT HUB 代码链接之一中看到的,他们为 spr
我有与 jersey 框架集成的 Spring Boot 应用程序。 现在,当我尝试运行该应用程序时,它只是停留在 Spring 启动徽标上,之后没有任何 react 。 我也尝试添加 -X ,但徽标
我指的是 Spring Boot 关于 的文档自动配置 和 执行器 模块: 自动配置: Spring Boot AutoConfiguration attempts to automatically
我正在尝试将 apache log4j 集成到我的 Spring boot 应用程序中。这是我的 build.gradle 文件: build.gradle buildscript { rep
使用 Spring Boot Maven 插件的以下命令在生产中启动 Spring Boot 应用程序是否是一个好主意或实践? mvn spring-boot:run 最佳答案 不,这是个坏主意。 您
据我所知,spring boot 和 spring session 为我们提供了一站式自动配置,但是当我的应用程序使用 session redis 和应用程序缓存 redis 时,不是同一个 redi
我希望使用Spring Boot创建一个新的Web应用程序。不幸的是,我的服务器在技术堆栈方面相当有限。它安装了Java 5。 谁能告诉我spring boot是否可以在Java 1.5上运行以及什么
我有3个实体 CarWash(设置Wash) Wash(car_wash_id FK到CarWash) WashComment(wash_id FK到Wash) 有什么办法可以写这个查询 @Qu
我一直在关注this文章。 我正在尝试在Spring-boot应用程序中优雅地处理gRPC错误,的主要目标是能够在gRPC客户端中获取错误状态。 在上面的文章之后,我坚持为异常添加拦截器。如何在Spr
我有一个要使用的自定义log4j布局插件。在IntelliJ中运行或与./gradlew bootRun一起运行时,插件可以正常工作。不使用./gradlew bootJar构建启动jar。 启用-D
我想在给定范围 (5001-5100) 的随机端口上启动 Spring Cloud 应用程序(Spring Boot 1.5.14,Spring Cloud Edgware.SR4)。我知道我们可以使
任何人都可以向我展示或指出不使用 spring boot gradle 插件的 spring boot gradle 项目。 我正在寻找类似不使用 gradle 插件的 spring boot sta
我当时尝试包含上述依赖项之一,但找不到任何区别: spring boot starter web:我可以看到 Flux 和 Mono 类并制作一个响应式(Reactive)休息 Controller
我们一直在为我们的应用程序使用 Springboot 1.X。 现在准备开始一些新的应用程序,想知道我们是应该使用 SpringBoot2.0 还是坚持使用 SpringBoot 1.X? 对一种方式
我希望记录应用程序正在加载 application-profile.propeties 或 application.yml。怎么做。在哪种方法中,我可以听取它并检测它是成功加载还是失败。 最佳答案 您
当我在 pom.xml 中添加简单的 spring-boot-starter-data-jpa 依赖项时,在 pom.xml 文件中出现错误。如果我删除该依赖项,则不会再有错误。我不确定为什么会发生这
我希望记录应用程序正在加载 application-profile.propeties 或 application.yml。怎么做。在哪种方法中,我可以听取它并检测它是成功加载还是失败。 最佳答案 您
我在网上看了很多关于 spring-boot-devtools 的文章和问题,但仍然无法弄清楚为什么它对我不起作用。每次运行我的应用程序时,我都会得到以下信息: 17:54:28.057 [main]
我正在尝试将现有的 Spring 应用程序移植到 Spring Boot。我不使用 spring-boot-starter-data-solr 启动器,但是我的类路径上有 apache solrj (
(这主要是一个历史问题。Pivotal 建议所有论坛讨论都在 StackOverflow 上进行,这就是我在这里问它的原因。) Spring Boot 项目用来证明将应用程序的类和依赖项从可执行 ja
我是一名优秀的程序员,十分优秀!