웹찢남

Spring - MVC 본문

BACK_END/Spring 공부

Spring - MVC

harry595 2021. 2. 17. 20:51

MVC (Model-View-Controller)

  • Model : 모델은 뷰가 렌더링하는데 필요한 데이터입니다. 예를 들어 사용자가 요청한 상품 목록이나, 주문 내역이 이에 해당합니다.
  • View : 웹 애플리케이션에서 뷰(View)는 실제로 보이는 부분이며, 모델을 사용해 렌더링을 합니다. 뷰는 JSP, JSF, PDF, XML등으로 결과를 표현합니다.
  • Controller : 컨트롤러는 사용자의 액션에 응답하는 컴포넌트입니다. 컨트롤러는 모델을 업데이트하고, 다른 액션을 수행합니다.

MVC Model2 아키텍처

요청을 서블릿(controller)이 받고 자바 빈(Model)을 이용해서

db에서 데이터를 꺼내오고 JSP(View)를 통해 화면에 보여주도록 함

 

위를 발전 시킨게 아래인데 Spring은 아래의 방식을 채택

출처) https://www.boostcourse.org/web326/lecture/58979

DispatcherServlet

- 프론트 컨트롤러 

- 클라이언트의 모든 요청을 받은 후 이를 처리할 핸들러에게 넘기고 핸들러가 처리한 결과를 받아 사용자에게 응답    결과를 보여준다.

- 1. 요청

- 2. Locale 결정(국가별 언어 셋팅, 지역화)

- 3. RequestContextHolder에 요청 저장 (요청을 받아 응답할 때까지 httpservlet request, response 등을 spring이 관리하는 객체 내에서 사용할 수 있도록 함, But 권장되지 않아 사용을 자제하는 것이 좋음)

- 4. FlashMap 복원 (리다이렉트로 값을 전달할 때 사용, DJango에서 개인적으로 이 기능을 사용하기 힘들었는데... 역시 Spring)

- 5. 멀티파트 요청

- 6(예).  request를 MultipartResolver가 멀티파트를 결정 후 핸들러 결정과 실행

- 6(아니요). 핸들러 결정과 실행

 

사용법

WebMvcContextConfiguration.java

package kr.or.connect.mvcexam.config;
//dispatcher servlet
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "kr.or.connect.mvcexam.controller" })
public class WebMvcContextConfiguration extends WebMvcConfigurerAdapter {
	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(31556926);
        registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
        registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
        registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
    }
 
    // default servlet handler를 사용하게 합니다. static한 자원을 보여줌
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
    
    //특정 url에 대한 처리를 controller class를 작성하지 않고 처리
    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
    		System.out.println("addViewControllers가 호출됩니다. ");
        registry.addViewController("/").setViewName("main");
    }
    
    //view 정보를 사용, prefix suffix를 설정해줌
    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app>

  <display-name>Spring JavaConfig Sample</display-name>

  <servlet>
    <!-- 아래에서 매핑에서 mvc를 등록했으니까 아래 mvc를 찾아 실행 -->
    <servlet-name>mvc</servlet-name>
    <!-- 아래를 frontcontroller로 사용 및 실행-->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <!-- webmvccontextconfiguration에서 설정을 읽어내서 수행 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>kr.or.connect.mvcexam.config.WebMvcContextConfiguration</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- 모든 요청이 들어오면 servlet name(mvc)이랑 같은 servletclass가 실행 -->
  <servlet-mapping>
    <servlet-name>mvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

 

 

@RequestParam

  • Mapping된 메소드의 Argument에 붙일 수 있는 어노테이션
  • @RequestParam의 name에는 http parameter의 name과 멥핑
  • @RequestParam의 required는 필수인지 아닌지 판단

@PathVariable

  • @RequestMapping의 path에 변수명을 입력받기 위한 place holder가 필요함
  • place holder의 이름과 PathVariable의 name 값과 같으면 mapping 됨
  • required 속성은 default true 임

 

@RequestHeader

  • 요청 정보의 헤더 정보를 읽어들 일 때 사용
  • @RequestHeader(name="헤더명") String 변수명

