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 | <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> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 첫번째 요청엔 똑같은 이름의 servlet-name을 찾아 xml파일을 읽어들인다. --> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> | cs |
1. 서버가 시작되면서 web.xml을 읽으면서 시작한다.
맨 처음에 filter를 먼저 읽게되고 들어오는 모든 파일을 UTF-8처리 해주는 작업을 먼저해주고
2. .do로 실행되는 dispatcher를 읽는다.
dispatcher가 실행되면서 같은 서블릿네임을 가진 xml파일을 찾아간다.
[distpacher-servlet.xml]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <bean id="helloController" class="spring.controller.HelloController" /> <bean id="newArticleController" class="spring.controller.NewArticleController" p:articleService-ref="articleService" /> <bean id="articleService" class="spring.service.ArticleService" /> <!-- hello라는 setName을 리졸버가 받는다 그것을, /WEB-INF/views/hello.jsp 로 만들어주고 이 완성값을 디스페쳐에게 돌려준다. --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> <!-- property들을 앞에 붙히고 뒤에붙혀서 뷰 경로를 만들어준다 --> | cs |
3.
spring.controller.HelloController,
spring.controller.NewArticleController,
spring.service.ArticleService 세개의 java 클래스 파일을 bean객체화 함과 동시에 밑에 viewResolver의 정보를 로딩해놓는다.
동시에 어노테이션 @Controller를 올린 클래스들은, 컨트롤러 객체로도 생성된다.
또는,
1 2 3 4 5 | @Autowired private ArticleService articleService; <context:annotation-config/> <context:component-scan base-package="spring.controller"/> | cs |
빈객체를 일일이 생성할 필요없이, 모든 패키지를 스캔하겠다는 의미의 태그를 사용할 수 있다.
그리고 articleService부분을 @Autowired속성을 걸어서 사용 가능하다.
-------- 페이지 시작 ---------
[index.jsp]
1 2 3 4 | <body> <h2>Hello World!</h2> <a href="article/newArticle.do">파라미터 저장하기</a><br> </body> | cs |
4. 처음 앵커태그로 article/newArticle.do로 요청이 들어가게되면, 앵커태그는 'GET' 방식으로 요청이 들어가게 된다.
[NewArticleController.java]
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 | @Controller @RequestMapping("/article/newArticle.do") public class NewArticleController { private ArticleService articleService; // 컨트롤러 메서드 리턴타입이 String인 경우 // 리턴값을 view name으로 사용한다. @RequestMapping(method = RequestMethod.GET) public String form() { return "article/newArticleForm"; } @RequestMapping(method = RequestMethod.POST) public String submit(@ModelAttribute("command") NewArticleCommand command) { // 모델 데이터는 dispatcher를 통해 뷰로 다 알아서 전달이 된다. // 1. 객체 생성해서 저장하고 // 2. 같은이름으로 전달된 파라미터의 값을 setter로 저장함 // 3. model 데이터에 추가한다 ==> 뷰로 넘어가며 데이터도 같이 넘어간다. // 명시하지않으면 첫글자가 소문자인 newArticleCommand로 getter를 통해 꺼낼 수 // 있다.(${newArticleCommand.xxxx}) // 그 이름이 지정해주고 싶다면, @ModelAttribute("command") 를 사용해 key로 쓸 이름을 지정할 수 있다. articleService.writeArticle(command); return "article/newArticleSubmit"; } public void setArticleService(ArticleService articleService) { this.articleService = articleService; } } | cs |
5. @Controller의 @RequestMapping에있는 /article/newArticle.do로 요청이 들어왔으나,
앵커태그로 들어오는 GET방식으로 요청이 들어왔기때문에,
method방식을 get으로 넣어논 public String form(){...} 이 실행 된다.
또한, @Controller에 해당하는 클래스의 메서드는 return 타입이 String으로 돌아가는경우 그 String값을 viewName으로 사용한다.
리턴값을 ModelAndView.setViewName("") 으로 사용하는것과 같다.
6. viewName값을 리턴하면서 dispatcher가 리턴값을 받고, dispatcher가 그 네임을 viewResolver로 바로 요청(Request)한다.
return값이 "article/newArticleForm" 이고, Resolver의 prefix와 suffix에 맞추어서 뷰경로가 결정된다.
1 2 3 4 5 | <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> | cs |
article/newArticleForm 라는 스트링 값에
앞에 prefix가 붙고,
뒤에 suffix가 붙는다.
즉 view경로는 '/WEB-INF/views/' + 'article/newArticleForm' + '.jsp' 가 된다.
-prefix- -viewName- -suffix-
경로에 맞춰서 /WEB-INF/views/article/newArticleForm.jsp 에있는 jsp페이지를(뷰::view) Open한다.
물론, 웹페이지에있는 url경로는 처음 요청한 /article/newArticle.do에서 변하지않는다.
[/WEB-INF/views/article/newArticleForm.jsp]
1 2 3 4 5 6 7 | 게시글 쓰기 입력 폼: <form method="post"> <input type="hidden" name="parentid" value="10" /> 제목: <input type="text" name="title" /><br/> 내용: <textarea name="content"></textarea><br /> <input type="submit" /> </form> | cs |
또한, 반드시 폼에서 보내지는 name값과
같은 DTO가 존재해야하며, DTO가 가지는 변수명의 이름이 같아야한다
[NewArticleCommand.java]
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 | public class NewArticleCommand { private String title; private String content; private int parentid; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public int getParentid() { return parentid; } public void setParentid(int parentid) { this.parentid = parentid; } @Override public String toString() { return "NewArticleCommand [title=" + title + ", content=" + content + ", parentid=" + parentid + "]"; } } | cs |
이번엔 Form형태의 전송이다. parentid, title, content 세가지의 name과 value값 세가지로 전송되는데,
이번 Form은 POST방식으로 보내지게된다. POST방식임을 기억하자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Controller @RequestMapping("/article/newArticle.do") public class NewArticleController { @Autowired private ArticleService articleService; @RequestMapping(method = RequestMethod.POST) public String submit(@ModelAttribute("command") NewArticleCommand command) { // 모델 데이터는 dispatcher를 통해 뷰로 다 알아서 전달이 된다. // 1. 객체 생성해서 저장하고 // 2. 같은이름으로 전달된 파라미터의 값을 setter로 저장함 // 3. model 데이터에 추가한다 ==> 뷰로 넘어가며 데이터도 같이 넘어간다. // 명시하지않으면 첫글자가 소문자인 newArticleCommand로 getter를 통해 꺼낼 수 // 있다.(${newArticleCommand.xxxx}) // 그 이름이 지정해주고 싶다면, @ModelAttribute("command") 를 사용해 key로 쓸 이름을 지정할 수 있다. articleService.writeArticle(command); return "article/newArticleSubmit"; } | cs |
POST방식으로 요청들어왔기때문에 이번엔 public String submit(){} 메서드를 실행하게되는데,
이번에는 매개변수가 NewArticleCommand command가 있다.
Controller의 RequestMapping으로 이루어진 메서드가 실행이 될때,
모델 데이터는 dispatcher를 통해 저장이된다. 그 순서와 방법은 다음과 같다.
----------------------------------------------------------------------------------------------------------------------------------
모델 데이터는 dispatcher를 통해 뷰로 다 알아서 전달이 된다.
1. 매개변수로 들어온 객체를 생성해서 저장하고
2. 같은이름으로 전달된 파라미터의 값을 setter로 저장함
3. model 데이터에 추가한다 ==> 뷰로 넘어갈때 데이터도 자동으로 같이 넘어간다.
명시하지않으면 첫글자가 소문자인 newArticleCommand로 ★★getter를 통해★★ 꺼낼 수 있다.
ex)${newArticleCommand.xxxx})
key값을 따로 지정해주고 싶다면, @ModelAttribute("command") 를 사용해 key로 쓸 이름을 지정할 수 있다.
==>${command.xxx}로 사용할 수 있게 된다.
다시한번더 강조하지만, 이부분에서 가능한 이유는
반드시 폼에서 보내지는 name값과 같은 DTO(getter/setter)가 존재해야하며,
DTO(getter/setter)가 가지는 변수명과 이름이 같아야한다
return '뷰'로 넘어가기전에 articleService.writeArticle(command); 메서드를 요청했기때문에,
1 2 3 4 | public class ArticleService { public void writeArticle(NewArticleCommand command) { System.out.println("신규 게시글 등록 : " + command); } | cs |
Console창에 이러한 시스템 메시지를 뿌려준 후,
return 한다..........
물론 여기서도 return값이 String이기때문에 이것은
@Controller에 해당하는 클래스의 메서드는 return 타입이 String으로 돌아가는경우
그 String값을 viewName으로 사용한다.
를 다시 한번더 기억하자
즉 view경로는 '/WEB-INF/views/' + 'article/newArticleSubmit' + '.jsp' 가 된다.
-prefix- -viewName- -suffix-
경로에 맞춰서 /WEB-INF/views/article/newArticleSubmit.jsp 에있는 jsp페이지를(뷰::view) Open한다.
물론, 웹페이지에있는 url경로는 처음 요청한 /article/newArticle.do에서 변하지않는다.
마지막 jsp페이지에서는 model 데이터를 저장한 상태로 뿌려지기때문에 EL로 꺼낼 수 있다.
여기서 처음 Form메서드를 요청할때와 다르게 데이터를 저장까지 한 이유는,
매개변수에 DTO(setter/getter)가 있었기 때문이다.
[/WEB-INF/views/article/newArticleSubmit.jsp]
1 2 3 4 5 | <body> 게시글 등록됨:<br> 제목: ${command.title}<br> 내용: ${command.content } </body> | cs |
아까 newArticleForm의 input태그창에 적어놓은 값들이 결과값으로 나오게 된다.
'JAVA > Spring' 카테고리의 다른 글
Spring MVC - 예제(List로 출력) (2) | 2018.09.12 |
---|---|
@Autowired, @Resource, @Inject의 차이 (0) | 2018.09.11 |
Spring - Maven웹프로젝트 web.xml설정 (0) | 2018.09.11 |
Spring MVC 설정 (0) | 2018.09.11 |
Spring - mybatis 연결 (0) | 2018.09.10 |