Java Spring MVC 控制器 PathVariables 上的 bean 验证
Java bean validation on Spring MVC Controller PathVariables
我正在尝试获取 Java Bean 验证注释以在 Spring MVC 控制器中使用路径变量和查询参数。 (环境:SpringBoot v1.3.5,Springxxx 4.2.6,编程语言Kotlin 1.0.3)
例如
@RequestMapping(value = "/{someId}" ...)
fun getSomething(**@SomeValidId** @PathVariable("someId") someId: String):...
我已经按照 https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/ 中的描述添加了 org.springframework.validation.beanvalidation.MethodValidationPostProcessor,并且还在上面添加了 org.springframework.validation.beanvalidation.LocalValidatorFactoryBean 作为 validatorFactory。
@Configuration
...class .... {
...
@Bean
open fun localValidatorFactoryBean() = LocalValidatorFactoryBean()
@Bean
open fun methodValidationPostProcessor() : MethodValidationPostProcessor {
val methodValidationPostProcessor = MethodValidationPostProcessor()
methodValidationPostProcessor.setValidator(localValidatorFactoryBean())
return methodValidationPostProcessor
}
}
但是当我用
org.springframework.validation.annotation.Validated 按照建议看起来控制器 class 被代理了(这似乎是预期的 - https://github.com/spring-projects/spring-security/issues/3215)。
@Validated
interface SomeResource {
....
@RestController
@RequestMapping("/somepath")
class SomeController ......: SomeResource ....
但这会导致 Spring mvc 请求映射设置忽略 SomeController。通过 Spring 框架代码调试看起来像 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods() 遍历 beans 列表并尝试检测处理程序方法,但是上面的控制器在遇到代理实例时被忽略了不带有@Controller 或@RequestMapping 注释。
有谁知道缺少什么吗?似乎有很多信息似乎表明这应该是可能的,但找不到有效的例子。
好吧,我发现了问题 - 这是因为为控制器创建的代理是 JDK 动态代理。当我强迫它成为 CGLIB 代理时,它开始正常工作。
默认情况下,Kotlin classes 是最终的,因此被迫使用 JDK 动态代理,但将控制器标记为 'open' 不足以强制其使用 CGLIB。必须将 @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 添加到控制器 class
@RestController
@RequestMapping("/somepath")
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class SomeController ......: SomeResource ....
我正在尝试获取 Java Bean 验证注释以在 Spring MVC 控制器中使用路径变量和查询参数。 (环境:SpringBoot v1.3.5,Springxxx 4.2.6,编程语言Kotlin 1.0.3)
例如
@RequestMapping(value = "/{someId}" ...)
fun getSomething(**@SomeValidId** @PathVariable("someId") someId: String):...
我已经按照 https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/ 中的描述添加了 org.springframework.validation.beanvalidation.MethodValidationPostProcessor,并且还在上面添加了 org.springframework.validation.beanvalidation.LocalValidatorFactoryBean 作为 validatorFactory。
@Configuration
...class .... {
...
@Bean
open fun localValidatorFactoryBean() = LocalValidatorFactoryBean()
@Bean
open fun methodValidationPostProcessor() : MethodValidationPostProcessor {
val methodValidationPostProcessor = MethodValidationPostProcessor()
methodValidationPostProcessor.setValidator(localValidatorFactoryBean())
return methodValidationPostProcessor
}
}
但是当我用 org.springframework.validation.annotation.Validated 按照建议看起来控制器 class 被代理了(这似乎是预期的 - https://github.com/spring-projects/spring-security/issues/3215)。
@Validated
interface SomeResource {
....
@RestController
@RequestMapping("/somepath")
class SomeController ......: SomeResource ....
但这会导致 Spring mvc 请求映射设置忽略 SomeController。通过 Spring 框架代码调试看起来像 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods() 遍历 beans 列表并尝试检测处理程序方法,但是上面的控制器在遇到代理实例时被忽略了不带有@Controller 或@RequestMapping 注释。
有谁知道缺少什么吗?似乎有很多信息似乎表明这应该是可能的,但找不到有效的例子。
好吧,我发现了问题 - 这是因为为控制器创建的代理是 JDK 动态代理。当我强迫它成为 CGLIB 代理时,它开始正常工作。
默认情况下,Kotlin classes 是最终的,因此被迫使用 JDK 动态代理,但将控制器标记为 'open' 不足以强制其使用 CGLIB。必须将 @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 添加到控制器 class
@RestController
@RequestMapping("/somepath")
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class SomeController ......: SomeResource ....