MVC를 사용해서 1+1 만들기 (post와 Get을 사용하여 page 처리(위의 annotation 사용)

 

pluscontroller.java

package kr.or.connect.mvcexam.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class PlusController {
	@GetMapping(path="/plusform")
	public String plusform() {
		return "plusForm";
	}
	
	//request param 내의 name='value1'을 plus method 내의 value1으로 사용한다는 뜻
	//Spring이 제공하는 modelmap을 사용해서 선언하면 request scope에 알아서 매칭해줌
	@PostMapping(path = "/plus")
	public String plus(@RequestParam(name = "value1", required = true) int value1,
			@RequestParam(name = "value2", required = true) int value2, ModelMap modelMap) {
		int result = value1 + value2;

		modelMap.addAttribute("value1", value1);
		modelMap.addAttribute("value2", value2);
		modelMap.addAttribute("result", result);
		return "plusResult";
	}
	
}

 

plusform.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post" action="plus">  
value1 : <input type="text" name="value1"><br>
value2 : <input type="text" name="value2"><br>
<input type="submit" value="확인">  
</form>  
</body>
</html>

plusResult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
${value1} 더하기 ${value2} (은/는) ${result} 입니다.
</body>
</html>

 

위에서 pluscontroller를 통해 아래의 bean을 통해 prefix와 suffix를 매칭하여 jsp를 찾아 view단으로 보여줌

그 후 plusform에서 post 형식으로 controller에 request param을 통해 값을 전달하고 spring 내장 함수

modelMap.addAttribute에 request scope에 자동으로 매칭 후 plusResult.jsp에 값을 전달하여 값을 전달해 el에 표시

    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

 

@GetMapping과 달리 @RequestMapping 조금 다름

비슷하긴 한데 다양한 방식을 알기 위해 부스트 코스를 통해 실습을 해봄

userform을 통해 사용자가 /regist에 post를 보내면 그 값을 받아RequestMapping,@ModelAttribute를 통해 값을

 

UserController.java

package kr.or.connect.mvcexam.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.connect.mvcexam.dto.User;

@Controller
public class UserController {
	@RequestMapping(path="/userform", method=RequestMethod.GET)
	public String userform() {
		return "userform";
	}
	
	@RequestMapping(path="/regist", method=RequestMethod.POST)
	public String regist(@ModelAttribute User user) {

		System.out.println("사용자가 입력한 user 정보입니다. 해당 정보를 이용하는 코드가 와야합니다.");
		System.out.println(user);
		return "regist";
	}
}

User.java

package kr.or.connect.mvcexam.dto;

public class User {
	private String name;
	private String email;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", email=" + email + ", age=" + age + "]";
	}	
}

userform.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post" action="regist">  
name : <input type="text" name="name"><br>
email : <input type="text" name="email"><br>
age : <input type="text" name="age"><br>
<input type="submit" value="확인"> 
</form>
</body>
</html>

regist.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>등록되었습니다.</h2>
</body>
</html>

+추가로 아래의 방식으로 @RequestHeader을 사용하면 헤더 정보를 받을 수 있음

package kr.or.connect.mvcexam.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;

@Controller
public class GoodsController {
	@GetMapping("/goods/{id}")
	public String getGoodsById(@PathVariable(name="id") int id,
							   @RequestHeader(value="User-Agent", defaultValue="myBrowser") String userAgent,
							  HttpServletRequest request,
							  ModelMap model
							  ) {
		
		String path = request.getServletPath();
		
		System.out.println("id : " + id);
		System.out.println("user_agent : " + userAgent);
		System.out.println("path : " + path);
		
		model.addAttribute("id", id);
		model.addAttribute("userAgent", userAgent);
		model.addAttribute("path", path);
		return "goodsById";
	}
}

'BACK_END > Spring 공부' 카테고리의 다른 글

Spring - 방명록 만들기  (0) 2021.02.25
Spring - 레이어드 아키텍처  (0) 2021.02.23
Spring - JDBC  (0) 2021.02.15
Spring - Spring Core  (0) 2021.02.13
Spring - JSTL  (0) 2021.02.03
Comments