1️⃣ Passo: Tratando erros de validação simples
Objetivo: Tratar erros de validação e retornar uma resposta personalizada no formato JSON.
- Crie o
@RestControllerAdvice
para tratar exceções de validação.
Exemplo:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidationException(MethodArgumentNotValidException ex) {
List<FieldErrorResponse> fieldErrors = ex.getBindingResult().getFieldErrors()
.stream()
.map(error -> new FieldErrorResponse(error.getField(), error.getDefaultMessage()))
.collect(Collectors.toList());
return new ErrorResponse(List.of(), fieldErrors, fieldErrors.size());
}
}
- Crie a classe
ErrorResponse
eFieldErrorResponse
.
Exemplo:
public record ErrorResponse(
List<String> globalErrorMessages,
List<FieldErrorResponse> errors,
int numberOfErrors
) {}
public record FieldErrorResponse(String field, String message) {}
- Resultado de erro no formato JSON:
{
"globalErrorMessages": [],
"errors": [
{
"field": "email",
"message": "must not be blank"
}
],
"numberOfErrors": 1
}
2️⃣ Passo: Adicionando Mensagens de Erro com MessageSource
(Internacionalização)
Objetivo: Configurar internacionalização e personalizar as mensagens de erro.
- Crie o arquivo de mensagens
messages.properties
.
Exemplo (src/main/resources/messages.properties
):
error.notblank = O campo {0} não pode estar em branco.
error.invalid = O valor informado para {0} é inválido.
error.internal = Ocorreu um erro interno. Tente novamente mais tarde.
- Configure o
MessageSource
no Spring.
Criação da classe MessageSourceConfig
:
@Configuration
public class MessageSourceConfig {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.forLanguageTag("pt-BR"));
return localeResolver;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
}
- Uso do
MessageSource
no@RestControllerAdvice
para mensagens de erro personalizadas.
Modifique o código do @RestControllerAdvice
para usar o MessageSource
:
@RestControllerAdvice
public class GlobalExceptionHandler {
private final MessageSource messageSource;
public GlobalExceptionHandler(MessageSource messageSource) {
this.messageSource = messageSource;
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidationException(MethodArgumentNotValidException ex, Locale locale) {
List<FieldErrorResponse> fieldErrors = ex.getBindingResult().getFieldErrors()
.stream()
.map(error -> new FieldErrorResponse(
error.getField(),
messageSource.getMessage(error.getDefaultMessage(), new Object[]{error.getField()}, locale)
))
.collect(Collectors.toList());
return new ErrorResponse(List.of(), fieldErrors, fieldErrors.size());
}
}
- Resultado de erro internacionalizado em português (pt):
{
"globalErrorMessages": [],
"errors": [
{
"field": "email",
"message": "O campo email não pode estar em branco."
}
],
"numberOfErrors": 1
}
3️⃣ Passo: Tratando Exceções Genéricas com @ExceptionHandler(Exception.class)
Objetivo: Capturar qualquer exceção inesperada e retornar uma resposta personalizada.
- Adicione o tratamento de exceções genéricas para capturar erros não esperados.
Exemplo:
@RestControllerAdvice
public class GlobalExceptionHandler {
private final MessageSource messageSource;
public GlobalExceptionHandler(MessageSource messageSource) {
this.messageSource = messageSource;
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidationException(MethodArgumentNotValidException ex, Locale locale) {
List<FieldErrorResponse> fieldErrors = ex.getBindingResult().getFieldErrors()
.stream()
.map(error -> new FieldErrorResponse(
error.getField(),
messageSource.getMessage(error.getDefaultMessage(), new Object[]{error.getField()}, locale)
))
.collect(Collectors.toList());
return new ErrorResponse(List.of(), fieldErrors, fieldErrors.size());
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleGenericException(Exception ex) {
List<String> globalErrors = List.of("Ocorreu um erro inesperado. Contate o suporte.");
return new ErrorResponse(globalErrors, List.of(), 1);
}
}
- Resultado de erro genérico (quando ocorre uma exceção inesperada):
{
"globalErrorMessages": [
"Ocorreu um erro inesperado. Contate o suporte."
],
"errors": [],
"numberOfErrors": 1
}
4️⃣ Passo: Permitir a Troca de Idioma com Parâmetro na URL
Objetivo: Permitir que o idioma da aplicação seja alterado via parâmetro na URL.
- Adicione o
LocaleResolver
eLocaleChangeInterceptor
para permitir a troca de idioma.
Já configurado na classe MessageSourceConfig
:
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.forLanguageTag("pt-BR"));
return localeResolver;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
-
Testar a troca de idioma na URL:
- Requisição com idioma português:
GET /minha-rota?lang=pt
- Requisição com idioma inglês:
GET /minha-rota?lang=en
- Requisição com idioma português:
📌 Conclusão:
Agora você tem uma aplicação que:
- Captura erros de validação e os retorna no formato JSON personalizado.
-
Personaliza mensagens de erro usando internacionalização (
MessageSource
). - Captura exceções genéricas e retorna uma resposta consistente para erros inesperados.
- Permite trocar o idioma da aplicação dinamicamente via parâmetro na URL.
Esses passos podem ser expandidos conforme a necessidade de sua aplicação, mas com esses fundamentos, você já tem uma base sólida para tratar erros de maneira organizada, escalável e amigável ao usuário. 🚀
Top comments (0)