Java @RequestMapping MethodInterceptor方面忽略@Validated注释
我对Java @RequestMapping MethodInterceptor方面忽略@Validated注释,java,spring,validation,interceptor,aspect,Java,Spring,Validation,Interceptor,Aspect,我对MethodInterceptor方面和@Validated注释有一个奇怪的问题。当我添加方法拦截器来截取用@RequestMapping注释的所有方法时,@Validated注释不起作用。当我移除它时,它又可以正常工作了。我想,我的拦截器会覆盖@Validated。有没有什么方法可以做到这一点,因为我不想在我的拦截器中执行验证,因为它是用来审计东西的 以下是验证程序: @Component public class UserValidator implements Validator {
MethodInterceptor
方面和@Validated
注释有一个奇怪的问题。当我添加方法拦截器来截取用@RequestMapping
注释的所有方法时,@Validated
注释不起作用。当我移除它时,它又可以正常工作了。我想,我的拦截器会覆盖@Validated
。有没有什么方法可以做到这一点,因为我不想在我的拦截器中执行验证,因为它是用来审计东西的
以下是验证程序:
@Component
public class UserValidator implements Validator {
@Override
public void validate(Object target, Errors errors) {
//validation stuff
}
}
控制器的代码:
@Controller
@RequestMapping("/profile")
public class UserProfileController {
@Autowired
private UserValidator userValidator;
@InitBinder("userValidator")
private void userValidatorInitBinder(WebDataBinder binder) {
binder.setValidator(userValidator);
}
@RequestMapping(value = "/reg.do", method = RequestMethod.POST)
public @ResponseBody RegisterResponse reg(HttpServletRequest httpServletRequest, @RequestBody @Validated CreateUserRequest createUserRequest) {
}
}
拦截器代码:
@Aspect
@Component
public class MyInterceptor implements MethodInterceptor, Serializable {
@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object returnValue = null;
final StopWatch stopWatch = new StopWatch();
try {
stopWatch.start();
returnValue = invocation.proceed();
return returnValue;
} catch (Throwable ex) {
stopStopwatch(stopWatch);
throw ex;
} finally {
System.out.println(stopwatch);
}
}
}
我的环境是带有rest控制器(Jackson Mapper)的Spring MVC(3.2)。您应该检查Spring上下文和POM中的以下元素:
- 说明您应该配置
MethodValidationPostProcessor
,与Hibernate类似。因此,应该配置依赖项。这应该起作用:方法验证后处理器
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.0.1.Final</version> </dependency>
javax.validation 验证api 1.1.0.1最终版本 org.hibernate 休眠验证器 5.0.1.最终版本
- 问题在于使用了基于代理的AOP,在这种情况下,由于没有接口,它是基于类的代理。由于
@RequestBody
和@Validated
方法不是继承的,因此它们不存在于重写该方法的子类中。因此,不再有@验证的
要解决这个问题,有(在这种情况下)两种解决方案
一个HandlerInterceptor
而不是AOP
侦听ServletRequestHandledEvent
s的ApplicationListener
向所有控制器添加一个界面,该界面也包含注释
使用加载时或编译时编织,而不是基于代理的AOP
因为这只是一个性能测量,所以使用选项1和2非常容易。选项3可能非常具有侵入性,选项4取决于所使用的servlet容器
使用HandlerInterceptor
但是,由于这只是一个性能度量,适用于处理程序而不是AOP,我建议使用HandlerInterceptor
,它将在preHandle
方法中开始计时,并在afterCompletion
方法中结束计时
public class PerformanceMeasureInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
StopWatch sw = new StopWatch();
sw.start();
request.setAttribute("performance-measure-sw", sw);
return true;
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
StopWatch sw = (StopWatch) request.getAttribute("performance-measure-sw");
if (sw != null) {
sw.stop();
System.out.println(sw);
}
}
}
使用ApplicationListener
由于已监视处理请求所需的时间,并且在处理请求后将触发一个包含处理所需时间的。您可以创建侦听事件并将一行写入日志文件(或控制台)的
您可能希望检查spring已经提供的spring性能拦截器,而不是自己滚动。您可能希望使用的子类之一,而不是您自己的。(虽然这不能帮助您解决代理问题,但它可以帮助您维护自己的性能拦截器)。您的方面会导致实际控制器的代理。此代理在检测实际注释时可能有问题。还有为什么UserValidator
也是绑定中使用的对象!!!还发布拦截器的代码。@M.Deinum“UserValidator”是一个单例实例,我在活页夹中注册它,因为我有多动作控制器,所以我有多个验证器,拦截器中的代码只计算请求和“return invocation.procedure();”的时间请阅读我的评论。。。您正在将验证器用作模型对象。。。此@RequestBody@validateduservalidator UserValidator
是方法签名的一部分。。。我非常怀疑传入的请求是否会变成UserValidator
它可能更像用户
。。。如前所述,添加方面的imlpementation..。@M.Deinum是的,我注意到并更新了线程,但这不是问题,实际代码使用CreateUserRequest(上面更新)时没有任何注释。再次请求请为您的方面添加代码。。。当你混合AspectJ风格和aopalliance风格时,这看起来很奇怪。选择一个不要混合。它在没有任何额外配置的情况下运行良好,每当我删除拦截器时,它就会再次正常工作,而且我没有使用hibernate验证注释,我使用的是spring验证程序,它不需要上述2个JAR。我昨天已经做了,但仍然不工作,关于Handler拦截器,我知道,但拦截器的范围超出了时间跟踪,它正在审核每个请求和响应(JSON),因此方法参数已经绑定,我知道HandlerInterceptor可以这样做,但需要额外的代码。我会选择普通的过滤器,谢谢:)根据您的需要(如果只是记录),Spring有AbstractRequestLoggingFilter
,如果配置正确,它会记录请求,包括有效负载等。正如我所说的,由于子类化,代理方法会遇到问题。
@Component
public class PerformanceListener implements ApplicationListener<ServletRequestHandledEvent> {
public void onApplicationEvent(ServletRequestHandledEvent event) {
System.out.println("Processing: " + event.getRequestUrl() + ", took: " + event.getProcessingTimeMillis + "ms. ");
}
}
@Aspect
@Component
public class MyInterceptor {
@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
Object returnValue = null;
final StopWatch stopWatch = new StopWatch();
try {
stopWatch.start();
returnValue = pjp.proceed();
return returnValue;
} catch (Throwable ex) {
throw ex;
} finally {
stopStopwatch(stopWatch);
System.out.println(stopwatch);
}
}
}