[Spring] Spring WebMVC

Wonkyun Jung·2023년 4월 19일
0

스프링

목록 보기
3/6
post-thumbnail

Spring Web MVC

MVC(Model-View-Controller) pattern

  • Model

    • 어플리케이션 상태의 캡슐화
    • 상태 쿼리에 대한 응답
    • 어플리케이션의 기능 표현
    • 변경을 view에 통지
  • View

    • 모델을 화면에 시각적으로 표현
    • 모델에게 업데이트 요청
    • 사용자의 입력을 컨트롤러에 전달
    • 컨트롤러 view를 선택하도록 허용
  • Controller

    • 어플리케이션의 행위 정의
    • 사용자 액션을 모델 업데이트와 mapping
    • 응답에 대한 view 선택

  • 어플리케이션의 확장을 위해 Model, View, Controller 세가지 영역으로 분리

  • 컴포턴트의 변경이 다른 영역 컴포넌트에 영향을 미치지 않음(유지보수 용이)

  • 컴포넌트 간의 결합성이 낮아 프로그램 수정이 용이(확장성이 뛰어남 )

  • 장점

    • 화면과 비즈니스 로직을 분리해서 작업 가능
    • 영역별 개발로 인하여 확장성이 뛰어남
    • 표준화된 코드를 사용하므로 공동작업이 용이하고 유지보수성이 좋음
  • 단점

    • 개발과정이 복잡해 초기 개발속도가 늦음
    • 초보자가 이해하고 개발하기에 다소 어려움

Model2 (Web MVC) 요청 흐름


Spring MVC

  • Spring MVC 특징
    • Spring은 DI나 AOP 같은 기능 뿐만 아니라, Servlet 기반의 WEB 개발을 위한 MVC Framework를 제공

    • Spring MVC는 Model2 Architecture와 Front Controller Pattern을 Framework 차원에서 제공

    • Spring MVC Framework는 Spring을 기반으로 하고 있기 때문에 Spring이 제공하는 Transaction 처리나 DI 및 AOP등을 손쉽게 사용

Spring MVC 구성요소

  • DispatcherServelt (Front Controller)

    • 모든 클라이언트의 요청을 전달받음

    • Controller에게 클라이언트의 요청을 전달하고, Controller가 리턴 한 결과값을 View에게 전달하여 알맞은 응답을 생성

  • HandlerMapping

    • 클라이언트의 요청 URL을 어떤 Controller가 처리할지를 결정

    • URL과 요청 정보를 기준으로 어떤 핸들러 객체를 사용할지 결정하는 객체이며, DispathcerServelt은 하나 이상의 핸들러 매핑을 가질 수 있음


  • Controller

    • 클라이언트의 요청을 처리한 뒤, Model을 호출하고 그 결과를 DispatcherServelt에 알려준다

  • ModelAndView
    • Controller가 처리한 데이터 및 화면에 대한 정보를 보유한 객체

  • ViewResolver
    • Controller가 리턴한 뷰 이름을 기반으로 Controller의 처리 결과를 보여줄 View를 결정

  • View
    • Controller의 처리결과를 보여줄 응답화면을 생성

Spring MVC 요청 흐름



Spring MVC 실행 순서


Spring MVC 구현

  • Spring MVC를 이용한 Application 구현 step
    • web.xml에 DispatcherServlet 등록 및 Spring 설정파일 등록

    • 설정 파일에 HandlerMapping 설정

    • Controller 구현 및 Context 설정 파일(servelt-context.xml)에 등록

    • Controller와 JSP의 연결을 위해 View Resolver 설정

    • JSP 코드 작성

  • Controller 작성

    • 좋은 디자인은 Controller가 많은 일을 하지 않고 Service에 처리를 위임


  • web.xml - DispatcherServlet 설정

    • <init-param>을 설정하지 않으면 < servelt-name >-servelt.xml file에서 applicationContext 정보를 load

    • Spring Container는 설정파일의 내용을 읽고 ApplicationContext 객체를 생성

    • <url-pattern>은 DispatacherServelt이 처리하는 URL Mapping pattern을 정의

    • Servelt이므로 1개 이상의 DispatcherServelt 설정 가능

    • <load-on-startup>1<load-on-startup> 설정 시 WAS startup시 초기화 작업 진행



