2012-04-17 84 views
3

我在我的web应用程序的服务层(根据this article)实施了JSR303 JavaBean验证。现在我想将所有验证异常(例如,javax.validation.ConstraintViolationException)转换为我的自定义异常。将JSR303 JavaBean验证异常转换为自定义异常

我创建每当一个例外是服务层抛出时调用的看点:

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

也许这将有助于为validateMethodInvocation方法打造方面 - 它将在例外通过该方法抛出触发或覆盖ValidateAspect所以它抛出适当的异常? – 2012-04-20 13:49:53

回答

0

当几个方面共享一个公共连接点时,您可以使用@DeclarePrecedence语句手动设置执行顺序。你的情况,你可以创建一个新的方面:

@Aspect 
@DeclarePrecedence("ValidateAspect, ExceptionConversionAspect") 
    public class SystemArchitecture { 
     // ... 
    } 

如果没有指定优先级,执行顺序默认的规则定义here

0

劳尔贝尔托内几乎是正确的,但并不完全。逻辑必须颠倒,ExceptionConversionAspect必须是第一个优先。对Java SE

完全工作示例(我只是模仿了Java EE除外):

Helper类:

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