재_패캠Java/Spring - 6주차

하파타카·2023년 8월 14일
0

패캠JAVA, Spring과정

목록 보기
17/20

Spring MVC

redirect와 forward

redirect

클라이언트가 요청을 보내면 다른 곳으로 다시 요청을 보내게 하므로 요청 2번, 응답 2번이 된다.
=> 브라우저가 자동으로 재요청을 보내기 때문에 URL이 바뀜

forward

다른 페이지로 페이지가 자체적으로 forward요청을 보내기 때문에 클라이언트는 한번의 요청으로 한번의 응답을 받을 수 있다.
=> 브라우저의 내부에서 forward요청이 처리되기 때문에 URL이 바뀌지 않음

출처: https://goodgid.github.io/Redirect-vs-Forwarding/

@RequestMapping("/download")
public String download(HttpServletRequest request, 
					@RequestParam(required=false, defaultValue="") String type) {
	List<User> userList = getUserList();
    request.setAttribute("data", userList);
    
    if(type.equals("pdf")){
    	return "forward:/pdfView";
    } else if(type.equals("csv")){
    	return "forward:/csvView";
    }
    return "forward:/txtView";
}
  • 이름과 값의 쌍으로 구성된 작은 정보.
  • 아스키 문자만 가능.(한글은 URL인코딩 사용.)
  • 서버에서 생성 후 전송, 브라우저에 저장.
  • 정보의 유효기간이 있음. 유효기간 이후 자동 삭제.
  • 서버에 요청 시 domain, 하위경로를 포함한 path가 일치하는 경우에만 자동 전송.
  • 쿠키는 클라이언트를 구분하기 위한 기술임.

쿠키의 생성

Cookie cookie = new Cookie("id", "asdf");	// name이 id, value가 asdf인 쿠키 생성
cookie.setMaxAge(60*60*24);					// 유효기간 설정(초 단위)
response.addCookie(cookie);					// 응답에 쿠키 추가

쿠키의 변경

쿠키의 구분을 위해 name설정에 주의.

Cookie cookie = new Cookie("id", "");		// 변경할 쿠키와 같은 이름의 쿠키 생성
cookie.setValue(URLEncoder.encode("남궁성"));	 // 값 변경
cookie.setDomain("www.fastcampus.co.kr");	// 도메인의 변경
cookie.setPath("/ch2");						// 경로의 변경
cookie.setMaxAge(60*60*24*7);				// 유효기간의 변경
response.addCookie(cookie);					// 응답에 쿠키 추가

쿠키의 삭제

쿠키의 유효기간을 0으로 셋팅하면 됨.
쿠키의 구분을 위해 name은 중요하지만 value는 관계없음.

Cookie cookie = new Cookie("id", "");	// 변경할 쿠키와 같은 이름의 쿠키 생성
cookie.setMaxAge(0);				// 유효기간을 0으로 설정(삭제)
response.addCookie(cookie);					// 응답에 쿠키 추가

쿠키 읽어오기

Cookie[] cookies = request.getCookies();	// 쿠키 읽기

for(Cookie cookie : cookies) {
	String name = cookie.getName();
    String value = cookie.getValue();
    
    System.out.printf("[cookie]name=%s, value=%s%n", name, value);
}

쿠키가 2개 이상일 수 있으므로 배열로 반환받음. (이때 쿠키가 없으면 null값이 반환됨)

session

서로 관련된 요청들을 하나로 묶은 것 - 쿠키를 기반으로 하되 서버에 저장됨.
브라우저마다 개별 저장소(session객체)를 서버에서 제공.
key-value형태로 이루어진 map을 저장방식으로 사용함.

쿠키로 세션id를 보내면 서버에서 확인 후 응답헤더에 세션id를 보내고 다음 요청부터 둘의 id가 같으면 서버의 세션저장소를 사용할 수 있음.

세션속성
session = "true" : 세션이 없을 때 세션생성o
session = "false" : 세션이 없을 때 세션생성x
=> 세션이 이미 있을때 false를 준다고 있는 세션이 사라지지는 않고, 새로 만들지는 않는다는 의미.(=기존의 세션에 영향x)

cookie와 session의 차이점

쿠키(Cookie)세션(HttpSession)
브라우저에 저장서버에 저장
서버 부담 X서버에 부담 O
보안에 불리보안에 유리
서버 다중화에 유리서버 다중화에 불리

예외처리

Spring에서의 예외처리
1) 컨트롤러 메서드 내에서 try-catch로 처리
2) 컨트롤러의 @ExceptionHandler메서드가 처리
3) @ControllerAdvice클래스의 @ExceptionHandler메서드가 처리
4) 예외 종류별로 뷰 지정 - SimpleMappingExceptionResolver
5) 응답 상태 코드별로 뷰 지정 - <error-page>

@ExceptionHandler와 @ControllerAdvice

@ExceptionHandler 어노테이션을 이용해 예외처리 가능.

@Controller
public class ExceptionController {
	@ExceptionHandler(NullPointException.class)
    public String catcher2(Exception ex, Model m) {
    	m.addAttribute("ex", ex);
        return "error";
    }
    
    @ExceptionHandler(Exception.class)
    public String catcher(Exception ex, Model m) {
    	m.addAttribute("ex", ex)
        return "error";
    }
    
    @RequestMapping("/ex")
    public String main() throws Exception {
    	throw new Exception("예외가 발생했습니다.");
    }
    
