JSP 피피티 07 Spring Framework
FrameWork란?
프로그램의 기본 흐름이나 구조를 정하고, 이 구조에 자신의 코드를 추가하는 방식으로 개발할 수 있도록 하는 프로그래밍의 기본 틀
일반적인 FrameWork 구조
Presentation Layer(HTML, CSS, Javascript) -> View |
UI를 담당하는 구성 요소들이 들어간다. 웹과 모바일에 따라 사용되는 기술이 변경된다. |
Business Logic Layer(Controller -> Service Layer) |
서비스 계층이라고도 하며, 기능적인 요구사항이 직접적으로 반영되는 계층이다. |
Data Access Layout(DAO -> Model) |
저수준의 데이터 처리를 전문적으로 담당한다. DATABASE에 대한 직접적인 제어가 포함된다. |
Database |
Oracle, MySQL등의 DBMS 시스템 |
Spring FrameWork의 특징
-경량 컨테이너?
간단하다.
-POJO(Plain Old Java Object) 프로그램의 구현
특정한 인터페이스를 구현하거나 상속받을 필요없다. 일반적인 Java코드와 기존에 존재하는 라이브러리들을 그대로 활용
-확장성이 높다
다른 프레임워크들과의 통합을 지원하기 때문에 이미 수많은 라이브러리가 Spring에서 지원되고 있고 또 라이브러리를 별도로 분리하기에도 용이하다.ex)정부표준 프레임워크
-제어반전(IoC Inversion of Control)
개발자가 프레임워크의 기능을 호출하는 형태가 아니라 프레임워크가 개발자의 코드를 호출하기 떄문에 개발자는 전체를 직접 구현하지 않고 자신의 코드를 부분적으로 "끼워넣기"하는 형태로 구현할 수 있다. 이는 개발자로 하여금 구현하고자 하는 특정 분야의 기능에 집중할 수 있도록 한다. 프레임워크가 객체의 생성, 소멸과 같은 라이프 사이클을 관리하며 Spring으로부터 필용한 객체를 얻어올 수도 있다.
-트랜잭션의 지원
트랙잭션의 관리를 어노테이션이나 XML로 설정할 수 있기 때문에, 개발자가 별도의 소스코드를 개발할 필요가 없다.
트랜잭션의 정의
트랜잭션(Transaction)은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미한다.
트랜잭션의 특징
1. 트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위이다.
2. 사용자가 시스템에 대한 서비스 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업단위이다.
3. 하나의 트랜잭션은 Commit되거나 Rollback된다.
트랜잭션의 성질
Atomicity(원자성)
1. 트랜잭션의 연산은 데이터베이스에 모두 반영되든지 아니면 전혀 반영되지 않아야 한다.
2. 트랜잭션 내의 모든 명령은 반드시 완벽히 수행되어야 하며, 모두가 완벽히 수행되지 않고 어느하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 한다.
Consistency(일관성)
1. 트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 변환한다.
2. 시스템이 가지고 있는 고정요소는 트랜잭션 수행 전과 트랜잭션 수행 완료 후의 상태가 같아야 한다.
Isolation(독립성,격리성)
1. 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행중에 다른 트랜잭션의 연산이 끼어들 수 없다.
2. 수행중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다.
Durablility(영속성,지속성)
1. 성공적으로 완료된 트랜잭션의 결과는 시스템이 고장나더라도 영구적으로 반영되어야 한다.
트랜잭션 연산 및 상태
Commit연산
1. Commit 연산은 한개의 논리적 단위(트랜잭션)에 대한 작업이 성공적으로 끝났고 데이터베이스가 다시 일관된 상태에 있을 때, 이 트랜2. 잭션이 행한 갱신 연산이 완료된 것을 트랜잭션 관리자에게 알려주는 연산이다.
Rollback연산
1. Rollback 연산은 하나의 트랜잭션 처리가 비정상적으로 종료되어 데이터베이스의 일관성을 깨뜨렸을 때, 이 트랜잭션의 일부가 정상적으로 처리되었더라도 트랜잭션의 원자성을 구현하기 위해 이 트랜잭션이 행한 모든 연산을 취소(Undo)하는 연산이다.
2. Rollback시에는 해당 트랜잭션을 재시작하거나 폐기한다.
스프링 Hello World 뽑기
스프링 지도
1. src/main/webapp/WEB-INF/web.sml << 웹설정 파일
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.xsd">
<web-app>에서 version을 3.1로 바꾸고 태그 거의 끝부분 'web-app_3_1.xsd'로 바꾸기
web.xml에 UTF-8관련 파라미터/ beans관련 설정하기 ↓↓↓
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.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>
<!-- UTF-8 관련 파라미터 설정 --> ←새롭게 추가된 부분
<filter>
<filter-name>encodingFilterUTF8</filter-name>
<filter-class>org.springframework.web.filter.CharcterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilterUTF8</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- beans 관련 설정 --> ←새롭게 추가된 부분
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</context-param>
<context-param>
<param-name>spring.liveBeansView.mbeanDomain</param-name>
<param-value>dev</param-value>
</context-param>
</web-app>
2. pom.xml << maven 설정
-<properties> 태그의 내용들은 pom.xml에서 사용되는 변수값 이다.
-이 변수들을 다른 설정에서 참조하게 된다.
-Slf4j는 2.x이상 버전이 log4j와 충돌하기 때문에 현 버전을 유지한다.
<?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>study.spring</groupId>
<artifactId>practicespring</artifactId>
<name>PracticeSpring</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.8</java-version> ←1.6 에서 1.8로 바꿈
<org.springframework-version>3.1.1.RELEASE</org.springframework-version> ←3.1.1.RELEASE에서 5.2.8.RELEASE로 바꿈
<org.aspectj-version>1.6.10</org.aspectj-version> ←1.6.10 에서 1.9.6로 바꿈
<org.slf4j-version>1.6.6</org.slf4j-version> ←1.6.6 에서 1.7.30로 바꿈
</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.10</version> ← 2.9 에서 2.10로 바꿈
<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>3.8.1</version> ← 2.5.1 에서 3.8.1로 바꿈
<configuration>
<source>${java-version}</source> ← 1.6 에서 ${java-version}로 바꿈
<target>${java-version}</target> ← 1.6 에서 ${java-version}로 바꿈
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version> ← 1.2.1 에서 3.0.0로 바꿈
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
URL을 보면 http://localhost:8080/practicespring/ 이렇게 되어있다. 일단 이 URL로 들어오면 servlet-context.xml를 거쳐서 HomeController.java에 있는 home라는 메서드가 실행된다.
home( ) 메서드는 문자열(String)로 home를 리턴하는데 리턴된 home은 servlet-context.xml로 넘어가게 된다. servlet-context.xml에서는 home 문자열을 받아서 앞에는 /WEB-INF/views/ 를 뒤에는 .jsp를 붙이게 된다. 결론적으로 /WEB-INF/views/home.jsp 가 되면서, 프로젝트 내에 있는 home.jsp 파일이 실행되는 것이다.
출처: https://all-record.tistory.com/157 [세상의 모든 기록]
위의 예제를 실습하는 과정에서 404에러가 떴다. 아무리 찾아도 도통 이유를 찾을수 없어 전에 했던 프로젝트에서 web.xml파일을 그대로 복사해다 썼더니 실행 되었다. 원래 있던 코드로 되돌려 놓고 한 글자 한 글자 비교해본 결과
<!--beans 관련 설정-->에서 <param>태그중 하나를 <parma>라고 잘못 쓴 것을 발견했다.
Spring 프로젝트 구조
- 컨트롤러 기본구조
-HomeController.java - Spring Path 설정 파일
-servlet-context.xml - 리소스 사용하기
-style.css
-script.js
-home.jsp
컨트롤러 기본구조
HomeController.java
package study.spring.practicespring;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 lombok.extern.slf4j.Slf4j;
/**
* Handles requests for the application home page.
*/
@Slf4j
@Controller
public class HomeController {
//private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
//logger.info("Welcome home! The client locale is {}.", locale);
log.debug("Hello Spring");
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
}
- @Controller
모든 컨트롤러 클래스가 정의해야 하는 어노테이션 - @RequestMapping(value="/" method=RequestMethod.GET)
웹페이지의 URL과 접근방식 정의 - public String home(Locale locale, Model model)
메서드 파라미터 필요에 따라 다양한 패턴이 존재함 model 객체를 통해서 view에 데이터 전달 - model.addAttribute("serverTime", formattedDate);
View에 Key와 value의 쌍으로 데이터 전달 View에서는 JSTL을 통해 Model2와 같은 방식으로 데이터에 접근 - return "home";
이 컨트롤러가 호출할 View의 경로 void형인 경우 메서드 이름을 View 이름으로 인식한다.
Mapping??? 매핑???? (더보기 클릭)
Spring Path 설정파일
src/main/webapp/WEB_INF/spring/appServlet/servlet-context.xml
-리소스(CSS,JS,IMG등) 경로
-View의 경로
-컨트롤러나 서비스 구현체의 경로
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="study.spring.practicespring" />
</beans:beans>
- <!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
MVC 패턴의 Controller를 허용하는 옵션(수정금지) - <resources mapping="/resources/**" location="/resources/" />
URL상에서의 /resources/** 형태의 경로를 실제 프로젝트 상의 /webapp/resources 폴더에 연결하는 경로 설정 옵션(수정가능) - <beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
view파일의 경로와 확장자 형식 지정 - <context:component-scan base-package="study.spring.practicespring"/>
컨트롤러 클래스나 서비스 구현체 글래스가 위치하는 패키지들을 명시 필요에 따라 추가할수 있다.
※location에 값 쓸때 '/' 잘 보기 저거 앞뒤로 '/'가 있는거를 안썼더니 자꾸 404에러나서 또 한참 찾느라 시간 낭비 ㅜㅜ