Spring MVC Framework
- 웹 애플리케이션 개발을 위한 모델 뷰 컨트롤러 아키텍처를 제공한다.
- Model
- 애플리케이션 데이터를 캡슐화하고 일반적으로 POJO(순수 자바 객체)로 구성된다.. - View
- 모델 데이터를 렌더링하고 일반적으로 HTML 출력을 생성한다. - Controller
- 사용자 요청을 처리하고 적절한 모델을 작성하고 렌더링을 위해 View로 전달한다.
- Model
1. 개요
-
Dispatcher servlet
- 사용자의 요청을 맨 먼저 받는다.(Front Controller로서 작동한다.)
- 요청을 적절한 Controller에게 전달해주는 역할
(애플리케이션으로 들어오는 모든 요청을 intercept 하고 Handler(Controller)에 디스패치(전달)한다.) - 요청을 처리하기 위해 Controller에 대한 Handler Mapping을 참조한다.
- Spring이 만들어준다.
-
Handler Mapping
- 요청이 들어오면 어떤 Controller가 수행되어야 하는지 알려주는 매핑 테이블
(특정 요청을 처리하는 적절한 Controller를 찾아 응답한다.) - 요청 URL과 Controller 클래스 간의 매핑은 XML 설정 또는 Annotation으로 수행된다.
- 요청이 들어오면 어떤 Controller가 수행되어야 하는지 알려주는 매핑 테이블
-
Controller
- 실제로 사용자의 요청을 처리한다.(다른 business/service 클래스를 호출하여 요청을 처리)
- 결과를 View로 전달될 Model 객체에 저장
-
View Resolver
- 적절한 View를 찾아준다.
(Logical 이름으로부터 Physical view file를 찾는다.)
- 적절한 View를 찾아준다.
-
View
- 필요한 Model을 가져와 보여준다.
- Physical view file -> JSP, HTML, XML, Velocity template
참고)
Spring이 제공하는 클래스: Dispatcher Servlet, Handler mapping, View Resolver
2. 요구되는 Configuration
Maven Configuration(POM.xml)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javatpoint</groupId>
<artifactId>SpringMVC</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>SpringMVC Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
</dependency>
</dependencies>
<build>
<finalName>SpringMVC</finalName>
</build>
</project>
Web deployment descriptor(web.xml)
- DispatcherServlet
- 스프링 컨테이너 (WebApplicationContext)를 인스턴스 화한다.
- 요청 --> DispatcherServlet --- instantiate
---> Spring Container( Controller(Bean), Special Beans(HandlerMapping, ViewResolver) )
- DI 컨테이너와 마찬가지로 WebApplicationContext에는 일부 구성 메타 데이터(XML 파일)가 제공되어야 한다.- <init-param>에서 설정해준 sales-context.xml이 메타 데이터(sales- 예시로 sales 관련 요청을 설정한 파일명이다.
- <init-param>에서 설정해준 sales-context.xml이 메타 데이터(sales- 예시로 sales 관련 요청을 설정한 파일명이다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>SpringMVC</display-name>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/sales-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- ContextLoadListener
- 공유 Bean을 포함하는 Spring Container를 인스턴스화 한다.
- DispatcherServlet으로 작성된 Bean은 ContextloaderListener로 작성된 Bean을 참조할 수 있다.
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>
참고)
Spring Container: Bean을 생성해주고, 의존성을 주입해주는 역할
공유되는 Bean들은 ContextLoadListener에 넣어두고
그렇지 않은 Bean들은 DispatcherServlet에 넣어둔다.(그렇지 않은 Bean 예시: Controller)
web.XML 설정 및 Spring MVC Configuration 예시
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:app-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>my-dispatcher-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:web-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my-dispatcher-servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 공유 빈을 관리하는 contextLoadListener의 설정 파일 명은 app-config.xml
- 공유하지 않은 빈을 관리하는 DispatcherServlet의 설정 파일 명은 web-config.xml
app-config.xml
- 모든 서블릿과 필터에서 공유될 수 있는 root Spring container의 설정을 지정한다.
- 애플리케이션 시작 시 Spring의 ContextLoaderListener에 의해 로드된다.
- 이 파일은 기본적으로 비어 있다.
web-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<mvc:annotation-driven />
<resources mapping="/resources/**" location="/resources/" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<context:component-scan base-package="com.memorynotfound" />
</beans>
- <mvc:annotation-driven />
- 지정된 패키지의 파일을 스캔하기 위해 annotation 기반 접근 방식을 사용하도록 프레임 워크에 지시한다. - <resources mapping.../>
- 정적 리소스를 HTTP GET 요청과 직접 매핑한다.
따라서 Image, JavaScript, CSS 등의 리소스들은 Controller를 거치지 않아도 된다. - <bean class="... InternalResourceViewResolver">
- Controller가 반환한 Logical Name에 따라 프레임워크가 실제 JSP 파일을 찾을 수 있게 경로 매핑을 해준다.
-> 예를 들어, Controller가 sales를 반환한다면 /WEB-INF/views/sales.jsp로 매핑 - context:component-scan.../>
- Annotation 기반 strategy를 사용할 때 어떤 패키지를 스캔할지 Spring Container에 알려준다.
- Container에 annotation이 달린 Controller를 auto-detect(자동 감시)하도록 한다.
- Container는 패키지 아래의 모든 클래스를 스캔한다.
3. Model
- 모델은 결과의 일부를 포함한다.
- Controller에서 뷰로 객체를 전달하는 데 사용.
- 명명 된 객체의 컬렉션
MVC 아키텍처 Model
- 브라우저 request
- Presentation Layer(Front Controller, View, Controller)의 Front Controller(DispatcherServlet)가 요청을 받음
- DispatcherServlet은 적절한 Controller를 찾아 호출
- Controller는 Service Layer에 데이터 처리를 요청
- Service Layer -> DAO Layer 호출
- DAO Layer에서 받은 데이터를 Model 형태로 Service Layer를 타고 Controller에게 전달
- Controller는 Model을 DispatcherServlet에 전달
- DispatcherServelt은 View에 Model을 전달
- View는 Model을 가지고 HTML을 렌더링 후 DispatcherServlet에 전달
- DispatcherServlet은 브라우저에 response
Model Implement
- java.util.map( public String getData(Map <String, Object> model){...} )
- 요구사항: Model 속성을 저장할 때 key의 자료형이 Spring 이어야 한다.
@RequestMapping("/data")
public String getData(Map<String, Object> model){
String data = service.getData();
model.put("data", data)
return "home"
}
- Spring에서 제공한 Model( public String getData(Model model){... } )
- Map 사용의 단점은 모델의 속성 이름들을 일일이 정해야 한다는 단점이 있다.
- Model 인터페이스는 addAttribute()같이 Model 속성을 채우는 편리한 메서드를 제공한다.
- addAttribute()는 자동으로 모델 속성을 생성해준다는 점을 제외하면 Map의 put 메서드와 같다.
@RequestMapping("/data")
public String getData(Model model){
List<Data> datas = service.getData();
model.addA
- ModelMap 객체는 Spring에서 제공한다.( public String getData (ModelMap model){ ... } )
- Model 인터페이스에서 좀 더 편한 기능 제공
- addAttribute() 메서드에 체이닝 기법 적용
- Model 인터페이스에서 좀 더 편한 기능 제공
@RequestMapping("/data")
public String getData(ModelMap model){
model.addAttribute("Lname", "kwon")
.addAttribute("Fname","DH");
return "home"
}
4. @Controller
- Spring Controller는 @Controller annotation이 달린 bean이다.
- @RequestMapping
- URL을 전체 클래스 또는 특정 핸들러 메서드에 맵핑하는 데 사용된다.
@Controller
public class HomeController{
@RequestMapping(value="/", method=RequestMethod.GET)
public String home(Local local, Model model){
Date date = new Date();
DataFormat dataFormat = DataFormat.getTimeInstance(DataFormat.LONG, DataFormat.LONG, locale);
String formatteDate = dataFormat.format(data);
model.addAttribute("serverTime", formattedData);
return "home";
}
}
- 이 메서드는 "home"이라는 View를 리턴한다.
-> "web-config.xml"파일(DispatchServlet의 설정 파일)에 지정된 viewResolver에 의해 실제 파일을 찾는다.
- @RequestParam
- URL에 쿼리 값을 받을 수 있다.
@RequestMapping(value= "/login", method = RequestMethod.GET)
public String doLogin(@RequestParam String username,
@RequestParam String password){
return ...;
}
References
https://memorynotfound.com/spring-mvc-xml-configuration-example/
https://howtodoinjava.com/spring-mvc/contextloaderlistener-vs-dispatcherservlet/
https://www.javatpoint.com/spring-mvc-tutorial
'Spring > 이론' 카테고리의 다른 글
Spring Security (0) | 2020.03.30 |
---|---|
Spring Web Form (0) | 2020.03.25 |
DB 연동(with Spring JDBC) (0) | 2020.03.09 |
관점 지향 프로그래밍(AOP, Aspect Oriented Programming) (0) | 2020.03.07 |
의존성 주입(Dependency Injection) (0) | 2020.03.05 |
댓글