Web Application 동작 원리


Web Application 실행 순서


Spring WebMVC 실습 코드

  • xml @annotation mapping
    • 웹일 땐 @Controller @Service @repository , 아닐 땐 @Component
  • 실습 코드 구조

Controller

MainController.java
 
@Controller
public class MainController {

	private static final Logger logger = LoggerFactory.getLogger(MainController.class);

	@Autowired
	private HelloService helloservice;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		return "index"; // WEB-INF/views/index.jsp
	}

	@RequestMapping(value = "/hello", method = RequestMethod.GET)
	public ModelAndView hello() {
		ModelAndView mav = new ModelAndView();
		HelloDto hellodto = new HelloDto();
		hellodto.setMessage("Hello Spring Web MVC");

		// hellodto 객체를 ex1에 담아서 WEB-INF/views/step01/hello.jsp로 보낸다
		mav.addObject("ex1", hellodto);
		mav.setViewName("step01/hello");

		return mav; // WEB-INF/views/step01/hello.jsp
	}

//	@RequestMapping(value = "/hellomvc", method = RequestMethod.GET)
//	public ModelAndView hellomvc() {
//		ModelAndView mav = new ModelAndView();
//		HelloDto hellodto = helloservice.greeting();
//		
//		//hellodto 객체를 ex2에 담아서 WEB-INF/views/step02/hello.jsp로 보낸다
//		mav.addObject("ex2",hellodto);
//		mav.setViewName("step02/hello");
//		
//		return  mav; //WEB-INF/views/step02/hello.jsp
//	}

	@RequestMapping(value = "/hellomvc", method = RequestMethod.GET)
	public String hellomvc(Model model) {
		HelloDto hellodto = helloservice.greeting();
		model.addAttribute("ex2", hellodto);
		return "step02/hello";
	}

	@RequestMapping(value = "/parameter", method = RequestMethod.GET)
	public String parameter() {
		return "step03/form";
	}

	//@RequestMapping(value = "/sendparam", method = RequestMethod.GET)
	@GetMapping(value = "/sendparam")
	public String parameterTest(@RequestParam("userid") String id, 
								@RequestParam("username") String name,
								@RequestParam("area") String area) {
		System.out.println("test1: " + id + " " + name + " " + area);
		return "step03/form";
	}

	//@RequestMapping(value = "/sendparam", method = RequestMethod.POST)
	@PostMapping(value = "/sendparam")
	public String parameterTest(ParameterDto parameterdto, Model model) {
		model.addAttribute("data",parameterdto);
		return "step03/result";
	}

}


Model


HelloDto.java

public class HelloDto {
	
	private String message;
	
	public void setMessage(String message) {
		this.message = message;
	}

	public String getMessage() {
		return message;
	}
}


ParameterDto.java

public class ParameterDto {
	
	private String userid;
	private String username;
	private List<String>fruit;
	
	
	public String getUserid() {
		return userid;
	}
	public void setUserid(String userid) {
		this.userid = userid;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public List<String> getFruit() {
		return fruit;
	}
	public void setFruit(List<String> fruit) {
		this.fruit = fruit;
	}

}


HelloService.java

public interface HelloService {
	public HelloDto greeting();
}


HelloServiceImpl.java

@Service
public class HelloServiceImpl implements HelloService{
	
	@Autowired
	private HelloDao helloDao;
	
	@Override
	public HelloDto greeting() {
		HelloDto hellodto = new HelloDto();
		hellodto.setMessage(helloDao.greeting());
		return hellodto;
	}
	
}


HelloDao.java

public interface HelloDao {

	public String greeting();

}


HelloDaoImpl.java

@Repository
public class HelloDaoImpl implements HelloDao {

