Spring boot ExceptionHandler, когда исключение выдается в сервисе - PullRequest
0 голосов
/ 18 февраля 2020

Я использую ControllerAdvice для обработки исключений в моем приложении с весенней загрузкой.

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class ErrorApiHandler extends ResponseEntityExceptionHandler {

    final
    ResponsesHelper rh;

    public ErrorApiHandler(ResponsesHelper rh) {
        this.rh = rh;
    }

    @ExceptionHandler(UsernameNotFoundException.class)
    public ResponseEntity<Object> handleUsernameNotFoundException(UsernameNotFoundException ex) {
    log.error(ExceptionUtils.getStackTrace(ex));

    var error = buildError(ex);
    return rh.buildResponse(error, HttpStatus.NOT_FOUND);
    }
...
}

Он отлично работает для исключений, возникающих в моих контроллерах. Однако, за исключением исключений, например, внутри службы, ControllerAdvice не выполняется.

@Service
public class CustomUserDetailsService implements UserDetailsService {

    final
    UserRepository userRepository;

    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    @Transactional
    public User loadUserByUsername(String email)
            throws UsernameNotFoundException {

        log.debug(String.format("Loading user %s", email));

        User user = userRepository.findByEmail(email)
                .orElseThrow(() -> {

                    log.debug(String.format("User %s not found", email));
                    return new UsernameNotFoundException("User not found : " + email); // <- This exception is not handled.
                });

        log.debug(String.format("User %s loaded", user));
        return user;
    }

Как мне обработать все исключения, созданные в моем приложении?

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 18 февраля 2020

Я нашел это в документах ResponseEntityExceptionHandler:

Удобный базовый класс для классов @ControllerAdvice, который sh обеспечивает централизованную обработку исключений во всех методах @RequestMapping с помощью методов @ExceptionHandler.

Кажется, что пользовательский обработчик исключений, расширяющий этот класс, будет обрабатывать только исключения на уровне контроллера.

Я нашел этот урок - решение, использующее HandlerExceptionResolver, звучит как тот, который вы ищете.

0 голосов
/ 18 февраля 2020

В моем случае мой «CustomUserDetailsService» вызывается внутри фильтра:

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenProvider tokenProvider;

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain
        ) throws ServletException, IOException {

        try {
            String jwt = getJwtFromRequest(request);

            if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
                UUID userId = tokenProvider.getUserIdFromJWT(jwt);

                UserDetails userDetails = customUserDetailsService.loadUserById(userId);
...

Я обработал его, поймав там исключения:

catch (UsernameNotFoundException ex){
            log.error(ExceptionUtils.getStackTrace(ex));

            var apiError = ErrorApiHandler.buildError(
                    new ResourceAlreadyTakenException(ex.getMessage())
            );

            response.addHeader("Content-Type", "application/json");
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            PrintWriter writer = response.getWriter();
            writer.write(convertObjectToJson(apiError));
            writer.flush();
            return;
        }

В идеале обработать все исключения с помощью совет контроллера, но так работает

0 голосов
/ 18 февраля 2020

@ControllerAdvice предназначен для обработки исключений, которые распространяются через методы контроллера (которые вызываются из вызовов методов контроллера - включая исключения пузырькового типа). Таким образом, всякий раз, когда вы напрямую генерируете исключения в вашем методе контроллера или что-то, что вызывает метод контроллера, генерирует исключение, будет сделана попытка обработать его с помощью совета.

Если вы хотите, чтобы ваши исключения обрабатывались (как-то) вне веб-контекста аналогичным образом, вам придется написать собственный аспект, который буквально обернет все try-catch и позволит вам обработать исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...