15 de agosto de 2026 • Java

09 - Spring Handlers de Exceção e Controller Advice

Forma Tradicional de Lidar com Exceções

Em uma aplicação Spring básica, as exceções são frequentemente tratadas diretamente dentro dos métodos do controller usando blocos try-catch.

Exemplo:

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public User findById(@PathVariable Long id) {

        try {
            return userService.findById(id);
        } catch (UserNotFoundException ex) {
            throw new ResponseStatusException(
                    HttpStatus.NOT_FOUND,
                    ex.getMessage()
            );
        }
    }
}

Problemas com essa abordagem

  • Código repetido em múltiplos controllers.
  • Difícil de manter.
  • A lógica de negócio se mistura com o tratamento de erros.
  • Respostas de erro inconsistentes.
  • Viola o princípio da Separação de Preocupações (Separation of Concerns).

À medida que a aplicação cresce, essa abordagem se torna difícil de gerenciar.


Exception Handler

Spring oferece a anotação @ExceptionHandler para centralizar o tratamento de exceções dentro de um controller.

Exemplo:

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public User findById(@PathVariable Long id) {
        return userService.findById(id);
    }

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handleUserNotFound(
            UserNotFoundException ex) {

        return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(ex.getMessage());
    }
}

Como funciona

Quando uma UserNotFoundException é lançada:

  1. Spring procura por um @ExceptionHandler.
  2. O método handler correspondente é executado.
  3. Uma resposta HTTP personalizada é retornada.

Vantagens

  • Remove blocos try-catch dos métodos do controller.
  • Código do controller mais limpo.
  • Tratamento de exceções centralizado dentro de um controller.
  • Manutenção mais fácil.

Limitação

O exception handler funciona apenas para o controller onde foi declarado.

Se você tiver múltiplos controllers, pode acabar duplicando o mesmo código de tratamento de exceções.


Necessidade de Controller Advice e Implementação

Para evitar a duplicação de exception handlers em vários controllers, Spring oferece a anotação @ControllerAdvice.

@ControllerAdvice atua como um exception handler global para todos os controllers na aplicação.

Por que usar Controller Advice?

Sem @ControllerAdvice:

UserController
 └── @ExceptionHandler(UserNotFoundException)

ProductController
 └── @ExceptionHandler(UserNotFoundException)

OrderController
 └── @ExceptionHandler(UserNotFoundException)

O mesmo código é repetido várias vezes.

Com @ControllerAdvice:

GlobalExceptionHandler
 └── @ExceptionHandler(UserNotFoundException)

UserController
ProductController
OrderController

Um único handler atende a toda a aplicação.


Exemplo de Implementação

Exceção Personalizada

public class UserNotFoundException extends RuntimeException {

    public UserNotFoundException(String message) {
        super(message);
    }
}

Global Exception Handler

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handleUserNotFound(
            UserNotFoundException ex) {

        return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(ex.getMessage());
    }
}

Controller

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public User findById(@PathVariable Long id) {
        return userService.findById(id);
    }
}

Quando a exceção é lançada:

throw new UserNotFoundException("User not found");

Spring automaticamente direciona a exceção para o handler global.

Resposta:

HTTP/1.1 404 Not Found

User not found

Retornando uma Resposta de Erro Personalizada

Em vez de retornar uma string simples, é comum retornar uma resposta JSON estruturada.

DTO de Erro

public record ErrorResponse(
        String message,
        int status,
        LocalDateTime timestamp) {
}

Handler

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleUserNotFound(
            UserNotFoundException ex) {

        ErrorResponse error = new ErrorResponse(
                ex.getMessage(),
                HttpStatus.NOT_FOUND.value(),
                LocalDateTime.now()
        );

        return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(error);
    }
}

Resposta:

{
  "message": "User not found",
  "status": 404,
  "timestamp": "2026-07-27T20:30:00"
}

@ControllerAdvice vs @RestControllerAdvice

@ControllerAdvice

Usado para aplicações MVC e pode retornar:

  • Views
  • Objetos Model
  • ResponseEntity
@ControllerAdvice
public class GlobalExceptionHandler {
}

@RestControllerAdvice

Combinação de:

@ControllerAdvice
@ResponseBody

Recomendado para APIs REST porque as respostas são automaticamente serializadas para JSON.

@RestControllerAdvice
public class GlobalExceptionHandler {
}

Resumo

AbordagemScopeRecommended
Try-Catch no ControllerMétodo único❌ Não
@ExceptionHandlerController único⚠️ Pequenas aplicações
@ControllerAdviceMúltiplos controllers✅ Sim
@RestControllerAdviceAPIs REST✅ Melhor Prática

Boas Práticas

  • Crie exceções personalizadas para cenários de negócio.
  • Lance exceções da camada de serviço.
  • Lide com exceções globalmente usando @RestControllerAdvice.
  • Retorne respostas de erro JSON padronizadas.
  • Mantenha os controllers focados no processamento de requisições e fluxo de negócio.
  • Evite duplicar a lógica de tratamento de exceções em vários controllers.
  • Inclua informações úteis nas respostas de erro, como:
    • Mensagem de erro
    • Código de status HTTP
    • Timestamp
    • Caminho da requisição (opcional)
    • Código de erro (opcional)

Para APIs REST modernas com Spring Boot, @RestControllerAdvice combinado com @ExceptionHandler é a abordagem recomendada para um tratamento de exceções centralizado e de fácil manutenção.

← Voltar para o blog