Spring filter throws custom exception

2019-07-30 12:23发布

问题:

I have a controller advice that handle all validation exception thrown by my application as below.

@RestControllerAdvice
public class RestApiExceptionController {

    @ExceptionHandler(ValidationErrorException.class)
    public ResponseEntity<?> appNotFoundException(ValidationErrorException exception) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body(new ErrorResponse(exception.getErrorCode(), exception.getMessage())); 
    }
}

In my way, I would like to create a filter that will make validation to every request and throw custom exception when necessary. But the thing is that I cannot throw custom exception as show below.

public class ValidationFilter implements Filter {
    ...
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        throw new ValidationErrorException(); // This is impossible
    }
    ...
}

How can I throw the ValidationErrorException in this case or there are other better ways to handle such task.

回答1:

The validations are generally done on the request objects which are in general available in Controller layer after they are transformed from request format to server processing format. e.g. JSON to Java object.

So the validation should be performed or triggered on Controller layer once the request is reached by completing your entire filter chaining.

Any validation exception thrown then later on can be handled in your following handler,

@RestControllerAdvice
public class RestApiExceptionController {

    @ExceptionHandler(ValidationErrorException.class)
    public ResponseEntity<?> appNotFoundException(ValidationErrorException exception) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body(new ErrorResponse(exception.getErrorCode(), exception.getMessage())); 
    }
}

The very much one of the purpose of filters is,

To intercept requests from a client before they access a resource at back end.

So filters in real don't have the actual resource yet to be validated. They are available once the control reaches to correct component and in your case it is Controller.

So better approach is not to do any resource based validations at filter components.