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 ....