MVC 패턴
애플리케이션의 역할을 모델(Model), 뷰(View), 컨트롤러(controller)로 나누어 작업
Smalltalk-80 처음 소개
업무 서비스와 도메인 객체를 사용자 인터페이스로부터 분리, 하나 이상의 컨트롤러를 통해서 이들 사이 상호작용을 통제하는 아키텍처 패턴
MVC 모델 구성 요소
모델 : 데이터를 실어서 보내준다.
애플리케이션의 핵심적인 기능 제공
뷰와 컨트롤러 등록
데이터 변경 시 뷰와 컨트롤러에 통지
뷰
관련된 컨트롤러 생성, 초기화, 사용자에게 정보 표시
데이터 변경이 통지될 때 모델로부터 데이터를 읽어 처리
컨트롤러
사용자 입력을 이벤트로 받아들여 해석하여 모델에 대한 요청을 서비스하거나 뷰에 대한 요청을 표시
데이터 변경이 통지될 때 모델로부터 데이터 읽어와 처리
Front Controller 패턴 적용 – 컨트롤러가 중심이 되는 변형된 구조를 가짐 (이전 글의 BoardServlet 같은 전단서블릿)
동작
클라이언트가 컨트롤러에게 데이터 조회, 저장 등의 작업 요청
컨트롤러 : 서블릿으로 구현, 업무 로직 처리, 모델생성, 모델의 데이터 갱신, 뷰에 모델 전송, 뷰가 변경된 데이터 사용 가능하게 함
모델 : POJO Java 클래스로 구현, 데이터와 데이터처리에 필요한 메서드 포함, 자신이 관리하는 데이터에 집중
뷰 : JSP로 구현, 컨트롤러가 제공한 모델을 사용하여 데이터에 액세스하여 웹페이지(뷰)를 렌더링하여 응답을 생성하고 컨트롤러에 전달
컨트롤러는 클라이언트에 응답을 전송하고 서비스 종료
Spring MVC 매커니즘
BoardServlet 만들 필요 없이 기본으로 Servlet MVC 패턴은 Dispatcher Servlet을 제공한다.
또한 annotation도 제공한다.
1. 핸들러 맵핑 : 어떤 요청이 들어왔는지 확인한다.
2. 실질적으로 일을 처리할 컨트롤러를 선택한다.
3. 처리 결과를 Model(데이터를 실어준다)과 논리View(데이터를 표시)로 다시 Dispatcher Servlet으로 돌려준다.
4. ViewResolver, 진짜 물리적인 뷰를 찾아서 내용을 보여준다.
* 논리뷰와 물리적인 뷰의 차이는>
스프링 프로젝트 작성 두 가지 방법
Spring Boot를 이용하는 방법
File -> new -> Spring Start Project
Spring 템플릿 프로젝트를 이용하는 방법 (이 글에서 사용할 전통적인 방법)
File>New>Spring Legacy Project
New Spring Project 위저드의 Spring Project 화면에서 Spring MVC Project 항목을 선택, 프로젝트 이름: SpringProject01로 지정하고 next 선택
Project Setting>Spring MVC Project화면에서 패키지명을 com.pgm.project01로 지정, finish 선택
디렉토리 구조 살펴보기
src/main/java - controller (dto, dao...)
resources - 자원
webapp - view
--- 디렉토리는 * 두개, 파일이름은 하나
스피링 한글 처리 인코딩 필터
한글 처리 시 web.xml에 CharacterEncodingFilter 추가
<filter>
<filter-name>characterEncodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping> //필터 지정 위치
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
root 웹 애플리케이션 컨텍스트
IoC 컨테인 애플리케이션 컨텍스트는 트리 구조를 가짐
모든 애플리케이션 컨텍스트는 부모 애플리케이션 컨텍스트를 가질 수 있으며, 계층구조 안에 모든 애플리케이션 컨텍스트는 각각 독립적인 설정 정보를 사용하여 Spring 빈 객체를 생성하고 관리
의존성 주입을 위해 Spring 빈을 찾을 때 먼저 자신의 애플리케이션컨텍스트를 관리하는 Spring 빈 중에서 찾는다
자신을 관리하는 Spring 빈 중에 없는 경우 부모 애플리케이션 컨텍스에게 Spring 빈을 찾아 줄 것을 요청
계층구조를 따라 최상위 root 컨텍스트까지 요청 가능
컨트롤러 구현
데이터를 받는 두 가지 방법
데이터(커맨드) 객체 이용
Get /Post 방식 처리
실습하기
1. Spring Legacy Project 프로젝트를 생성한다.
스프링은 항상 디폴트 패키지를 적어야한다.
사용하지 않는 프로젝트는 클로즈 시켜서 닫아두어야 엉키는 등의 에러가 없다.
처음 플젝 만들 때마다 시작 전 구축이 빨라진 이유는 아래 사진처럼
디폴트로 받아야하는 라이브러리가 이미 생성되어있기 때문이다.
2. Maven Repository 바로가기
스프링의 장점! 직접 찾아 라이브러리를 넣어줄 필요없이
pom.xml에 라이브러리를 등록해놓으면 알아서 프로그램이 찾아간다.
프로젝트 아래 pom.xml을 수정한다.
. Maven을 사용하는 프로젝트에는 설정 파일인 pom.xml 파일이 있다.
POM은 Project Object Model의 약자
출처 : https://offbyone.tistory.com/163
pom.xml 수정 전 기본내용은?
//수정 전 기본내용
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lje</groupId>
<artifactId>exam01</artifactId>
<name>exam01</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>3.1.1.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
자바버전 수정, 스프링 현재버전(5.1.9)으로 바꾸고 junit 버전을 고친다.
스프링 현재버전 확인은 아래 홈페이지에서.
pom.xml 변경 후 플젝의 버전들이 자동으로 바뀐 것을 확인해볼 수 있다.
메이븐을 사용하여 프로젝트의 라이브러리 의존성을 관리하면 실제 .jar 파일들을 관리할 필요없이 pom.xml 파일만 잘 관리하며 되는 것
다른 방법으로는 Maven > Update Project 한 후 프로퍼티에 들어가 확인한다.
pom.xml 바뀐 코드
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lje</groupId>
<artifactId>exam01</artifactId>
<name>exam01</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.8</java-version>
<org.springframework-version>5.1.9.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
로딩 순서
실행 시 web.xml을 가장 먼저 읽는다. 스프링에서 루트는 webapp이다. (jsp의 WebContent와 같은 것)
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 디폴트서블릿 -->
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>characterEncodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
디폴트 패키지에 가서 컨트롤러를 보고, 그 후 RequestMapping 에 보면 / (루트,경로)가 적혀있다.
요청을 찾는다는 뜻.
TestController.java
package com.lje.exam01;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.lje.exam01.vo.MemberInfo;
@Controller
public class TestController {
@RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(HttpServletRequest req, Model model) {
String name = req.getParameter("name");
model.addAttribute("name", name);
return "test";
}
// public void test(){}해도 찾아진다.
// public String test(){return "test"; //논리뷰}
@RequestMapping("/input")
public String input() {
return "board/input";
}
// @RequestMapping(value="/memberPro", method=RequestMethod.POST)
// public String member(Request..??? request, Model model) {
// String id = request.getParameter("id");
// String pw = request.getParameter("pw");
// String name = request.getParameter("name");
// String tel = request.getParameter("tel");
// model.addAttribute("id", id);
// model.addAttribute("pw", pw);
// model.addAttribute("name", name);
// model.addAttribute("tel", tel);
// return "board/memberPro";
// }
@RequestMapping(value="/memberPro", method=RequestMethod.POST)
public String member(@RequestParam("id") String id,
@RequestParam("pw") String pw, Model model)
{
model.addAttribute("id", id);
model.addAttribute("pw", pw);
return "board/memberPro";
}
/* @RequestMapping("/view") */
public ModelAndView view() {
ModelAndView mv = new ModelAndView();
mv.addObject("id", "abcd");
mv.addObject("pw", "1234");
mv.setViewName("board/view");
return mv;
}
// 위랑 같은 내용 다른 문법
@RequestMapping("/view")
public String view(Model model) {
model.addAttribute("id", "abcd");
model.addAttribute("pw", "1234");
return "board/view";
}
@RequestMapping("/test2")
public String view2(@RequestParam("id")
String id, Model model) {
model.addAttribute("id", id);
return "board/view";
}
//@RequestMapping("/test3")
public String memberView(MemberInfo memberInfo ) {
return "board/view3";
}
//test3의 다른 방법
@RequestMapping("/test3")
public String memberView(HttpServletRequest request,
Model model) {
MemberInfo memberInfo = new MemberInfo();
memberInfo.setName(request.getParameter("name"));
memberInfo.setId(request.getParameter("id"));
memberInfo.setPw(request.getParameter("pw"));
memberInfo.setTel(request.getParameter("tel"));
model.addAttribute("memberInfo", memberInfo);
return "board/view3";
}
}
'Frameworks > Spring' 카테고리의 다른 글
Spring mybatis를 이용하여 게시판 만들기 (0) | 2019.08.28 |
---|---|
Spring MVC 패턴 스프링 게시판 만들기 (1) | 2019.08.27 |
CRUD MVC 패턴 총정리 : 게시판만들기 (0) | 2019.08.26 |
스프링 프레임워크 Spring Framework (2) Spring 개발 환경 설정 (0) | 2019.08.23 |
스프링 프레임워크 Spring Framework (1) 프레임워크 정의, 장점, 스트링프레임워크, 컨테이너 개념 (0) | 2019.08.23 |