Spring MVC ㅇ 스프링 MVC 구성요소 설명 DispatcherServlet 클라이언트의 요청을 컨트롤러에게 전달하고 컨트롤러가 리턴하는 결과를 View로 전달 (Model2 Command Pattern의 Commander 역할) HandlerMapping 클라이언트의 요청을 어떤 컨트롤러가 처리할지 결정 Controller 클라이언트의 요청대로 로직 수행 후 결과 리턴 (ModelAndView) ModelAndView 컨트롤러가 수행한 로직 결과 및 View 페이지에 대한 정보를 담음 ViewResolver ModelAndView에서 지정된 View 페이지 처리 View 컨트롤러가 로직을 수행하고 ModelAndView에 저장된 결과를 화면으로 출력 (일반적으로 JSP 또는 Velocity 같은 뷰 템플릿 사용)
Spring MVC ㅇ 스프링 MVC 흐름 Controller HandlerMapping 클라이언트 4. 처리 요청 2. url과 매핑되는 Controller 검색 3. 처리할 Controller 리턴 5. 처리 결과를 ModelAndView로 리턴 1. 처리요청(url) 클라이언트 DispatcherServlet 6. 결과를 출력할 View 검색 7. 결과를 출력할 View 위치 리턴 8. 결과 출력 View ViewResolver
Spring MVC ㅇ 필요 라이브러리 - spring-web.jar - spring-webmvc.jar
Spring MVC web.xml … 생략 … <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> </servlet> <servlet-mapping> <url-pattern>*.do</url-pattern> </servlet-mapping>
Spring MVC dispatcher-servlet.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="edu.seowon.mvc"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
Spring MVC TestController.java @Controller public class TestController { @RequestMapping("/first.do") public ModelAndView first() { ModelAndView mav = new ModelAndView(); mav.setViewName("first"); mav.addObject("var", "FIRST"); return mav; } @RequestMapping("/second.do") public String second(Model model) { model.addAttribute("var", "SECOND"); return "second";
Spring MVC first.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>First</title> </head> <body> First :: ${var} </body> </html>
Spring MVC second.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Second</title> </head> <body> Second :: ${var} </body> </html>
Spring MVC Service ㅇ 기존 Model2 : Controller Model(DAO) DB ㅇ 스프링 : Controller Service Model(DAO) DB 비즈니스 로직 처리 / 트랜잭션 단위 / 여러 개의 DAO를 호출 Client Controller Service Dao (Model) request DB Forward View (JSP) response
Spring MVC 연습 ㅇ 프로젝트 구조
Spring MVC 연습 ㅇ 프로젝트 구성 파일 설명 역할 파일명 설명 프로젝트 설정 web.xml 스프링 설정 파일 정의 dispatcher-servlet.xml viewResolver 정의 controller, service, model 빈 등록 Controller HelloController.java 클라이언트의 요청을 받은 후 처리결과를 포함하여 View로 포워드 Service HelloService.java 핵심 로직 처리 Model HelloDao.java 데이터베이스 작업 View hello.jsp Controller로 부터 넘겨받은 처리 결과를 (클라이언트/웹브라우저) 출력
Spring MVC 연습 web.xml … 생략 … <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> </servlet> <servlet-mapping> <url-pattern>*.do</url-pattern> </servlet-mapping>
Spring MVC 연습 dispatcher-servlet.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="mvc.spring" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
Spring MVC 연습 HelloController.java @Controller public class HelloController { @Autowired private HelloService helloService; @RequestMapping("intro/hello") public ModelAndView hello() { ModelAndView mav = new ModelAndView(); String value = null; value = "Hello " + helloService.getName(); mav.addObject("value", value); mav.setViewName("hello"); return mav; }
Spring MVC 연습 HelloService.java @Service public class HelloService { @Autowired private HelloDao helloDao; public String getName() { String name = helloDao.selectMember(); return name; }
Spring MVC 연습 HelloDao.java @Repository public class HelloDao { public String selectMember() { return "SPRING"; }
Spring MVC 한글처리 ㅇ web.xml <filter> <filter-name>encodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <url-pattern>/*</url-pattern> </filter-mapping>
컨트롤러 메소드 파라미터 @RequestMapping 속성 요청조건 지원 버전 value URL 패턴 3.0 이상 method HTTP 요청 메소드 params 파라미터 headers HTTP 헤더 consumes Content-Type 헤더 3.1 이상 produces Accept 헤더
컨트롤러 메소드 파라미터 @RequestMapping ㅇ value @RequestMapping(“/hello”) @RequestMapping({“/hello”, “/hello/”, “hello.*”}) @RequestMapping(“main*”) @RequestMapping(“/admin/*/user”) @RequestMapping(“/admin/**/user”) ㅇ method @RequestMapping(value=“/hello.do”, method=RequestMethod.GET) @RequestMapping(value=“/hello.do”, method=RequestMethod.POST) ㅇ params @RequestMapping(value=“/hello.do”, params=“type”) @RequestMapping(value=“/hello.do”, params=“type=admin”) @RequestMapping(value=“/hello.do”, params=“/user/edit”) @RequestMapping(value=“/hello.do”, params=“!type”) ㅇ headers @RequestMapping(value=“/hello.do”, headers=“Content-Type=text/*”)
컨트롤러 메소드 파라미터 @RequestMapping ㅇ consumes @RequestMapping(consumes=“application/json”) @RequestMapping(consumes={“application/json”, “multipart/form-data”}) ※ @RequestMapping(headers=“Content-Type=application/json”) ㅇ produces @RequestMapping(produces=“text/html”) @RequestMapping(produces={“text/html”, “application/json”}) ※ @RequestMapping(headers=“Accept=application/json”)
컨트롤러 메소드 파라미터 @RequestParam ㅇ 요청주소 http://localhost/list.do?currentPage=1&searchText=abcd @Controller public class ListController { @RequestMapping(“list.do”) public ModelAndView list(@RequestParam(“currentPage”) int currentPage, @RequestParam(“searchText”) String searchText) { ...... } @RequestParam을 지정하는 경우 반드시 요청 주소에 해당 파라미터가 존재해야 됨 필수 파라미터로 쓰지 않으려면 requeired를 false로 변경 null을 지정 못하는 타입은 defaultValue로 사용 ex) @RequestParam(value=“searchText”, required=false) String searchText @RequestParam(value=“currentPage”, defaultValue=“1”) int currentPage
컨트롤러 메소드 파라미터 @CookieValue @RequestMapping(“/cookie/view.do”) public String view(@CookieValue(“auth”) String authValue) { ..... } 해당 쿠키가 존재하지 않으면 500 에러 발생 쿠키가 필수가 아닌 경우 required 속성을 false로 지정 defaultValue를 사용하여 기본값 지정 가능
컨트롤러 메소드 파라미터 @RequestHeader @RequestMapping(“/header/check.do”) public String check(@RequestHeader(“Accept-Language”) String languageHeader) { ..... } 해당 헤더가 존재하지 않으면 500 에러 발생 쿠키가 필수가 아닌 경우 required 속성을 false로 지정 defaultValue를 사용하여 기본값 지정 가능
컨트롤러 메소드 파라미터 ㅇ 서블릿 API 직접 사용 - javax.servlet.http.HttpServletRequest / javax.servlet.ServletRequest - javax.servlet.http.HttpServletResponse / javax.servlet.ServletResponse - javax.servlet.http.HttpSession @RequestMapping(“/anything.do”) public ModelAndView anything(HttpServletRequest request, HttpServletResponse response, HttpSession session) { ..... }
컨트롤러 메소드 리턴 타입 리턴 타입 설명 ModelAndView 뷰 정보 및 모델 정보를 담아서 리턴 Model 뷰의 이름은 URL로부터 결정 Map 뷰에 전달할 객체 정보를 담고 있는 Map 리턴 String 뷰 이름 리턴 View 객체 View 객체 직접 리턴 void 메소드가 ServletResponse나 HttpServletResponse 타입의 파라미터를 갖는 경우 메소드가 직접 응답을 처리 그렇지 않은 경우 URL로부터 결정 @ResponseBody 적용 메소드에서 @ResponseBody 가 적용된 경우 리턴 객체를 HTTP 응답으로 전송 HttpMessageConverter를 이용해서 객체를 HTTP 응답 스트림으로 변환
뷰 이름 명시적 지정 ㅇ ModelAndView @RequestMapping(“/main.do”) public ModelAndView main() { ModelAndView mav = new ModelAndView(); mav.setViewName(“main”); return mav; } ㅇ String @RequestMapping(“/main.do”) public String main() { return “admin/main”; }
뷰 이름 자동 지정 ㅇ RequestToViewNameTranslator 를 이용하여 URL로부터 뷰 이름 결정 - 리턴 타입이 Model 또는 Map 인 경우 - 리턴 타입이 void 이면서 ServletResponse 또는 HttpServletResponse 타입의 파라미터가 없는 경우 @RequestMapping(“/search/list.do”) public Map<String, Object> searchList() { Map<String, Object> map = new HashMap<String, Object>(); return map; } /search/list.do search/list
리다이렉트 뷰 ㅇ redirect:/bbs/list : 현재 서블릿 컨텍스트에 대한 상대적인 경로 사용 예) ModelAndView mav = new ModelAndView(); mav.setViewName(“redirect:/list.do”); return mav;
뷰로 전달되는 모델 데이터 ㅇ @RequestMapping이 적용된 메소드가 ModelAndView / Model / Map을 리턴하는 경우 해당 객체에 담긴 모델 데이터가 뷰로 전달 ㅇ @RequestMapping이 적용된 메소드가 가지는 파라미터(클래스) ㅇ @ModelAttribute가 적용된 메소드가 리턴한 객체 @RequestMapping(“/search/game.do”) public ModelAndView search( @ModelAttribute(“command”) SC sc, ModelMap model) { ..... } @ModelAttribute(“searchTypeList”) public List<SearchType> searchTypeList() { List<SearchType> options = new ArrayList<SearchType>(); option.add(new SearchType(1, “전체”)); option.add(new SearchType(2, “아이템”)); option.add(new SearchType(3, “캐릭터”)); return options; }
ModelAndView 모델 설정 ㅇ setViewName(String viewName) 뷰 이름 지정 ㅇ addObject(String key, Object value) 해당 key로 value 지정 ㅇ addAllObjects(Map<String, ?> map) Map 타입 객체 지정
@PathVariable – URI 템플릿 ㅇ @RequestMapping 값으로 {템플릿 변수} 사용 ㅇ @PathVariable를 이용해서 {템플릿 변수}와 동일한 이름을 갖는 파라미터 추가 @RequestMapping(“/game/users/{userId}/characters/{characterId}”) public String characterInfo(@PathVariable String userId, @PathVariable String characterId, ModelMap model) { model.addAttribute(“userId”, userId); model.addAttribute(“characterId”, characterId); return “game/chracter/{characterId}”; }
@ResponseBody ㅇ return String ㅇ MessageConverter @RequestMapping(value=“/ajax/hello.do") @ResponseBody public String ajaxHello () { return “<html><body>Hello</body></html>”; } ㅇ MessageConverter <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.StringHttpMessageConverter" /> </list> </property> </bean>
@ResponseBody ㅇ return Map ㅇ MessageConverter @RequestMapping("/ajax/getData.do") @ResponseBody public Map<String, Object> ajaxGetData() { Map<String, Object> map = new HashMap<String, Object>(); map.put("a", 1); map.put(“b", "abcd"); List<String> list = new ArrayList<String>(); list.add("HI"); list.add("HELLO"); map.put("list", list); return map; } ㅇ MessageConverter <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json. MappingJacksonHttpMessageConverter" /> </list> </property> </bean>
MessageConverter ㅇ ByteArrayHttpMessageConverter - Request : HTTP 본문을 byte 배열로 변경 - Response : Content-Type 을 octet-stream 으로 변경 ㅇ StringHttpMessageConverter - Request : HTTP 본문을 String 으로 변경 - Response : Content-Type 을 text/plain으로 변경 ㅇ FormHttpMessageConverter - application/x-www-form-urlencoded로 정의된 폼 데이터를 주고 받을때 사용 ㅇ SourceHttpMessageConverter - application/xml, application*+xml, text/xml 지원 - XML 문서를 DomSource, SAXSource, StreamSource 전환시 사용 위 4가지 MessageConverter 기본 등록
MessageConverter ㅇ Jaxb2RootElementHttpMessageConverter - JAXB2의 @XmlRootElement와 @XmlType 이 붙은 클래스를 이용해서 XML과 오브젝트 사이의 메시지 변환 지원 - JAXB2의 스키마 컴파일러를 통해 생성된 바인딩용 클래스를 이용하여 XML과 오브젝트 변환 ㅇ MarsharllingHttpMessageConverter - Marshaller와 Unmarsharller를 이용해서 XML 문서와 자바 오브젝트 변환 ㅇ MappingJacksonHttpMessageConverter - 자바 오브젝트와 JSON 자동 변환 위 3가지 MessageConverter 등록 시 기본 컨버터 자동 등록되지 않음