Day95 java프로그래밍 기초(Spring web MVC)
1. View Resolver
1) View Resolver의 역할
2) 기본 View Resolver
- 기본 ViewResolver는 리턴 값으로 받은 view name으로 포워딩 할 JSP를 찾는다.
view name을 리턴하지 않으면 request hanlder의 url(@RequestMapping읠 value 값)을 상대경로로 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@RequestMapping("/c01_1") public class Controller01_1 { // http://localhost:9999/eomcs-spring-webmvc/app2/c01_1/h1 @GetMapping("h1") public String handler1(Model model) { return "jsp/c01_1.jsp"; // => /app2/c01_1/jsp/c01_1.jsp } // http://localhost:9999/eomcs-spring-webmvc/app2/c01_1/h2 @GetMapping("h2") public void handler2(Model model) { // 뷰 이름을 리턴하지 않으면, // request handler의 URL을 상대 경로로 사용한다. // 즉 다음 리턴 문과 같다. // return "c01_1/h2" // = /app2/c01_1/c01_1/h2 } }
3) InternalResourceViewResolver
- JSP URL의 접두어와 접미사를 미리 설정해 둘 수 있어 URL을 지정해준다.
미리 지정된 접두사, 접미사를 사용하여 뷰이름으로 콤포넌트의 URL을 완성한다.
1 2 3 4 5 6 7 8 9 10
//config에서 설정을 한다. @Bean public ViewResolver viewResolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver("/WEB-INF/jsp2/", // prefix ".jsp" // suffix ); return vr; // => prefix + 페이지컨트롤러 리턴 값 + suffix // 예) "/WEB-INF/jsp2/" + "board/list" + ".jsp" = /WEB-INF/jsp2/board/list.jsp }
- ViewResolver 실행 과정
- 페이지 컨트롤러는 클라이언트가 요청한 작업을 실행한 후 그 결과를 출력할 뷰의 이름을 리턴한다.
- 프론트 컨트롤러는 request handler가 리턴한 URL을 view resolver에게 전달한다.
- view resolver는 자신의 정책에 맞춰서 뷰 URL을 준비한다.
- InternalResourceViewResolver의 경우, request handler가 리턴한 URL 앞, 뒤에 접두사와 접미사를 붙여 JSP를 찾는다.
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
@Controller @RequestMapping("/c01_2") public class Controller01_2 { // http://localhost:9999/eomcs-spring-webmvc/app2/c01_2/h1 @GetMapping("h1") public String handler1(Map<String, Object> map) { return "c01_2/h1"; // => /WEB-INF/jsp2/c01_2/h1.jsp } // http://localhost:9999/eomcs-spring-webmvc/app2/c01_1/h2 @GetMapping("h2") public void handler2(Model model) { // request handler가 뷰 이름을 리턴하지 않으면 // request handler의 URL을 상대 경로로써 뷰 이름으로 사용한다. // => "/WEB-INF/jsp2/c01_2/h2.jsp" } // http://localhost:9999/eomcs-spring-webmvc/app2/c01_2/h3 @GetMapping("h3") public Map<String, Object> handler3() { HashMap<String, Object> map = new HashMap<>(); map.put("name", "홍길동3"); map.put("age", 40); // Map 객체에 값을 담아 리턴하면 // 프론트 컨트롤러는 Map 객체에 보관되어 있는 값들을 ServletRequest 보관소로 옮긴다. // 그리고 view URL은 request handler의 URL을 사용한다. // => "/WEB-INF/jsp2" + "/c01_2/h3" + ".jsp" = "/WEB-INF/jsp2/c01_2/h3.jsp" return map; } // http://localhost:9999/eomcs-spring-webmvc/app2/c01_2/h4 @GetMapping("h4") public ModelAndView handler4() { ModelAndView mv = new ModelAndView(); mv.addObject("name", "홍길동3"); mv.addObject("age", 40); mv.setViewName("c01_2/h4"); // ModelAndView 객체에 값과 뷰 이름을 담아 리턴하면 // 프론트 컨트롤러는 ModelAndView 객체에 보관되어 있는 값들을 // ServletRequest 보관소로 옮기고, // 설정된 뷰 이름을 ViewResolver에게 넘긴다. // return mv; } // http://localhost:9999/eomcs-spring-webmvc/app2/c01_2/h5 @GetMapping("h5") public ModelAndView handler5() { ModelAndView mv = new ModelAndView(); mv.addObject("name", "홍길동3"); mv.addObject("age", 40); // 뷰 이름을 지정하지 않으면 request handler의 path를 ViewResolver에게 넘긴다. // InternalResourceViewResolver 는 위 URL을 다음과 같이 바꾼다. // => /WEB-INF/jsp2/c01_2/h5.jsp return mv; } }
2. 세션다루기
1) HttpSession 직접 사용하기
2) @SessionAttributes, @ModelAttribute으로 다루기
3) 세션의 값을 무효화시키는 방법
3. 인터셉터
- 프론트 컨트롤러와 페이지 컨트롤러 사이에 코드를 삽입하는 기술이다.
1) 설정하기
config에서 인터셉터 호출 정책을 설정한다.
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 31 32 33
@ComponentScan("bitcamp.app2") public class App2Config implements WebMvcConfigurer { // 이 설정을 사용하는 프론트 컨트롤러에 적용할 인터셉터 설정하기 @Override public void addInterceptors(InterceptorRegistry registry) { // 1) 모든 요청에 대해 실행할 인터셉터 등록하기 // => 인터셉터를 적용할 URL을 지정하지 않으면 현재 프론트 컨트롤러의 모든 요청에 대해 적용된다. registry .addInterceptor(new Controller04_1_Interceptor1()); // 2) 특정 요청에 대해 실행할 인터셉터 등록하기 // 패턴: /c04_1/* => c04_1/ 바로 밑의 있는 자원에 대해서만 인터셉터를 적용한다. registry .addInterceptor(new Controller04_1_Interceptor2()) .addPathPatterns("/c04_1/*"); // 3) 특정 요청에 대해 실행할 인터셉터 등록하기 // 패턴: /c04_1/** => /c04_1/ 의 모든 하위 경로에 있는 자원에 대해서만 인터셉터를 적용한다. registry .addInterceptor(new Controller04_1_Interceptor3()) .addPathPatterns("/c04_1/**"); // 4) 특정 요청에 대해 인터셉터 적용을 제외하기 // => 패턴: /c04_1/** (include), /c04_1/a/** (exclude) // 즉, /c04_1/ 의 모든 하위 경로에 있는 자원에 대해서만 인터셉터를 적용한다. // 단 /c04_1/a/ 의 모든 하위 경로에 있는 자원은 제외한다. registry .addInterceptor(new Controller04_1_Interceptor4()) .addPathPatterns("/c04_1/**") .excludePathPatterns("/c04_1/a/**"); } }
2) 인터셉터 구현하기
- 인터페이스 HandlerInterceptor를 구현하여 만든다.
- preHandle : 페이지 컨트롤러의 핸들러를 호출하기 전에 이 메서드가 먼저 호출된다.
- postHandle : 페이지 컨트롤러의 핸들러가 리턴한 후 이 메서드가 호출된다.
afterCompletion : JSP를 실행한 후 이 메서드가 호출된다.
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
public class Controller04_1_Interceptor1 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 페이지 컨트롤러의 핸들러를 호출하기 전에 이 메서드가 먼저 호출된다. System.out.println("Interceptor1.preHandle()"); // 다음 인터셉터나 페이지 컨트롤러를 계속 실행하고 싶다면 true를 리턴한다. // 여기서 요청 처리를 완료하고 싶다면 false를 리턴한다. return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 페이지 컨트롤러의 핸들러가 리턴한 후 이 메서드가 호출된다. System.out.println("Interceptor1.postHandle()"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // JSP를 실행한 후 이 메서드가 호출된다. System.out.println("Interceptor1.afterCompletion()"); } }
4. JSON 데이터 출력
5. 예외 처리하기
- Request예외 처리 우선순위
- 페이지컨트롤러
- @ControllAdvice
- web.xml설정파일
- Servlet Container
1) 페이지 컨트롤러
페이지 컨트롤러 내에
@ExceptionHandler
가 있다면 이 컨트롤러의 예외는 해당 매서드로 처리된다.1 2 3 4 5 6 7 8
@ExceptionHandler public ModelAndView exceptionHandler(Exception ex) { System.out.println("Controller06_1.exceptionHandler() 호출됨!"); ModelAndView mv = new ModelAndView(); mv.addObject("error", ex); mv.setViewName("error6"); return mv; }
2) @ControllerAdvice
@ControllerAdvice
을 사용하는 클래스 파일에서 에러 처리에 대해 탐색한다.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 31 32
@ControllerAdvice public class GlobalControllerAdvice { // DispatcherServlet은 // request handler가 던지는 예외에 따라 // 그 예외를 받을 수 있는 메서드를 찾아 호출한다. // 단, @ExceptionHandler 가 선언된 메서드여야 한다. // @ExceptionHandler public ModelAndView exceptionHandler(Exception ex) { ModelAndView mv = new ModelAndView(); mv.addObject("error", ex); mv.setViewName("error3"); return mv; } @ExceptionHandler public ModelAndView ioExceptionHandler(IOException ex) { ModelAndView mv = new ModelAndView(); mv.addObject("error", ex); mv.setViewName("error4"); return mv; } @ExceptionHandler public ModelAndView sqlExceptionHandler(SQLException ex) { ModelAndView mv = new ModelAndView(); mv.addObject("error", ex); mv.setViewName("error5"); return mv; } }
3) xml 설정파일
xml에서 error-page를 설정하여 해당 url로 이동할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13
<!-- 서블릿 컨테이너에서 요청을 처리하는 중에 오류가 발생했을 때 오류 내용을 출력하는 기본 페이지를 교체하기 --> <!-- 1)오류가 발생했을 때 직접 JSP를 실행 --> <error-page> <location>/WEB-INF/jsp2/error1.jsp</location> </error-page> <!-- 2)오류가 발생했을 때 페이지 컨트롤러를 경유하여 JSP 실행 --> <error-page> <location>/app2/error</location> </error-page>
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.