我已经在我的网络应用程序的服务层中实现了JSR303 JavaBean验证(根据this article)。现在我想将所有验证异常(例如javax.validation.ConstraintViolationException)转换为我的自定义异常。
我创建了一个在服务层中抛出异常时调用的Aspect:
@Aspect
public class ExceptionConversionAspect {
@AfterThrowing(pointcut="execution(* com.myexample.service.*.*(..))", throwing="e")
public void convertServiceException(Exception e) {
if (e instanceof ConstraintViolationException) {
// this is my custom exception
throw new InvalidServiceInputException("The service inputs failed validation", e);
}
}
}
但是当我的服务使用ConstraintViolationException验证失败时,我的异常转换方面没有被触发。我怀疑这是因为验证异常本身是由Aspect触发的:
@Aspect
public class ValidateAspect {
@Autowired
private Validator validator;
// Match any public methods in a class annotated with @AutoValidating
@Around("execution(public * *(..)) && @within(com.myexample.validator.annotation.Validate)")
public Object validateMethodInvocation(ProceedingJoinPoint pjp) throws Throwable {
// some code here
....
}
如何以正确的顺序链接我的方面?首先是ValidateAspect,然后是ExceptionConversionAspect?
答案 0 :(得分:0)
当多个方面共享公共连接点时,您可以使用@DeclarePrecedence语句手动设置执行顺序。在您的情况下,您可以创建一个新的方面:
@Aspect
@DeclarePrecedence("ValidateAspect, ExceptionConversionAspect")
public class SystemArchitecture {
// ...
}
如果未指定优先级,则执行顺序默认为定义的规则here
答案 1 :(得分:0)
ExceptionConversionAspect
必须是优先的第一个。
Java SE的完全工作示例(我只是模拟Java EE异常):
助手类:
package javax.validation;
public class ConstraintViolationException extends RuntimeException {
private static final long serialVersionUID = -8041265519275356912L;
public ConstraintViolationException(String arg0) {
super(arg0);
}
}
package com.myexample.validator.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Validate {}
package com.myexample.service;
public class InvalidServiceInputException extends RuntimeException {
public InvalidServiceInputException(String arg0, Throwable arg1) {
super(arg0, arg1);
}
}
示例驱动程序应用程序:
驱动程序应用程序由@Validate
注释并模拟服务 - 请参阅包名称。它循环遍历10个方法调用,捕获异常并将它们打印到标准输出,以便显示它们确实按照需要进行转换。
package com.myexample.service;
import com.myexample.validator.annotation.Validate;
@Validate
public class Application {
public void doSomething(int i) {
System.out.printf("Doing something #%d%n", i);
}
public static void main(String[] args) {
Application application = new Application();
for (int i = 0; i < 10; i++) {
try {
application.doSomething(i + 1);
}
catch (Exception e) {
System.out.println(e);
System.out.println(" cause: " + e.getCause());
}
}
}
}
<强>方面:强>
验证方面随机抛出ConstraintViolationException
用于演示目的。
package com.myexample.aspect;
import java.util.Random;
import javax.validation.ConstraintViolationException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class ValidateAspect {
private static final Random RANDOM = new Random();
@Around("execution(public !static * *(..)) && @within(com.myexample.validator.annotation.Validate)")
public Object validateMethodInvocation(ProceedingJoinPoint thisJoinPoint) throws Throwable {
Object result = thisJoinPoint.proceed();
if (RANDOM.nextBoolean())
throw new ConstraintViolationException("uh-oh");
return result;
}
}
异常转换方面现在有一个额外的@DeclarePrecedence
注释。
package com.myexample.aspect;
import javax.validation.ConstraintViolationException;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclarePrecedence;
import com.myexample.service.InvalidServiceInputException;
@Aspect
@DeclarePrecedence("ExceptionConversionAspect, *")
public class ExceptionConversionAspect {
@AfterThrowing(pointcut = "execution(* com.myexample.service..*(..))", throwing = "e")
public void convertServiceException(Exception e) {
if (e instanceof ConstraintViolationException) {
throw new InvalidServiceInputException("The service inputs failed validation", e);
}
}
}
控制台输出:
Doing something #1
Doing something #2
com.myexample.service.InvalidServiceInputException: The service inputs failed validation
cause: javax.validation.ConstraintViolationException: uh-oh
Doing something #3
com.myexample.service.InvalidServiceInputException: The service inputs failed validation
cause: javax.validation.ConstraintViolationException: uh-oh
Doing something #4
Doing something #5
Doing something #6
com.myexample.service.InvalidServiceInputException: The service inputs failed validation
cause: javax.validation.ConstraintViolationException: uh-oh
Doing something #7
Doing something #8
Doing something #9
Doing something #10