	@Override
	public String greeting() {
		Calendar calendar = new GregorianCalendar();
		int hour = calendar.get(Calendar.HOUR_OF_DAY);
		if(hour > 7 && hour < 12) {
			return "좋은 아침입니다.";
		} else if(hour >= 12 && hour < 18) {
			return "즐거운 오후에요.";
		} else {
			return "굿 밤!!!!";
		}
	}

}


View

index.jsp

<c:set var = "root" value = "${pageContext.request.contextPath}" />
<html>
<head>
<title>Home</title>
</head>
<body>
	<p>test: ${root}</p>
	<br>
	<div align="center">
		<h3>Spring Web MVC</h3>
		<a href="${root}/hello">1. Hello Spring</a><br> <a
			href="${root}/hellomvc">2. Hello Spring Web MVC</a><br> <a
			href="${root}/parameter">3. parameter</a><br>
	</div>
</body>
</html>

step01.hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	${ex1.message} 
</body>
</html>

step02.hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	${ex2.message} 
</body>
</html>

step03.form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="root" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html lang="ko">
<head>
	<title>SSAFY-파라미터전달</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>
	<div class="container">
		<div class="col-lg-6">
			<h5 class="text-center">Spring을 이용한 파라미터 전달(Single)</h5>
			<form name="paramform" method="get" action="${root}/sendparam">
				<div class="form-group">
					<label for="userid">아이디:</label> <input type="text"
						class="form-control" placeholder="아이디 입력" name="userid">
				</div>
				<div class="form-group">
					<label for="username">이름:</label> <input type="text"
						class="form-control" placeholder="이름 입력" name="username">
				</div>
				<div class="form-group">
					<label for="area">지역:</label> <select name="area"
						class="custom-select">
						<option value="0">서울</option>
						<option value="1" selected>대전</option>
						<option value="2">구미</option>
						<option value="3">광주</option>
						<option value="4">부울경</option>
					</select>
				</div>
				<button type="submit" class="btn btn-primary">전송</button>
			</form>
		</div>
		<hr>
		<div class="col-lg-6">
			<h5 class="text-center">Spring을 이용한 파라미터 전달(Multi)</h5>
			<form name="paramform" method="post" action="${root}/sendparam">
				<div class="form-group">
					<label for="userid">아이디:</label> <input type="text"
						class="form-control" placeholder="아이디 입력" name="userid">
				</div>
				<div class="form-group">
					<label for="username">이름:</label> <input type="text"
						class="form-control" placeholder="이름 입력" name="username">
				</div>
				<div class="form-group">
					<label for="">좋아하는 과일:</label>
				</div>
				<div class="form-group form-check">
					<div class="form-check-inline">
						<label class="form-check-label"> <input type="checkbox"
							name="fruit" class="form-check-input" value="딸기">딸기
						</label>
					</div>
					<div class="form-check-inline">
						<label class="form-check-label"> <input type="checkbox"
							name="fruit" class="form-check-input" value="수박">수박
						</label>
					</div>
					<div class="form-check-inline">
						<label class="form-check-label"> <input type="checkbox"
							name="fruit" class="form-check-input" value="포도">포도
						</label>
					</div>
					<div class="form-check-inline">
						<label class="form-check-label"> <input type="checkbox"
							name="fruit" class="form-check-input" value="사과">사과
						</label>
					</div>
				</div>
				<button type="submit" class="btn btn-primary">Submit</button>
			</form>
		</div>
	</div>
</body>
</html>

step03.result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="root" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div align="left">
${data.username}(${data.userid})님이 좋아하는 과일은
<c:if test="${!empty data.fruit}">
	<c:set var="len" value="${data.fruit.size()}"/>
	<c:forEach varStatus="idx" var="fruit" items="${data.fruit}">
	${fruit}<c:if test="${idx.index ne len - 1 }">, </c:if>
	</c:forEach>입니다.
</c:if>
<c:if test="${empty data.fruit}">없습니다.</c:if>
</div>
</body>
</html>

결과

  • 1번 클릭시 나오는 화면

  • 2번 클릭시 나오는 화면

  • 3번 클릭시 나오는 화면
    • Multi 입력시 나오는 화면

0개의 댓글