2012-04-17 64 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