[Spring] 날짜 값 변환, @PathVariable, 익셉션 처리

Fortice·2021년 3월 6일
0

Spring

목록 보기
12/13
post-thumbnail

날짜 값 변환

1. 자바 시간 API

java.util.Date > java.util.Calendar > java.time(org.joda.time)

2. 시간 타입

  • LocalDate : 날짜 정보만 필요할 떄 사용
    • 기본 결과 2020-03-03
LocalDate currentDate = LocalDate.now();
LocalDate targetDate = LocalDate.of(2020,03,03);
  • LocalTime : 시간 정보만 필요할 때 사용
    • 기본 결과 : 14:22:33
LocalTime currentTime = LocalTime.now();   
LocalTime targetTime = LocalTime.of(14,22,33,22); 
// 끝에 4번째 매개변수는 nanoSecond로 Optional이다.
// 14:22:33.0000022
  • LocalDateTime : 날짜와 시간 정보 모두가 필요할 때 사용
    • 기본 결과 : 2020-03-03T14:30:30.388
LocalDateTime currentDateTime = LocalDateTime.now(); 

LocalDateTime targetDateTime = LocalDateTime.of(2019, 11, 12, 12, 32,22,3333);
// second,nanoSecond 매개변수는 필수가 아닌 선택
// 2020-03-03T14:32:22.000003333

3. @DateTimeFormat

@DateTimeFormat 어노테이션으로 스트링값을 DATETIME 포맷으로 변환하여 쉽게 객체에 입력 가능

아래의 코드는 "2020030314"의 문자열을 "2020년 3월 3일 14시" 값을 가지는 LocalDateTime 객체로 변환해준다.

public class DateCommand {
    @DateTimeFormat(pattern = "yyyyMMddHH")
    private LocalDateTime from;
    @DateTimeFormat(pattern = "yyyyMMddHH")
    private LocalDateTime to;
}

만약 패턴에 맞지 않는 String을 입력 시 에러가 발생한다.

4. 변환 처리 : WebDataBinder

이런 형식에 대한 변환 처리는 WebDataBinder가 맡는다.

WebDataBinder는 이러한 날짜 변환 처리, 요청 파라미터-커맨드 객체 사이의 변환 처리 등 다양한 변환 처리를 한다.

이 처리는 직접 하지 않고, DefaultFormattingConversionService에 역할을 위임하여 처리한다.

Path Variable 처리

1. Query String vs Path Variable

특정 id값에 대한 요청을 할 때 두 가지 방식으로 id 값을 넘길 수 있다.

  • Query String
    • "/users?id=3"
  • Path Variable
    • "/users/3"

이러한 방식은 REST API에 대한 이해를 통해 알 수 있다. 두 방식은 어디에 어떤 데이터(명사)를 요청하는 것인지 명확하게 정의하기 위해 사용한다.

어떤 자원(데이터)의 위치를 특정해서 보여줘야 할 경우 Path variable을 쓰고, 정렬하거나 필터해서 보여줘야 할 경우에 Query parameter를 쓴다.

아래는 그 예시로, 전체 리스트나 리스트 중 특정 부분을 필터링 할 경우 Query String을 쓰고, 특정 id값만 조회할 때 Path Variable을 쓰기로 약속하여 사용한다.

/users # Fetch a list of users
/users?occupation=programer # Fetch a list of programer user
/users/123 # Fetch a user who has id 123

위와 같은 방식으로 어디에 어떤 데이터(명사)를 요청하는 것인지 명확하게 정의하게 되고, 어떤 행위를 할 지는 GET, POST, PUT, DELETE 같은 메소드들을 통해 정의한다.

2. Spring에서 Path Variable 처리

Path Variable 값을 처리하기는 쉽다. 요청 Mapping Url에 {name}형식으로 지정을 하고, 메소드 파라미터에 @PathVariable("name")으로 정의를 해주면된다. 기본적으로 String으로 받지만, 아래와 같은 경우 Long으로 자동 형변환을 해준다.

@GetMapping("/members/{id}")
public String profile(@PathVariable("id") Long memId, Model model) {
    System.out.Pringln(memId);
    Member member = memberDao.selectById(memId);
}

컨트롤러 익셉션 처리

1. @ExceptinalHandler

@ExceptinalHandler 어노테이션을 적용한 메서드를 통해 컨트롤러에서 익셉션을 처리할 수 있다.

@Controller
public class MemberDetailController {

	...(생략)

	@ExceptionHandler(TypeMismatchException.class)
	public String handleTypeMismatchException() {
		return "member/invalidId";
	}

	@ExceptionHandler(MemberNotFoundException.class)
	public String handleNotFoundException() {
		return "member/noMember";
	}
}

메소드 단에 어노테이션을 적용시키고 어노테이션의 파라미터로 적용할 익셉션을 넣으면 된다. 위 코드는 Long 형식을 받아야하는데 형 변환이 불가능한 "a" 같은 String 값이 들어올 경우 TypeMismatch 익셉션과, Member를 찾을 수 없을 경우의 익셉션을 처리한 코드이다.

2. 공통 익셉션 처리(@ControllerAdvice)

Validator나, 인터셉터 처럼 컨트롤러 범위를 지정하여 적용할 수 있다.

이 경우 클래스를 만들고 어노테이션을 적용해 범위를 지정하여 공통 익셉션을 처리할 수 있다.


@ControllerAdvice("spring") // 범위 지정
public class CommonExceptionHandler {

	@ExceptionHandler(RuntimeException.class)
	public String handleRuntimeException() {
		return "error/commonException";
	}
}

범위는 @ControllerAdvice어노테이션의 파라미터에 패키지를 지정해주면 된다.

3. 익셉션 처리의 중복

컨트롤러별 지정 익셉션 처리, 공통 익셉션 처리에 따라 익셉션이 중복되는 경우가 발생할 수 있다. 이 경우 아래의 순서를 따라 먼저 찾아지는 익셉션 처리를 진행한다.

  1. 같은 컨트롤러에 위치한 @EceptionHandler 메서드 중 해당 익셉션을 처리할 수 있는 메서드 검색
  2. 같은 클래스에 위치한 메서드가 익셉션을 처리할 수 없을 경우 @ControllerAdvice 클래스에 위치한 @ExceptionHandler 메서드를 검색

즉 컨트롤러 범위 -> 공통 범위 순으로 찾게 된다.

4. @ResponseStatus

@ResponseStatus 어노테이션을 통해 원래 에러에 해당하는 상태코드와 이유를 원하는 상태코드와 이유로 변경할 수 있다.

에러 뿐만 아니라 Http 통신 모두에 사용 가능하다.

@Controller
public class MemberDetailController {

	...(생략)

	@ExceptionHandler(TypeMismatchException.class)
        @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "My DataFormat Exception")
	public String handleTypeMismatchException() {
		return "member/invalidId";
	}

	@ExceptionHandler(MemberNotFoundException.class)
	public String handleNotFoundException() {
		return "member/noMember";
	}
}
profile
서버 공부합니다.

0개의 댓글