可以在 Kotlin 中将 LocalDateTime 用作 RequestParam 吗?
Is possible to use LocalDateTime as a RequestParam in Kotlin?
我正在学习 Kotlin,正在做一个简单的 API Rest with Spring Boot。我的问题是我正在尝试将 LocalDateTime 用作 @RequestParam,但它无法像在 Java 中那样工作。
这是我的代码:
import org.springframework.format.annotation.DateTimeFormat
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDateTime
@RestController
@RequestMapping("/flights")
class FlightController(private val flightService : FlightService) {
@GetMapping
fun getFlights(@RequestParam @DateTimeFormat(pattern = "hh:mma") departure : LocalDateTime?): List<Flight> {
return flightService.getFlights()
}
}
当我执行 HTTP 调用时,这是我在控制台中看到的错误:
Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime] for value '09:00am'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [09:00am]]
(在这种情况下,我尝试将 09:00am 作为 RequestParam)
我认为 Jackson 无法将 JSON 解析为 LocalDateTime 是个问题,有人知道是否有解决方案吗?
谢谢大家
(已编辑)
这是完整的堆栈跟踪:
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.1)
2021-06-18 11:34:42.650 INFO 16396 --- [ main] c.e.f.FlightsKotlinApplicationKt : Starting FlightsKotlinApplicationKt using Java 16.0.1 on ar-it14622 with PID 16396
2021-06-18 11:34:42.652 INFO 16396 --- [ main] c.e.f.FlightsKotlinApplicationKt : No active profile set, falling back to default profiles: default
2021-06-18 11:34:43.238 INFO 16396 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2021-06-18 11:34:43.293 INFO 16396 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 46 ms. Found 1 JPA repository interfaces.
2021-06-18 11:34:43.689 INFO 16396 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-06-18 11:34:43.696 INFO 16396 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-06-18 11:34:43.696 INFO 16396 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.46]
2021-06-18 11:34:43.838 INFO 16396 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-06-18 11:34:43.839 INFO 16396 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1145 ms
2021-06-18 11:34:43.971 INFO 16396 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2021-06-18 11:34:44.009 INFO 16396 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.32.Final
2021-06-18 11:34:44.104 INFO 16396 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2021-06-18 11:34:44.183 INFO 16396 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-06-18 11:34:44.440 INFO 16396 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2021-06-18 11:34:44.464 INFO 16396 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2021-06-18 11:34:44.780 INFO 16396 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-06-18 11:34:44.788 INFO 16396 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-06-18 11:34:45.092 WARN 16396 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-06-18 11:34:45.396 INFO 16396 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-06-18 11:34:45.404 INFO 16396 --- [ main] c.e.f.FlightsKotlinApplicationKt : Started FlightsKotlinApplicationKt in 3.084 seconds (JVM running for 3.901)
2021-06-18 11:34:54.426 INFO 16396 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-06-18 11:34:54.426 INFO 16396 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-06-18 11:34:54.427 INFO 16396 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2021-06-18 11:34:54.484 WARN 16396 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime] for value '09:00am'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [09:00am]]
还有我的 build.gradle.kts(也许会有帮助):
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.ir.backend.js.compile
plugins {
id("org.springframework.boot") version "2.5.1"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.10"
kotlin("plugin.spring") version "1.5.10"
kotlin("plugin.jpa") version "1.5.10"
}
group = "com.learning"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_16
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.apache.logging.log4j:log4j-api-kotlin:1.0.0")
implementation("org.apache.logging.log4j:log4j-api:2.11.1")
implementation("org.apache.logging.log4j:log4j-core:2.11.1")
runtimeOnly("mysql:mysql-connector-java")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.5")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "16"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
单靠时间信息不足以实例化 LocalDateTime
。 class 表示带有时间的日期。您缺少日期部分。
您评论说您尝试使用 LocalTime
但失败了。我猜测您的字符串输入与您的 JVM 当前默认值 Locale
预期的 AM/PM 指示符所使用的格式不匹配。不同的文化可能使用“am”、“AM”、“A.M.”或其他名称。解决方案包括:
- 明确指定
Locale
而不是隐式依赖 JVM 当前的默认语言环境。
- 使用标准 ISO 8601 格式。当 parsing/generating 日期时间文本值时,这些在 java.time classes 中默认使用。因此无需指定格式化模式。对于一天中的时间,使用 24 小时制,小时填充零,并且没有 AM/PM。例如:
23:45
和 03:27
.
我建议你在一些简单的一次性代码中练习使用 java.time classes,而没有 Spring 的复杂性。
日期时间处理并不像您的直觉那样简单和微不足道。事实上,您对日期时间的直观理解是一个障碍,例如导致您使用 AM/PM 而不是使用 24 小时制。花时间搜索 Stack Overflow 以了解有关 java.time classes.
的更多信息
我正在学习 Kotlin,正在做一个简单的 API Rest with Spring Boot。我的问题是我正在尝试将 LocalDateTime 用作 @RequestParam,但它无法像在 Java 中那样工作。 这是我的代码:
import org.springframework.format.annotation.DateTimeFormat
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDateTime
@RestController
@RequestMapping("/flights")
class FlightController(private val flightService : FlightService) {
@GetMapping
fun getFlights(@RequestParam @DateTimeFormat(pattern = "hh:mma") departure : LocalDateTime?): List<Flight> {
return flightService.getFlights()
}
}
当我执行 HTTP 调用时,这是我在控制台中看到的错误:
Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime] for value '09:00am'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [09:00am]]
(在这种情况下,我尝试将 09:00am 作为 RequestParam)
我认为 Jackson 无法将 JSON 解析为 LocalDateTime 是个问题,有人知道是否有解决方案吗? 谢谢大家
(已编辑)
这是完整的堆栈跟踪:
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.1)
2021-06-18 11:34:42.650 INFO 16396 --- [ main] c.e.f.FlightsKotlinApplicationKt : Starting FlightsKotlinApplicationKt using Java 16.0.1 on ar-it14622 with PID 16396
2021-06-18 11:34:42.652 INFO 16396 --- [ main] c.e.f.FlightsKotlinApplicationKt : No active profile set, falling back to default profiles: default
2021-06-18 11:34:43.238 INFO 16396 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2021-06-18 11:34:43.293 INFO 16396 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 46 ms. Found 1 JPA repository interfaces.
2021-06-18 11:34:43.689 INFO 16396 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-06-18 11:34:43.696 INFO 16396 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-06-18 11:34:43.696 INFO 16396 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.46]
2021-06-18 11:34:43.838 INFO 16396 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-06-18 11:34:43.839 INFO 16396 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1145 ms
2021-06-18 11:34:43.971 INFO 16396 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2021-06-18 11:34:44.009 INFO 16396 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.32.Final
2021-06-18 11:34:44.104 INFO 16396 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2021-06-18 11:34:44.183 INFO 16396 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-06-18 11:34:44.440 INFO 16396 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2021-06-18 11:34:44.464 INFO 16396 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2021-06-18 11:34:44.780 INFO 16396 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-06-18 11:34:44.788 INFO 16396 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-06-18 11:34:45.092 WARN 16396 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-06-18 11:34:45.396 INFO 16396 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-06-18 11:34:45.404 INFO 16396 --- [ main] c.e.f.FlightsKotlinApplicationKt : Started FlightsKotlinApplicationKt in 3.084 seconds (JVM running for 3.901)
2021-06-18 11:34:54.426 INFO 16396 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-06-18 11:34:54.426 INFO 16396 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-06-18 11:34:54.427 INFO 16396 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2021-06-18 11:34:54.484 WARN 16396 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime] for value '09:00am'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [09:00am]]
还有我的 build.gradle.kts(也许会有帮助):
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.ir.backend.js.compile
plugins {
id("org.springframework.boot") version "2.5.1"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.10"
kotlin("plugin.spring") version "1.5.10"
kotlin("plugin.jpa") version "1.5.10"
}
group = "com.learning"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_16
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.apache.logging.log4j:log4j-api-kotlin:1.0.0")
implementation("org.apache.logging.log4j:log4j-api:2.11.1")
implementation("org.apache.logging.log4j:log4j-core:2.11.1")
runtimeOnly("mysql:mysql-connector-java")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.5")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "16"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
单靠时间信息不足以实例化 LocalDateTime
。 class 表示带有时间的日期。您缺少日期部分。
您评论说您尝试使用 LocalTime
但失败了。我猜测您的字符串输入与您的 JVM 当前默认值 Locale
预期的 AM/PM 指示符所使用的格式不匹配。不同的文化可能使用“am”、“AM”、“A.M.”或其他名称。解决方案包括:
- 明确指定
Locale
而不是隐式依赖 JVM 当前的默认语言环境。 - 使用标准 ISO 8601 格式。当 parsing/generating 日期时间文本值时,这些在 java.time classes 中默认使用。因此无需指定格式化模式。对于一天中的时间,使用 24 小时制,小时填充零,并且没有 AM/PM。例如:
23:45
和03:27
.
我建议你在一些简单的一次性代码中练习使用 java.time classes,而没有 Spring 的复杂性。
日期时间处理并不像您的直觉那样简单和微不足道。事实上,您对日期时间的直观理解是一个障碍,例如导致您使用 AM/PM 而不是使用 24 小时制。花时间搜索 Stack Overflow 以了解有关 java.time classes.
的更多信息