어제 spring의 Dispatcher Servlet에 대해서 간단히 알아 보았다. 이번에는 Spring MVC와 구성요소에 대해 다뤄 볼 것이다.
Spring MVC의 구조
의 주요구성요는 Model, View, Controller이지만, 3가지 구성요소가 유기적으로 동작하기 위해 다양한 구성요소가 함께한다.
- DispatcherServlet(Front Controller)
- Handler(Controller)
- ModelAndView
- ViewResolver
MVC 프레임워크와 Spring 프레임워크가 거의 동일하다.
Handler(Controller)
동일한 형식에 대해 다른 controller
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="header.jsp" %>
<form method="POST">
<p><input type="text" name="name" placeholder="이름" required autofocus></p>
<p><input type="number" name="age" placeholder="나이" required ></p>
<p><input type="submit"></p>
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="header.jsp" %>
<h3>${msg }</h3>
</body>
</html>
데이터를 처리 하기 위한 Controller는 자바코드로 이루어진다.
1. JSP스러운 Spring 코드(Model)
package com.itbank.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class Ex01Controller {
@RequestMapping(value = "/ex01", method = RequestMethod.GET)
public void ex01() {}
// 가장 기본적인 반환형은 String이며, 포워딩할 jsp의 이름을 가리킨다
// 반환형이 void라면, 요청주소 문자열을 활용하여 포워딩할 jsp의 이름을 찾는다
// 주소 맨 앞의 /는 제거하고, /WEB-INF/views/ex01.jsp를 찾아서 포워드한다
// 새로 추가된 함수는 반드시 톰캣을 재시작해야 함수가 매핑되어 올라간다 => 스프링은 프로젝트가 시작할때 모든 것이 준비되기 때문
// 같은 주소라도 요청 메서드에 따라서 서로 다른 작동으로 구분한다.
@RequestMapping(value = "/ex01", method = RequestMethod.POST)
public String ex01(HttpServletRequest request) throws IOException {
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String adult = age >= 20 ? "성인" : "미성년자";
String msg = String.format("%s의 나이는 %d살이고, %s입니다", name, age, adult);
request.setAttribute("msg", msg);
return "ex01-result";
}
}
위 보기와 같이 어노테이션을 RequestMapping을 이용하여 진행할경우, method형식을 지정해줘야한다.
또한, request 모두를 받아서 사용하므로, String형식으로 변환을 해줘야하는 불편함도 존재한다.
2. Spring형식의 Controller
package com.itbank.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class Ex02Controller {
// 1) @RequestMapping의 단축 어노테이션이 존재한다(GetMapping, PostMapping ...)
// 2) request.getParameter() 대신 컨트롤러 메서드의 매개변수에 파라미터를 받을 수 있다.
// 3) HttpServletRequest 대신 Model타입의 객체를 이용하여 attribute를 전달할 수 있다.
@GetMapping("/ex02")
public void ex02() {}
@PostMapping("/ex02")
public String ex02(String name, int age, Model model) {
// primitive type + String 형식은 매개변수로 받으면 request.getParameter()가 필요없다.
// HttpServletRequest는 파라미터 및 어트리뷰트만 처리하기에는 너무 무거운 객체이다
// 어트리뷰트만 처리할 수 있는 간소화된 객체 Model을 사용한다 (스프링에서 사용하는 객체)
// request.setCharacterEncoding("UTF-8"); 이 코드는 web xml에서 필터로 처리할 것임
String adult = age >= 20 ? "성인" : "미성년자";
String msg = String.format("%s의 나이는 %d살이고, %s입니다.", name, age, adult);
model.addAttribute("msg", msg);
return "ex02-result";
}
}
JSP형식과 동일하게 출력되나 실제 코드는 많이 줄어든 모습을 확인할 수 있다.
Spring으로 오며 변경된 점 :
1) @RequestMapping의 단축 어노테이션이 존재한다(GetMapping, PostMapping ...)
2) request.getParameter() 대신 컨트롤러 메서드의 매개변수에 파라미터를 받을 수 있다.
3) HttpServletRequest 대신 Model타입의 객체를 이용하여 attribute를 전달할 수 있다.
3. ModelAndView 형식
package com.itbank.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/ex03") // 주소만 ex03이면 모두 해당
public class Ex03Controller {
@GetMapping // 같은 주소에서 요청 메서드에 따라 구분(GET)
public void ex03() {}
@PostMapping // 같은 주소에서 요청 메서드에 따라 구분(POST)
public ModelAndView ex03(String name, int age) { // 사용자 입력에 의해 들어오는 값만 매개변수
ModelAndView mav = new ModelAndView(); // Model model
// String viewName
// 고정값일 경우 주로 이용
mav = new ModelAndView("ex03-result"); // 생성자 매개변수로 viewName을 전달하기
// 변동값일 경우 주로 이용
mav.setViewName("ex03-result"); // setter로 viewName을 전달하기(포워드시킬 jsp의 이름)
String adult = age >= 20 ? "성인" : "미성년자";
String msg = String.format("%s의 나이는 %d살이고, %s입니다", name, age, adult);
mav.addObject("msg", msg); // jsp 에게 넘길 attribute(object)
return mav;
}
}
앞서 코드와 달라진 점 :
1) 데이터 처리 후 model에 넣기
2) Model을 넣을 view 이름을 지정해준다.
3) Model과 viewname을 감싼 ModelAndView '객체'를 DispatcherServlet으로 보낸다.
4. Spring 커멘드 객체 활용
package com.itbank.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.itbank.model.Ex04DTO;
@Controller
@RequestMapping("/ex04")
public class Ex04Controller {
@GetMapping
public void abcd() {}
// 컨트롤러의 함수 이름은 개발자가 구분하기 쉬운 이름이면 된다.
// 컨트롤러의 함수 이름은 viewName에 전형 영향을 주지 않는다.
@PostMapping
public ModelAndView ex04(Ex04DTO user) { // 스프링 커맨드 객체 활용
ModelAndView mav = new ModelAndView("ex04-result");
mav.addObject("user",user);
return mav;
}
}
위와 같은 경우 jsp때와 비슷하게 DTO를 만들어줘서 Controller로 넘겨준다
package com.itbank.model;
public class Ex04DTO { // 개별 데이터를 나타내기 위한 클래스
// 싱글톤 적용하면 안된다. 같은 형식이라도 서로 다른 데이터를 나타낼 수 있어야 한다
// 따라서, 스프링 빈으로 등록하지 않는다.
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
이후 변경된 result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="header.jsp" %>
<h3>
${user.name }의 나이는
${user.age }살이고,
${user.age >= 20 ? '성인' : '미성년자' }입니다.
</h3>
</body>
</html>
EL태그로 데이터를 바로 끌고 올 수 있다.
Handler(Controller)
- 코드상으로 완벽히 화면구현과 데이터처리 과정이 완벽히 분리된다.
- Java(Back-End : 데이터 처리만을 처리
- <-> 서로 정보를 전달 받고 뿌려주기만 한다.
- JSP(Front-End) : 화면구현만을 처리
'개발자 > Spring' 카테고리의 다른 글
[Spring] 간단한 UpDown 게임 구현 (0) | 2022.12.27 |
---|---|
[SPRING] Spring 컨트롤러 메서드 (0) | 2022.12.27 |
[SPRING] 인코딩 필터 (0) | 2022.12.27 |
[SPRING] 의존성(dependencies) (0) | 2022.12.26 |
[SPRING] DispatcherServlet(jsp에서 구동을 곁들인) (0) | 2022.12.26 |