일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 정보보안기사
- 해킹
- wargame
- 정보처리기사 실기
- LOB
- webhacking
- Buffer Overflow
- 워게임
- 웹해킹
- 정보보안기사 실기
- SQL
- Spring MVC
- Pwnable.kr
- Spring Framework
- BOF
- Spring
- pwnable
- system hacking
- Lord of BOF
- webhacking.kr
- 네트워크
- Payload
- hacking
- PWN
- Shell code
- Operating System
- System
- stack overflow
- 운영체제
- OS
- Today
- Total
DongDD's IT
[Spring] Spring Web Application, Controller, Exception Handler 본문
[Spring] Spring Web Application, Controller, Exception Handler
DongDD 2019. 4. 2. 21:04[Spring] Spring Web Application
Web Application
종류
1. 화면으로 응답하는 어플리케이션
- jsp 등을 이용해 클라이언트에게 동적 웹 페이지 형태로 응답
2. 데이터로 응답하는 어플리케이션
- JSON, xml을 사용해 데이터 형태로 클라이언트에 응답
- RESTful API
Controller
처리
1. 선언형 처리
- method 시그니처를 참조해서 front controller가 하는 일
- 요청 매핑, 요청 데이터 취득, 입력값 검증
2. 프로그래밍형 처리
- controller 클래스의 method 안에 하는 일
- 입력값 검증 확인, 비즈니스 로직 호출, 이동대상 확인/데이터 연계/지정
Controller 작성
1 2 3 4 | @Controller public class TestController { } | cs |
- @Controller로 controller 지정
-> @ComponentScan을 통해 DI 컨테이너에 빈으로 등록(Boot에서는 자동)
Component Scan
1 2 3 4 5 6 | @Configuration @EnableWebMvc @ComponentScan(basePackages = "com.mvc") public class WebMvcConfig implements WebMvcConfigurer { } | cs |
- @ComponentScan("package_path")를 설정하여 Controller로 지정된 bean을 탐색하게 함
Handler Method
1 2 3 4 5 6 7 | @Controller public class TestController { @RequestMapping(path = "/", method = RequestMethod.GET) public String main() { return "index"; } } | cs |
- @RequestMapping으로 메소드를 지정하여 handler method로 인식하게 함
1. Annotation 종류
1) @PathVariable
- URI에 있는 변수 값을 가져옴
2) @RequestParam
- 요청 파라미터 값을 가져옴
3) @RequestHeader
- 요청 헤더 값을 가져옴
4) @RequestBody
- 요청 Body 값을 가져옴
5) @CookieValue
- 쿠키 값을 가져옴
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Controller public class AnnoController { @RequestMapping(path ="/anno/{urlInput}", method = RequestMethod.GET) public void anno(@PathVariable String urlInput, @RequestHeader HttpHeaders requestHeaders, @RequestBody String requestBody, @RequestParam("a") int a, @RequestParam("b") String b) { System.out.println(urlInput); System.out.println(requestHeaders.getHost()); System.out.println(a); System.out.println(b); } } | cs |
- brace로 경로에 변수를 넣고 @PathVariable을 이용해 값을 가져옴
- @RequestBody 같은 경우, 일반적으로 객체를 생성하여 받음(String도 가능함)
- @RequestHeader는 HttpHeaders를 사용하여 data 사용
- @RequestParam은 받을 parameter를 명시하고 데이터로 받음
- 결과
2. 반환 값
1) Type
- String : View 이름 반환
- Model : 데이터 반환
- ModelAndView : View 이름과 데이터 반환
- void : Response 객체에 데이터를 쓰거나 view 이름을 결정할 때 사용
- ResponseEntity : 응답 헤더와 본문에 직렬화될 객체 반환
- HttpHeaders : 응답 헤더 반환
2) Annotation
- @ModelAttribute : Model에 저장한 객체 반환
- @ResponseBody : 응답 본문에 직렬화한 객체 반환
ex)
1 2 3 4 5 6 7 8 | @RequestMapping(path ="/anno/{urlInput}", method = RequestMethod.GET) @ResponseBody public String anno(@PathVariable String urlInput, @RequestHeader HttpHeaders requestHeaders, @RequestParam("a") int a, @RequestParam("b") String b) { return urlInput; } | cs |
- handler에 requestmapping 지정 후, @ResponseBody 사용
- Response Body에 urlInput 값을 넣어서 return
- 결과
Request Mapping
- 속성 값을 통해 요청 매핑 조건 지정
속성
- value : 요청 경로 지정
- path : 요청 경로 지정
- method : 요청 method 지정
- produces : 특정 media type의 accept를 가진 요청만 받음, 응답을 특정 media type으로 함
- consumes : 특정 media type의 content-type을 가진 요청만 받음
- params : 요청 파라미터 값 지정
- headers : 헤더 값 지정
- name : request mapping의 이름 지정
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @RequestMapping(path = "/anno/{urlInput}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.TEXT_PLAIN_VALUE, name = "annoController", params = {"a=1","b=2"}) @ResponseBody public String anno(@PathVariable String urlInput, @RequestHeader HttpHeaders requestHeaders, @RequestParam("a") int a, @RequestParam("b") String b) { System.out.println(urlInput); System.out.println(requestHeaders.getHost()); System.out.println(a); System.out.println(b); return urlInput; } | cs |
- method : GET method 요청을 받음
- consumes : 요청 header의 content-type이 text/plain인 것만 받음
- produces : 응답 header의 content-type을 application/json으로 보냄
- name : request mapping의 이름을 지정
- params : parameter가 a=1, b=2인 것만 받음
Binding
- 요청 데이터를 특정 method의 파라미터로 binding
- WebDataBinder를 사용
1. InitBinder 사용
1) addCustomFormatter
1 2 3 4 5 6 | public class BinderConfig { @InitBinder("dateTime") public void initBinder(WebDataBinder webDataBinder) { webDataBinder.addCustomFormatter(new DateFormatter("yyyyMMdd")); } } | cs |
- dateTime이라는 parameter를 "yyyyMMdd"의 포맷으로 바인딩
2) registerCustomEditor
1 2 3 4 5 6 7 | public class BinderConfig { @InitBinder("dateTime") public void initBinder(WebDataBinder webDataBinder) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd"); webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(simpleDateFormat, false)); } } | cs |
2. Annotation 사용
- @DateTimeFormat을 사용하여 datetime binding
- @NumberFormat을 사용하여 숫자 binding
1 2 3 4 5 6 7 8 9 10 11 12 | @RequestMapping(path = "/anno/{urlInput}", method = RequestMethod.GET) @ResponseBody public String anno(@PathVariable String urlInput, @RequestHeader HttpHeaders requestHeaders, @DateTimeFormat(pattern = "yyyyMMdd") @RequestParam Date a, @RequestParam("b") String b) { System.out.println(urlInput); System.out.println(requestHeaders.getHost()); System.out.println(a); System.out.println(b); return a; } | cs |
Validation
Validation
- 매개변수에 @Validated 또는 @Valid를 사용하여 입력 값 검증
1 2 3 4 5 6 7 | @RequestMapping(path = "/anno1", method = RequestMethod.POST) @ResponseBody public TestData anno1(@Validated @RequestBody TestData testData) { System.out.println(testData.getId()); System.out.println(testData.getMsg()); return testData; } | cs |
- TestData 객체의 Id에는 @NotEmpty가 걸려있음
- @Validated를 설정하면, 해당 값이 Empty로 올 경우, 에러 출력
Validation rule annotation
1. Null 검사
- @NotNull
- null이 들어오면 error
- 속성 : message(Null이 들어왔을 때, 해당 메시지로 에러 출력)
2. 빈 값 검사
- @NotEmpty
- null, 빈 값("")이 들어오면 error
3. Blank 검사
- @NotBlank
- null, 빈 값(""), blank(" ")가 들어오면 error
4. Size 검사
- @Size
- 속성 : max, min
- 최대 값, 최소 값을 지정
5. Pattern 검사
- @Pattern
- 특정 패턴을 검사
- 속성 : regexp(정규 표현식)
6. DateTime 검사
- @DateTimeFormat
- 속성 : pattern(해당 패턴의 날짜가 들어와야 함)
- @Past : 과거 날짜여야함
7. Boolean 검사
- @AssertTrue : True 값이 들어와야 함
Spring Validator
- Spring에서 지원하는 Spring Validator의 인터페이스를 이용하여 구현
- method : supports(Class<?> clazz), validate(Object target, Errors errors);
- Validator 구현
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @Component public class TestDataValidator implements Validator { @Override public boolean supports(Class<?> clazz) { return TestData.class.isAssignableFrom(clazz); } @Override public void validate(Object target, Errors errors) { TestData testData = (TestData) target; if(testData.getId() == null) { errors.rejectValue("id", "id가 null 입니다."); } } } | cs |
- supports method에는 원하는 Class를 위와 같이 선언
- validate는 검증할 로직을 구현
- Controller 구현
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Autowired private TestDataValidator testDataValidator; @InitBinder() public void initBinder(WebDataBinder webDataBinder) { webDataBinder.addValidators(testDataValidator); } @RequestMapping(path = "/valid", method = RequestMethod.POST) public void val(@Validated @RequestBody TestData testData) { System.out.println(testData.getId()); System.out.println(testData.getMsg()); } | cs |
- initBinder로 구현한 validator를 추가
- @Validated 어노테이션으로 requestbody(TestData)를 검증
- Validator 사용 시, @NotNull을 사용하지 않아도 Validator에서 검증
- null값을 넣었을 때 결과
예외 처리
Spring Exception Handler
- 컨트롤러, 컨트롤러 이후에 발생하는 예외를 처리하기 위해 Spring에서 제공
- DispathcerServlet이 예외를 발견하고 HandlerExceptionResolver에서 예외 처리
1. HandlerExceptionResolver 구현 클래스(예외 처리 순서 : 1 → 2 → 3)
1) ExceptionHandlerExceptionResolver
- @ExceptionHandler 어노테이션을 붙이고 메소드를 구현하여 예외 처리
2) ResponseStatusExceptionResolver
- @ResponseStatus를 붙인 클래스를 작성하여 예외 처리
3) DefaultHandlerExceptionResolver
- Front Controller에서 발생하는 예외 처리
→ 1,2,3에서 처리되지 않는 경우, NestedServletException 예외 발생
Exception Handler
- Exception Handler 구현
1 2 3 4 5 6 7 8 9 | @ControllerAdvice @ResponseBody public class TestExceptionHandler { @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public String handleTypeException() { return "exception"; } } | cs |
- @ControllerAdvice로 Exception Handler 지정
- @ExceptionHandler(예외)로 어떤 exception이 발생했을 때, 해당 method가 실행될지 결정
- 결과
- 존재하지 않는 GET handler에 대한 요청 시, ExceptionHandler가 해당 exception을 잡아 "exception" 출력
- 상태 코드는 지정하지 않아 200
ResponseStatus
- 예외 처리한 내용에 원하는 status code를 사용하게 해줌
1 2 3 4 5 6 7 8 9 10 | @ControllerAdvice @ResponseBody public class TestExceptionHandler { @ExceptionHandler(HttpRequestMethodNotSupportedException.class) @ResponseStatus(HttpStatus.CONFLICT) public String handleTypeException() { return "exception"; } } | cs |
- 해당 예외 발생 시, Status code를 409(CONFLICT)로 설정하여 응답
- 결과
- 같은 결과지만, 409 conflict 응답
'프로그래밍 > Spring' 카테고리의 다른 글
[Spring] Spring MVC - Session, Async, 공통 처리, Locale (0) | 2019.04.14 |
---|---|
[Spring] Spring REST (0) | 2019.04.14 |
[Spring] Spring MVC - MVC, IntelliJ 설정, 프로젝트 생성 (0) | 2019.03.28 |
[Spring] Datasource, Spring JDBC, Transaction (0) | 2019.03.27 |
[Spring] Aspect of Programming(AOP), Resource (0) | 2019.03.20 |