    @RequestMapping("/ex2")
    public String main() throws Exception {
    	throw new NullPointException("예외가 발생했습니다.");
    }
}

=> try-catch문을 사용하듯이 메서드를 만들어 각 오류상황에 대응할 수 있도록 한다.
단, @ExceptionHandler 어노테이션을 통한 예외처리는 메서드가 속해있는 컨트롤러 내부의 오류에만 대응한다.
모든 컨트롤러에서의 오류에 대응하려면 핸들링 클래스를 만들어 클래스에 @ControllerAdvice어노테이션을 적용한다.
@ControllerAdvice : 전역에서의 오류를 잡아 처리하는 어노테이션. 특정 패키지만 지정하는것도 가능함. 예외 처리 메서드가 중복된 경우, 컨트롤러 내의 예외 처리 메서드가 우선됨.

참고링크 - @ControllerAdvice, @ExceptionHandler를 이용한 예외처리 분리, 통합하기

@ResponseStatus

응답 메시지의 상태 코드를 변경할 때 사용.

1) 예외 처리 메서드에서의 사용 : 예외처리에 성공했다면 예외상황임에도 상태코드 200(요청처리 성공)가 전송되므로 에러사항을 클라이언트에게 알리기 위해 사용됨.

@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler({NullPointerException.class, ClassCastExcepion.class})
public String catcher2(Exception ex, Model m){
    m.addAttribute("ex", ex);
	return "error";
}

클라이언트쪽 에러일때 4xx, 서버쪽 에러일때 5xx 등 상태코드를 지정하여 보여줌.

2) 사용자 정의 예외클래스에서의 사용 :

@ResponseStatus(HttpStatus.BAD_REQUEST)
class MyException extends RuntimeExcption {
    MyException(String msg){
    	super(msg);
    }
    MyException(){
    	this();
    }
}

DispatcherServlet

공통적인 전처리 과정에 사용됨.

DispatcherServlet의 요청처리과정

출처: https://velog.io/@hyunjong96/Sprin-Spring-MVC-DispatcherServlet

DispatcherServletController뿐만 아니라 서블릿과 같은 다양한 대상을 호출할 수 있도록 DispatcherServletController의 연결을 느슨하게 하기 위해 HandlerAdepter를 사용함.

서블릿의 Filter : 요청 전후의 전처리 및 후처리
스프링의 Intercepter : Filter보다 발전된 개념으로, 역할은 유사함.

데이터의 변환과 검증

WebDataBinder

타입 변환, 데이터 검증 작업을 함.
BindingResult에 결과를 저장하여 반환.(에러 발생시에도 에러라는 결과를 저장함.)
매개변수에 선언할때 반환 결과를 저장할 객체의 바로 뒤에 위치해야 한다.

PropertyEditor

양방향 타입 변환 (String → 타입, 타입 → String)
특정 타입이나 이름의 필드에 적용 가능.

  • default PropertyEditor : Spring이 기본적으로 제공
  • custom PropertyEditor : 사용자가 직접 구현. PropertyEditorSupport를 상속하면 필요한 메서드만 오버라이딩 하면 되므로 편리함.

Converter와 ConverterService

Converter

단방향 타입 변환(타입A → 타입B)
PropertyEditor의 단점을 개선(stateful → stateless)
싱글톤으로 사용가능.

ConverterService

타입 변환 서비스를 제공.
여러 Converter를 등록 가능.
WebDataBinderDefaultFormattingConversionService가 기본 등록.
모든 컨트롤러 내에서의 변환 : ConfigurableWebBindingInitializer를 설정하여 사용.
특정 컨트롤러 내에서의 변환 : 컨트롤러에 @InitBinder가 붙은 메서드를 작성.

Fomatter

양방향 타입 변환 (String → 타입, 타입 → String)
바인딩할 필드에 적용 : @NumberFormat, @DateTimeFormat

@DateTimeFormat

entity클래스에서 필드를 지정할때 @DateTimeFormat어노테이션을 이용하면 입력받은 문자열을 Date타입으로 변환하기에 편리함.

@DateTimeFormat(pattern="yyyy/MM/dd")
private Date birth;

@NumberFormat(pattern="###,###")
BigDecimal salary;
}

=> "2023/08/16"형태의 문자열을 Date타입으로 변환, 천 단위마다 콤마가 붙은 문자열을 숫자형으로 변환.

Validator

객체를 검증하기 위한 인터페이스.
객체 검증기(validator) 구현에 사용함.

글로벌 Validator

하나의 Validator로 여러 객체를 검증할 때, 글로벌 Validator로 등록.

1) 글로벌 Validator로 등록하는 방법
- Servlet-constext.xml -

<annotation-driven validator="globalValidator"/>
<beans:bean id="globalValidator" class="com.fastcampus.ch2.GlobalValidator"/>	// 빈 등록

2) 글로벌 Validator와 로컬 Validator를 동시에 적용하는 방법

@InitBinder
public void toDate(WebDataBinder binder) {
	SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
    binder.registerCustomEditor(Date.class, new CustomDateEditor(df, false));
    
    binder.addValidators(new UserValidator());	// 로컬 validator를 WebDataBinder에 등록
    // 신규등록이 아닌 추가등록이기 때문에 setValidator()가 아니라 addValidators()를 사용해야 함
}
profile
천 리 길도 가나다라부터

0개의 댓글