ExceptionHandlerFilter 구현
ExceptionHandlerFilter는 Spring Security 필터 체인의 일부로서, 요청 처리 중 발생하는 예외를 잡아 처리합니다. 이 필터를 통해 UsernameFromTokenException과 같은 인증 관련 예외뿐만 아니라, RuntimeException 및 기타 예외에 대한 처리도 일관되게 관리할 수 있습니다.
package com.myshop.global.filter;
import com.myshop.global.exception.UsernameFromTokenException;
import com.myshop.global.exception.handler.ErrorDetailResponse;
import com.myshop.global.exception.handler.ErrorResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Component
public class ExceptionHandlerFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try{
filterChain.doFilter(request,response);
} catch (UsernameFromTokenException ex){
log.info("UsernameFromTokenException handler filter");
setErrorResponse(HttpStatus.FORBIDDEN,response,ex);
} catch (RuntimeException ex){
log.info("RuntimeException exception handler filter");
setErrorResponse(HttpStatus.FORBIDDEN,response,ex);
} catch (Exception ex){
log.info("Exception exception handler filter");
setErrorResponse(HttpStatus.FORBIDDEN,response,ex);
}
}
public void setErrorResponse(HttpStatus status, HttpServletResponse response,Throwable ex){
response.setStatus(status.value());
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
ErrorResponse errorResponse = new ErrorResponse(new ErrorDetailResponse(ex.getMessage()));
}
}
사용자 정의 예외 클래스
BadRequestException과 UsernameFromTokenException과 같은 사용자 정의 예외 클래스를 구현하여, 애플리케이션에서 발생할 수 있는 특정한 에러 상황을 명확하게 표현합니다.
BadRequestException
package com.myshop.global.exception;
import lombok.Getter;
@Getter
public class BadRequestException extends RuntimeException {
public BadRequestException(String message) {
super(message);
}
}
UsernameFromTokenException
package com.myshop.global.exception;
public class UsernameFromTokenException extends RuntimeException{
public UsernameFromTokenException(String message){
super(message);
}
}
GlobalExceptionHandler 설정
GlobalExceptionHandler는 @RestControllerAdvice를 사용하여 정의되며, 애플리케이션에서 발생하는 다양한 예외를 처리합니다. 이 클래스에서는 BadRequestException을 처리하는 메소드를 구현하여, 에러 발생 시 사용자에게 HTTP 상태 코드와 에러 메시지를 담은 응답을 반환합니다.
GlobalExceptionHandler
package com.myshop.global.exception.handler;
import com.myshop.global.exception.BadRequestException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.Arrays;
import java.util.Optional;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 사용자 정의 예외처리
*/
@ExceptionHandler(BadRequestException.class)
protected ResponseEntity<?> handleBadRequestException(BadRequestException e) {
String message = Optional.ofNullable(e.getMessage()).orElseGet(() -> "올바른 요청이 아닙니다. ");
ErrorDetailResponse detailResponse = ErrorDetailResponse.builder().msg(message).build();
ErrorResponse response = ErrorResponse.builder()
.errors(Arrays.asList(detailResponse))
.build();
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}
}
ErrorDetailResponse 및 ErrorResponse 클래스
에러 응답을 구성하는 ErrorDetailResponse와 ErrorResponse 클래스를 구현하여, 에러 정보를 명확하게 구조화하여 반환합니다.
ErrorDetailResponse
package com.myshop.global.exception.handler;
import lombok.Builder;
import lombok.Getter;
@Getter
public class ErrorDetailResponse {
private String msg;
@Builder
public ErrorDetailResponse(String msg) {
this.msg = msg;
}
}
ErrorResponse
package com.myshop.global.exception.handler;
import lombok.Builder;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
@Getter
public class ErrorResponse {
private List<ErrorDetailResponse> errors;
@Builder
public ErrorResponse(List<ErrorDetailResponse> errors) {
this.errors = errors;
}
public ErrorResponse(ErrorDetailResponse error) {
this.errors = Arrays.asList(error);
}
}
결론
GlobalExceptionHandler와 필터를 통한 예외 처리 방식을 도입함으로써, 애플리케이션의 에러 처리를 중앙에서 관리할 수 있게 되며, API 사용자에게 보다 일관되고 명확한 에러 응답을 제공할 수 있습니다. 이는 애플리케이션의 안정성과 사용자 경험을 모두 향상시키는 중요한 요소입니다.
'프로젝트 (Java) > 예약마켓' 카테고리의 다른 글
[프로젝트] 8. 로그인 기능 구현 (0) | 2024.01.25 |
---|---|
[프로젝트] 7. 회원가입 기능 구현 (0) | 2024.01.25 |
[프로젝트] 5. JWT(Jason Web Tokens)와 Spring Security 적용 (1) | 2024.01.25 |
[프로젝트] 4. ERD(Entity Relationship Diagram)와 API 문서 작성 (0) | 2024.01.25 |
[프로젝트] 3. Docker Compose를 활용한 로컬 개발 환경 구축 (0) | 2024.01.24 |