Spring 날짜, 경로변수, 컨트롤러 익셉션

김정훈·2024년 7월 15일

Spring

목록 보기
13/24

1. 날짜 값 변환

@DateTimeFormat

  • LocalDate, LocalTime, LocalDateTime ..
  • 형식이 일치 하지 않으면 예외 발생 (메세지 코드 typeMismatch)
  • @DateTimeFormat을통해 형식을 알려줘야지 예외없이 작동.
@Slf4j
@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {
    @GetMapping("/list")
    public String list(@ModelAttribute MemberSearch search){
        log.info(search.toString());
        return "member/list";
    }
}

MemberSearch

@Data
public class MemberSearch {
    @DateTimeFormat(pattern="yyyyMMdd")
    private LocalDate sDate; // 검색 시작일
    @DateTimeFormat(pattern="yyyyMMdd")
    private LocalDate eDate; // 검색 종료일
}

사용자에게 에러를 보여주기
MemberController

@GetMapping("/list")
public String list(@Valid @ModelAttribute MemberSearch search, Errors errors){
    log.info(search.toString());
    return "member/list";
}

list.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<h1>회원목록</h1>
<form:form method="get" autocomplete="off" modelAttribute="memberSearch">
    가입일
    <form:input path="sDate" />
    <form:errors path="sDate"/>
    ~
    <form:input path="eDate" />
    <form:errors path="eDate"/>
    <button type="submit">검색하기</button>
</form:form>

validations.properties

typeMismatch.java.time.LocalDate=날짜 형식이 아닙니다(예 - 20240716).

2. @PathVariable : 경로 변수

@Slf4j
@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {

    @ResponseBody
    @GetMapping({"/info/{id}/{id2}", "/info/{id}"}) //경로변수, 여러개도 가능.
    public void info(@PathVariable("id") String email, @PathVariable(value = "id2", required = false) String email2){
        log.info("email: {}, email2: {}", email, email2);
    }

}

웹브라우저에서 입력된 url주소가 경로변수로 유입됨.

3. 컨트롤러 익셉션 처리하기

1) @ExceptionHandler

  • 발생 예외를 정의
  • 예외발생시 특정 페이지를 노출
  • 메서드에 자동 주입
    • 발생한 예외 객체
    • Model
    • HttpServletRequest
    • HttpServletResponse
    • HttpSession

한 예외만 처리

MemberController

//BadRequestException이 발생하면 처리, 그 외 예외는 처리되지않는다.
@ExceptionHandler(BadRequestException.class)
public String errorHandler(BadRequestException e){
    e.printStackTrace();
 return "error/common";
}

다중 예외 처리

//다중으로 에러 처리가 가능
@ExceptionHandler({BadRequestException.class, RuntimeException.class})
public String errorHandler(BadRequestException e, HttpServletRequest request, HttpServletResponse response, Model model){
    e.printStackTrace();
 return "error/common";
}

모든 예외 처리

//Exception.class으로 다형성을 통해 모든 예외를 처리 할 수도 있다.
@ExceptionHandler(Exception.class)
public String errorHandler(BadRequestException e, HttpServletRequest request, HttpServletResponse response, Model model){
    e.printStackTrace();
 return "error/common";
}

스프링부트에서 추가된 속성

status : HTTP 상태 코드
error : 에러코드
path :예외 발생한 URI
exception :
message :
timestamp : 예외 발생한 시간

2) @ControllerAdvice

특정 패키지 범위의 컨트롤러에 공통적인 예외처리 등 수행

@ModelAttribute : 공통 값 유지
@ExcptionHandler : 공통 에러 페이지 처리

컨트롤러에서 작성된 ExceptionHandler는 member에서만 예외처리를 한다.
모든 컨트롤러에서 공통적으로 처리하기위해서는 @ControllerAdvice사용한다.
@ControllerAdvice는 컨트롤러보다 우선순위가 더 낮음.

@Slf4j
@ControllerAdvice("org.choongang")
public class CommonControllerAdvice {

    @ExceptionHandler(Exception.class)
    public String errorHandler(BadRequestException e, HttpServletRequest request, HttpServletResponse response, Model model){
        e.printStackTrace();
        log.info("advice에서 유입");
        return "error/common";
    }
}

3) 상태코드

위 코드로 에러처리를 하면 웹페이지에서는 200상태코드를 받게된다.
예외에 해당하는 상태코드를 보여줘야하기 때문에 아래 같이 한다.
기본적으로 예외에는 상태코드가 없기 때문에, 기본에러는 500으로 처리하고, 커스텀예외인 CommonException에 해당하는 에러는 400으로 처리한다. CommonException에 해당하는 예외인지 확인하기 위해 instaceof()메서드를 사용하여 해당하는지 확인한다.
또한 반환값을 ModelAndView자료형으로 지정해서 setStatus()메서드를 통해 상태코드를 설정하고 반환한다.

@Slf4j
@ControllerAdvice("org.choongang")
public class CommonControllerAdvice {

    @ExceptionHandler(Exception.class)
    public ModelAndView errorHandler(Exception e, HttpServletRequest request, HttpServletResponse response, Model model){
        e.printStackTrace();
        log.info("advice에서 유입");
        // 기본 HTTP 상태 코드를 INTERNAL_SERVER_ERROR(500)으로 설정
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; //500
        
        // 발생한 예외가 CommonException 타입인 경우 해당 예외의 상태 코드를 사용
        if(e instanceof CommonException commonException){
            //CommonException commonException = (CommonException) e;
            status = commonException.getStatus();
        }
        ModelAndView mv = new ModelAndView();
        mv.setStatus(status);
        mv.setViewName("error/common");
        return mv;
    }
}

profile
안녕하세요!

0개의 댓글