3

현재 JSR 303 주석을 사용하는 메소드 유효성 검증을위한 최대 절전 유효성 검사기 지원을 사용하여 조사 중입니다. 초기 시도는 유효성 검사를 수행 한 프록시 (cglib를 사용하여 생성 된)로 리소스를 래핑하려고 시도했지만, 시도한 프록시 메소드가 매개 변수 주석을 복사하지 않는 것처럼 보입니다. 이를 사용하는 리소스 메소드는 매개 변수없이 호출됩니다.아파치 윙크 (JAX/RS)로 Hibernate (JSR 303) 메소드 검증을 구현할 수 있습니까?

How can I create a dynamic proxy in java that retains parameter annotations on methods?

프록시를 사용하지 않고 이런 일을 할 윙크의 요청 체인에 후크의 대안 메커니즘이 : 그 항목에 현재 열려 또 다른 질문이?

답변

4

RequestHandler을 만들고 실제로 HandlersFactory을 재정 의하여 요청 처리기가 포함 된 목록을 반환하면 부분적으로 지원되는 방법입니다. 이에 대한 구성은 here입니다. 이 요청 처리기는 호출 된 마지막 요청 처리기 인 InvokeMethodHandler 바로 앞에 요청 처리 체인에 삽입되며 이는 실제로 자원 메서드를 호출하는 요청 처리기입니다.

다음과 같이 (실제로 JAX/RS 자원을 호출)을 InvokeMethodHandler에 대한 소스 코드를 읽기를 바탕으로, 당신은 매개 변수, 인스턴스와 방법 매개 변수를 얻을 수 있습니다 :이 다소 해키

// Get Method Validator from hibernate 
    MethodValidator validator = Validation.byProvider(HibernateValidator.class).configure() 
      .buildValidatorFactory().getValidator().unwrap(
        MethodValidator.class); 

    // Extract the method parameters, object instance and method metadata from the JAX/RS internals. 
    Method javaMethod = null; 
    Object instance = null; 
    Object[] parameters = null; 
    SearchResult searchResult = context.getAttribute(SearchResult.class); 

    javaMethod = searchResult.getMethod().getMetadata() 
      .getReflectionMethod(); 

    parameters = searchResult.getInvocationParameters(); 
    instance = searchResult.getResource().getInstance(context); 

    // Use all this to perform validation... 
    Set<MethodConstraintViolation<Object>> violations = validator 
      .validateAllParameters(instance, javaMethod, parameters); 
    if (!violations.isEmpty()) { 
     // do something with the violations here 
    } 

등 그것은 (필자가 말할 수있는 한 문서화되지 않은) 윙크의 구현 세부 사항에 의존하여 인스턴스, 매개 변수 및 메타 데이터를 얻습니다 (이 정보를 얻으려는 대중적인 방법을 제공하면 좋을 것입니다). 그러나 프록시에서 발생하는 리플렉션으로부터 여러 오버 헤드를 추정하지 않기 때문에 프록시를 사용하는 것이 다소 바람직합니다.

2

EJB 인터셉터를 추가하여 윙크로 bean 유효성 검사를 수행 할 수있었습니다.

public class RestValidationException extends WebApplicationException { 

    List<String> validationErrors = new ArrayList<String>(); 

    public RestValidationException(Set<? extends ConstraintViolation<?>> violations) { 
     for(ConstraintViolation<?> constraintViolation : violations) { 
      String error = constraintViolation.getPropertyPath().toString() + ": " + constraintViolation.getMessage(); 
      validationErrors.add(error); 
     } 
    } 

    @Override 
    public Response getResponse() { 
     return Response.status(Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(validationErrors).build(); 
    } 
} 

지금 당신이 @Interceptors (ValidationInterceptor.class) 모든 매개 변수입니다으로 REST 자원에 주석을 가지고 꽤 출력 할

@Interceptor 
public class ValidationInterceptor { 

    Validator validator = Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory().getValidator(); 

    @AroundInvoke 
    public Object validate(InvocationContext ctx) throws Exception { 
     Object[] parameters = ctx.getParameters(); 
     Set<ConstraintViolation<Object>> validateResult = new HashSet<>(); 

     for (Object parameter : parameters) { 
      Set<ConstraintViolation<Object>> validateParam = validator.validate(parameter); 
      validateResult.addAll(validateParam); 
     } 
     if (!validateResult.isEmpty()) { 
      throw new RestValidationException(validateResult); 
     } 
     return ctx.proceed(); 
    } 
} 

사용자 정의 예외 : 여기에는 공급 업체로는 OpenJPA 검사기를 사용 메서드를 입력하기 전에 유효성이 검사됩니다. EJB를 사용하지 않는 경우 cglib의 MethodInterceptor를 사용하여 차단할 수 있습니다 (Spring에서 도움이 될 수 있음).