Spring MVC 2015 Web Service Computing
Request & Response HTTP(Hyper-Text Transfer Protocol) 웹서버가하는일은요청 (Request) 과응답 (Response) 의연속이다. 1) 브라우저에 www.google.co.kr 을입력한다면 2) 구글서버에페이지를요청하는것이고 3) 화면이잘나타난다면구글서버가응답을한것이다.
. JSP 처리과정
MVC MVC (Model-View-Controller) 패턴은사용자의뷰페이지 (View) 와데이터 (Model) 그리고이들상호간의흐름제어 (Control) 하는비즈니스로직을분리하여상호영향없이모듈을재사용, 확장가능한구조적패턴 웹어플리케이션개발영역에까지보편적으로사용되기시작. 웹개발자라면반드시알아야할패턴
MVC MVC 패턴은크게모델, 뷰, 컨트롤러의세부분으로구성된다. Model: 상태정보를처리한다. View: 프리젠테이션뷰 ( 즉, 사용자가보게될결과화면을담당한다 ) Controller: 사용자의입력및흐름제어를담당한다.
MVC 1. 사용자가원하는기능을처리하기위한요청을컨트롤러에보낸다. 2. 모델은상태정보및관련기능을제공하는데, 컨트롤러는이모델을통해서사용자의요청을처리한다. 3. 모델을사용하여알맞은로직을수행한후컨트롤러는사용자에게보여줄뷰를선택하며, 선택된뷰는사용자에게알맞은결과화면을보여준다.
MVC MVC 패턴의핵심은다음과같다. 비즈니스로직을처리하는모델과결과화면을보여주는뷰가분리되어있다. 어플리케이션의흐름제어나사용자의처리요청은컨트롤러에집중된다. MVC 패턴을사용함으로써유지보수작업이간단해지고어플리케이션을쉽게확장할수있게되는것이다.
. Spring 의 DispatcherServlet
Spring 의 DispatcherServlet web.xml 에서 url-pattern 을 / 로설정함으로써모든요청은 DispatcherServlet 을거치게된다. <!--dispatcher-servlet.xml--> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.dispatcherservlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
Spring 의 DispatcherServlet 1) 클라이언트로부터요청이들어오면 DispatcherServlet 이가로챔 2) 가로챈정보를 HandlerMapping 에게보내해당요청을처리할수있는 Controller 를찾아냄 3) 컨트롤러를찾았다면해당컨트롤러로요청을보냄 ( 예 : HomeController) 4) 컨트롤러는요청에대한처리를한후해당 View 를리턴함 ( 예 : hello.jsp) 5) 이때, 그이름으로 ViewResolver 가찾아내서처리결과를 View 에보내줌 6) 이결과를다시 DispatcherServlet 에게보내주고, DispatcherServlet 은최종결과를다시클라이언트에게전송
Spring 의 DispatcherServlet ViewResolver 에아래와같이설정을해줬기때문에컨트롤러가 hello 를리턴하면 /WEB-INF/views/hello.jsp 가리턴됨 <bean id="contentnegotiatingviewresolver" class="org.springframework.web.servlet.view.contentnegotiatingviewresolver"> <property name="viewresolvers"> <list> <bean class="org.springframework.web.servlet.view.internalresourceviewresolver"> <property name="prefix" value="/web-inf/views/" /> <property name="suffix" value=".jsp" /> </bean> </list> </property> </bean>
Static Resources 아무런로직이없는정적리소스들 ( 각종 image, js, css 등 ) 도 DispatcherServlet 이처리해야할까? 정적리소스들은철저하게로직이있는컨트롤러요청과분리할필요가있다. 아래와같이설정한후, 정적리소스를담을디렉토리생성 <mvc:resources location="/web-inf/resources/" mapping="/resources/**" /> jsp 에서는아래와같이사용 <img src= /resources/images/spring.jpg"/>
HomeController Review package koreatech.cse.controller; import org.springframework.beans.factory.annotation.value; import org.springframework.stereotype.controller; import org.springframework.ui.model; import org.springframework.web.bind.annotation.requestmapping; @Controller @RequestMapping("/") public class HomeController { @RequestMapping public String home(model model) { model.addattribute("textfromcontroller", "World"); return "hello";
@RequestMapping String[] value RequestMethod[] method String[] params String[] headers URL 패턴 HTTP 메소드 (GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE) 요청파라미터 HTTP 헤더
@RequestMapping HTTP GET http://localhost:8080/requestmappinggettest?test=true @RequestMapping(value = "/requestmappinggettest", method = RequestMethod.GET, params="test=true") public String requestmappinggettest(model model) { model.addattribute("textfromcontroller", "World"); return "hello"; HTTP POST http://localhost:8080/requestmappingposttest?test=true @RequestMapping(value = "/requestmappingposttest", method = RequestMethod.POST) @ResponseBody public String requestmappingposttest() { return "hello";
@RequestParam String value 파라미터이름 String name 파라미터이름 ( 스프링 4.2.0 이후 ) boolean required 파라미터가필수인지아닌지여부 String defaultvalue 파라미터값이없을경우기본값지정
@RequestParam http://localhost:8080/requestparamtest http://localhost:8080/requestparamtest?a=1&b=anystring&c=true http://localhost:8080/requestparamtest?b=anystring @RequestMapping("/requestParamTest") public String requestparamtest( @RequestParam(name= "a", required=false, defaultvalue = "0") int a, @RequestParam("b") String b, @RequestParam(name= "c", defaultvalue = "true") boolean c) { System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); return "hello";
@RequestParam @RequestParam 에 map 을이용하면불특정다수로오는여러파라미터를활용할수있다. http://localhost:8080/requestparamtest http://localhost:8080/requestparamtest?name=hong&age=20&gender=1 http://localhost:8080/requestparamtest?b=anystring @RequestMapping("/requestParamMapTest") public String requestparammaptest(@requestparam Map<String, String> map) { for(map.entry entry: map.entryset()) { System.out.println(entry.getKey() + "=" + entry.getvalue()); return "hello";
@PathVariable @RequestParam 과다른형태의 URL 구성 값이 null 일경우주의 http://localhost:8080/pathvariabletest/any/input/value http://localhost:8080/pathvariabletest/when/null http://localhost:8080/pathvariabletest/value/with/1 @RequestMapping("/pathVariableTest/{a/{b/{c") public String pathvariabletest( @PathVariable(value="a") String a, @PathVariable String b, @PathVariable int c) { System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); return "hello";
Spring Form Spring 에서는 MVC 패턴에따라모델데이터를삽입하거나컨트롤러로 Form 태그라이브러리를제공한다. 스프링폼태그는 Model 데이터객체나참조데이터 (reference data) 들을화면상에서쉽게출력하도록도와준다. 스프링폼태그는 spring-form.tld 를필요로하므로 jsp 파일상단에다음과같이선언해줘야한다. <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
Spring Form 실습을위한구성 User.java package koreatech.cse.domain; public class User { private int id; private String name; private String email; private String password; private int age; //Getter, Setter 채워넣기 @Override public String tostring() { return "id: " + id + ", name: " + name + ", email: " + email + ", password: " + password + ", age: " + age;
Spring Form 실습을위한구성 UserController.java package koreatech.cse.controller; import koreatech.cse.domain.user; import org.springframework.stereotype.controller; import org.springframework.ui.model; import org.springframework.web.bind.annotation.requestmapping; @Controller @RequestMapping("/user") public class UserController { @RequestMapping("/signup") public String signup(model model) { User user = new User(); model.addattribute("user", user); return "signup";
Spring Form 실습을위한구성 /WEB-INF/views/signup.jsp <%@ page contenttype="text/html;charset=utf-8" language="java" %> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <html> <head> <title>form Test</title> </head> <body> <form:form modelattribute="user"> 이름 : <form:input path="name"/><br/> 이메일 : <form:input path="email"/><br/> 비밀번호 : <form:password path="password"/><br/> 나이 : <form:input path="age"/><br/> <input type="submit" value=" 가입 "/> </form:form> </body> </html>
Model Binding UserController.java @RequestMapping(value="/signup", method= RequestMethod.POST) @ResponseBody public String signup(@modelattribute User user, BindingResult result) { if (result.haserrors()) { List<FieldError> errors = result.getfielderrors(); for (FieldError error : errors ) { System.out.println (error.getobjectname() + " - " + error.getdefaultmessage()); System.out.println("user = " + user); return "success";
Controller level 의 Model Attribute HomeController.java @Controller @RequestMapping("/") public class HomeController { @ModelAttribute("name") private String getname() { return "IamHomeControllerModelAttribute";... - 위와같이컨트롤러의멤버변수와같이 ModelAttribute 를등록하면해당컨트롤러의모든 View 에서 name 이란변수를사용할수있다.