7.24 Spring Framework (Spring MVC)구조
DI 의존성 주입 : 필요한 클래스를 스프링이 전달함. 우리가 만들어준 메소드 통해서 요청 처리를 스프링이 함.
(IOC 제어 역전. 관리를 스프링이 한다. )
AOP : 필수 기능은 아니지만 어쩔 수 없이 반복되는 코드를 한 번에 처리
프로젝트 빌드 관리도구 MAVEN
MAVEN repository에서 라이브러리 확인 시groupId, artifactId 확인 해야함.
MAVEN 라이브러리 다운시 파일 깨져서 라이브러리 정상 수행 안될때도 있음.
그때는 C:\Users\admin\.m2\repository 폴더 삭제하면 된다.(로컬 저장소)
(pom.xml 컴파일 시 다시 생성됨.)
프로젝트 구조
src/main/java : 자바코드
src/main/resources : 프로젝트 구동에 필요한 설정파일
webapp - resources : 정적 자원(url을 통해 브라우저가 직접 읽어가는것, img, media, script 등)
WEB-INF : 외부에서 직접적으로 파일에 접근 불가.(보안성 강화), 내부에서는 접근가능(포워드 방식으로 화면 사용 가능)
-servlet-context.xml-------------------------------------------------------------------------------------------------------
<!-- /resources/** 라고 요청이 들어오면 dispatcher servlet이 하지 않고 그냥 파일 찾겠다. -->
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
pom.xml : 프로젝트 생성 후 제일 먼저 확인.
properties: 사용자 정의형 필드 선언
<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>
<!-- 이 프로젝트에 필요한 라이브러리(jar파일 다운필요 x) -->
<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>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
scope:
컴파일, 런타임(실행시에만 필요한 라이브러리ex.jstl), 프로바이디드(컴파일o,런타임시 제외(서버에 등록되어있으니까)
개발시에는 포함되서 쓰다가 실제 배포할때는 제외됨), 테스트(실제 배포시 제외됨), 어느영역까지 쓸 수 있을 지 지정함. (scope지정 안되어있으면 컴파일(개발당시부터 배포까지 유지되는 것))
</dependency>
<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> <!-- 컴파일 시켰을 때 몇버전으로 컴파일 할지 정하는 java 버전 -->
<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>
WEB.XML
<!-- 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> <-어느 servlet이든 모두 사용가능한 Bean들의 정보 담는 곳
</context-param>
servlet-context.xml---------------------------- : application에 등록됨.
- <context:component-scan base-package="com.bitc.first" />
DispatcherServlet(servlet-context.xml)이 패키지에 있는 클래스 파일 중에서
어노테이션이 붙여져 있는 걸 스캔함, Spring으로 관리할 수 있도록 Bean으로 등록함.
- <annotation-driven />
RequestMapping 어노테이션이 있는 메소드가 있으면
HandlerMapping 클래스를 생성해서 HandlerMapping 에 해당 메소드 정보 등록함.
@Controller 클래스 에서
메소드 호출에 필요한 매개변수 dispatcher servlet이 무조건 전달해줌.
(ex.model : request랑 똑같음. 포워드로 화면 출력할때 request에 실어서 정보 전달...)
호출된 메소드의 반환값이 없으면 요청경로가 view 페이지가 됨.
(ex. @RequestMapping("doA") 에서 /WEB-INF/views/ + "doA" + ".jsp")
src/main/java 에서 사용하는
component-scan으로 Bean으로 등록되는 class annotation
@Controller : Presentation Layer에서 Controller를 명시하기 위해서 사용
@Service : Business Layer 에서 Service를 명시하기 위해서 사용
@Repository : Persistence Layer 에서 Data Access Object를 명시하기 위해 사용
@Component : 그 외의 의미를 두지 않는 class를 Bean으로 등록하고 관리하기 위해 사용
@component의 하위 형태로 @Controller, @Service, @Repository가 존재
jsp파일에
<%@ page session="false" %>
이렇게 되어있으면 세션 객체 사용 못하니 주의! true로 바꿔주기
package com.bitc.controller.home;
import javax.servlet.http.HttpServletRequest;
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;
@Controller
public class SampleController {
// /WEB-INF/views/ + "doA" + ".jsp"
@RequestMapping("doA")
public void doA() {
System.out.println("doA 호출");
}
@RequestMapping("doB")
public String doB() {
System.out.println("do B 호출");
return "home";
}
@RequestMapping("doC")
public String doC(HttpServletRequest request) {
request.setAttribute("modelTest", "doC test");
return "home";
}
@RequestMapping(value="doD", method=RequestMethod.GET)
public String doD(@RequestParam(name="msg", required = true) String message, Model model) {
/*
* 서블릿이 name값이 일치하는 파마리터의 값을 message에 담아준다.
* RequestParam 이라고 지정하면 무조건 값이 전달되어야 함. */
System.out.println("doD 호출 - "+ message);
model.addAttribute("msg", message);
return "result";
}
@RequestMapping(value="doE")
public String doE(
@RequestParam(name="msg" , required=false, defaultValue = "empty message") String message,
Model model
) {
/* required=false : 필수값이 아니라고 지정. null값 활용가능.
이땐, defaultValue로 기본값 지정가능. */
model.addAttribute("msg",message);
return "result";
}
@RequestMapping(value="doF", method=RequestMethod.POST)
public String doD(String msg, int age, Model model) {
/* @RequestParam 없이 불러오는 경우: name값이랑 변수이름이 같은 경우, 변수 이름으로 일치하는 파라미터 값을 찾음. int타입이면 parseint도 해줌
null값 사용 가능 근데 int 타입에 null 값 들어가면 오류 발생함 주의!
*/
model.addAttribute("msg",msg+":"+age);
return "result";
}
@RequestMapping("productWrite")
public String productWrite(
String name,
int price,
Model model,
ProductVO vo
) {
ProductVO product = new ProductVO(name,price);
System.out.println(product);
model.addAttribute("product",product);
System.out.println(vo);
// key 값이 생략되면
// ProductVO class 이름의 첫글자만 소문자로 key 값 지정
// key : productVO
네임값 = 필드값 , 기본생성자 존재, getter setter 존재 일때 사용 가능.
// 파라미터 값이 다 저장되있는 상태로 넘겨받을 수 있다.! 데이터 타입까지!! 자동으로 !!
model.addAttribute(vo);
return "product";
}
// GET방식으로 전달시 405 error 발생
//@RequestMapping(value="productWriteSubmit", method=RequestMethod.POST)
@PostMapping("productWriteSubmit")
public ModelAndView productWrite(ModelAndView mav, ProductVO prod) {
// mav.addObject("productVO",prod);
mav.addObject(prod);
mav.addObject("product",prod);
mav.setViewName("product");
return mav;
}
}