웹_프론트_백엔드/JAVA프레임윅기반_풀스택

2020.06.22

shine94 2020. 6. 22. 09:17

1. Spring AOP(Aspect Oriented Programming)

1) 핵심관점(=핵심기능)

 : 객체지향 프로그래밍에서 각 객체안에는 중요한 기능들로 구성되어 있고

   AOP에서는 이러한 주요기능을 핵심관점(=핵심기능)이라고 한다.

 

2) Cross-Cutting Concern(횡단관점, 공통기능)

 : 핵심기능들을 잘 살펴보면 각 핵심기능들 전반에 걸쳐있는 공통적인 기능들이 있고
   AOP에서는 이러한 공통적인 것들을 횡단관점, 횡단관심사, Aspect라고 한다.

 

 

2. AOP(Aspect Oriented Programming)의 목적 
 : 프로그래머 들의 관심(concern)사를 핵심기능으로부터 분리
   즉, Separation of Cross-Cutting Concern
   결국, AOP는 개발자의 염두(concern)사항을 별도의 관심사(Aspect)로 분리해내어
   코드 개발시 핵심기능에 더 집중할 수 있게 한다.

 

 

3. 간단한 AOP 용어 정리

1) AOP
** 기존의 코드(핵심코드)를 수정하지 않고도 원하는 공통관심사(cross-concern)와 핵심코드를 엮는(weaving) 기술
** 즉 엮는다(weaving)는 AOP의 기본 동작

 

2) Target

** 공통코드와 관심코드가 분리된 핵심코드를 가지고 있는 객체

** 스프링 AOP에서 실체는 클래스


3) Proxy

** Target을 감싸고 있다

** Target 호출 코드가 수행될 때면, Target을 호출하기 전이나 후, 혹은 중간에 Advice를 weaving하여 실행

** 스프링AOP 에서 실체는 객체(수동생성, 혹은 Auto-proxy 자동생성)

 

4) JoinPoint
** Target 객체가 가진 메소드

** Proxy가 Advice를 weaving 주는 대상
** 스프링 AOP에서 실체는 메소드


5) Advice
** 삽입되어 엮어지는 코드

** 즉, 공통코드와 관심코드
** 스프링 AOP에서 실체는 메소드


6) Weaving
** Proxy가 PointCut 설정에 따라 JoinPoint가 호출될 때마다 Advice를 엮어서 실행해주는 동작

** 스프링 AOP에서 실체는 Proxy의 동작

 

7) Pointcut
** Advice가 어느 JoinPoint(들)에 적용될지 설정

** 스프링 AOP에서 실체는 설정(@어노테이션 혹은 XML)

 

8) Advisor
** Advice + Pointcut
** 스프링 AOP에서 실체는 메소드 + @어노테이션

 

9) Aspect
** 공통관점 사항들의 집합

** 즉, Advisor들을 모아놓은 객체
** 스프링 AOP에서 실체는 클래스

 

 

4. Spring에서 AOP 프로그래밍 구현 방법
방법1) XML 설정으로 구현

방법2) @Aspect 와 같은  어노테이션들로 구현 (*추천*)

 

 

5. STS07_AOP1, [방법1] XML 설정으로 구현

** AOP 관련 dependency 설정 필요 : 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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework.samples</groupId>
  <artifactId>STS07_AOP</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>

		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>3.2.3.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<hibernate.version>4.2.1.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.11</junit.version>

	</properties>
	
	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		
		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		
		
		
		<!-- spring AOP -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-context-support</artifactId>
		    <version>${spring-framework.version}</version>
		</dependency>
		
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-aop</artifactId>
		    <version>${spring-framework.version}</version>
		</dependency>
		
		<dependency>
		    <groupId>org.aspectj</groupId>
		    <artifactId>aspectjweaver</artifactId>
		    <version>1.7.4</version>
		</dependency>
		
		<dependency>
		    <groupId>org.aspectj</groupId>
		    <artifactId>aspectjrt</artifactId>
		    <version>1.6.11</version>
		</dependency>
		


	</dependencies>	
</project>

 

[추가] 직접 타이핑해도 되나 https://mvnrepository.com 사이트의 도움 받아도 된다.

1) spring-context-support 

2) spring-aop

3) aspectjweaver

 

[추가] spring-context-support, spring-aop는 spring-core와 버전이 같아야 한다.
        만약 버전이 다르면 ClassNotFoundException 발생

         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-context-support</artifactId>
             <version>${spring-framework.version}</version>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-aop</artifactId>
             <version>${spring-framework.version}</version>
         </dependency>

 

** pom.xml 선택 후 우클릭 > Maven > Update Maven Project

 

** [src/main/java] com.lec.beans > abstract Service.java

package com.lec.beans;

public abstract class Service {
	public abstract void doAction();   // 추상메소드
	
	// 테스트용 : 메소드 호출정보 출력
	public void printInfo() {
		String className = this.getClass().getSimpleName();
		StackTraceElement[] stackTrace = new Throwable().getStackTrace();
		String methodName = stackTrace[1].getMethodName();
		System.out.println(className + " 의 " + methodName + "() 호출");
	}
	
}

 

** [src/main/java] com.lec.beans > Logger.java

package com.lec.beans;

// log in / log out 동작과 같은
// 공통기능 / 관심기능(concern) 이 담긴 객체

// 나중에 Advice 로 사용되는 코드 

public class Logger {
	
	public void logIn() {
		System.out.println("## 로그인 처리 ##");
		
		try {			
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void logOut() {
		System.out.println("## 로그아웃 처리 ##");
		
		try {			
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}

 

** [src/main/java] com.lec.spring.aop01 > MyService11.java

package com.lec.spring.aop01;

import com.lec.beans.Logger;
import com.lec.beans.Service;

public class MyService11 extends Service {

	// 관심사(공통기능) 코드가 함께 섞여 있는 경우.
	
	@Override
	public void doAction() {
		new Logger().logIn();  // 공통기능
		
		// 핵심기능
		System.out.println("MyService11 의 doAction()");
		
		new Logger().logOut();  // 공통기능
	}

}

 

** [src/main/java] com.lec.spring.aop01 > MyService12.java

package com.lec.spring.aop01;

import com.lec.beans.Logger;
import com.lec.beans.Service;

public class MyService12 extends Service {

	// 관심사(공통기능) 코드가 함께 섞여 있는 경우.
	
	@Override
	public void doAction() {
		new Logger().logIn();  // 공통기능
		
		// 핵심기능
		System.out.println("MyService12 의 doAction()");
		
		new Logger().logOut();  // 공통기능
	}

}

 

** [src/main/resources] aopCtx1.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	
	<bean name="service1" class="com.lec.spring.aop01.MyService11"/>
	<bean name="service2" class="com.lec.spring.aop01.MyService12"/>


</beans>

 

** [src/main/java] com.lec.spring.aop01 > AopMain01.java

package com.lec.spring.aop01;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.lec.beans.*;

public class AopMain01 {

	public static void main(String[] args) {
		System.out.println("Main 시작");
		AbstractApplicationContext ctx = 
				new GenericXmlApplicationContext("classpath:aopCtx1.xml");
		System.out.println("ctx생성");

		Service service1 = ctx.getBean("service1", Service.class);
		Service service2 = ctx.getBean("service2", Service.class);
		
		service1.doAction();	// 핵심코드
		System.out.println();

		service2.doAction();	// 핵심코드
		System.out.println();
		
		ctx.close();
		System.out.println("Main 종료");
	} // end main()

} // end class

 

** [src/main/java] com.lec.spring.aop02 > MyService21.java

package com.lec.spring.aop02;

import com.lec.beans.Service;

public class MyService21 extends Service {

	@Override
	public void doAction() {
		
		// 공통 기능 없다??
		
		printInfo();	// 핵심 기능
		
	}
	
	public void hahaha() {
		System.out.println("hahaha");
	}

}

 

** [src/main/java] com.lec.spring.aop02 > MyService22.java

package com.lec.spring.aop02;

import com.lec.beans.Service;

public class MyService22 extends Service {

	@Override
	public void doAction() {
		
		// 공통 기능 없다??
		
		printInfo();	// 핵심 기능
		
	}

}


** [src/main/java] com.lec.spring.aop02 > LogAspect.java

package com.lec.spring.aop02;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

import com.lec.beans.Logger;

// Aspect : Advisor 들을 모아놓은 객체
// Advisor : Advice + Pointcut
// Advice : 공통 기능

// 첫번째 방법. 어노테이션 사용
// ↓ 이 클래스가 Aspect 역할을 할 클래스 임을 명시
@Aspect
public class LogAspect {
	
	@Pointcut("within(com.lec.spring.aop02.*)")
	public void pc1() {}

	@Pointcut("within(com.lec.spring.aop02.*)")
	public void pc2() {}
	
	
	//@Before("within(com.lec.spring.aop02.*)")	// Pointcut
	@Before("pc1()")
	public void beforAdvice() {
		System.out.print("[Before] ");
		new Logger().logIn();	// 공통코드. Advice!
	}
	
	
	//@After("within(com.lec.spring.aop02.*)")	// Pointcut
	//@After("execution(* com.lec.spring.aop02.MyService22.*(..))")
	//@After("pc2()")
	@After("execution(* com.lec.spring.aop02.*2.*(..))")
	public void afterAdvice() {
		System.out.print("[After] ");
		new Logger().logOut();
	}

	
	// Around advice : 메소드 실행을 제어하는 가장 강력한 코드
	//	직접 해당 메소드를 호출하고 결과나 예외처리도 가능.
	@Around("within(com.lec.spring.aop02.*)")
	public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
		// joinPoint 메소드 이름
		String signatureStr = joinPoint.getSignature().toShortString();
		
		// joinPoint 메소드 수행전
		System.out.println("[Around] " + signatureStr + " 시작");
		long st = System.currentTimeMillis();  // 시작시간 기록
		
		try {
			// joinPoint 메소드 수행
			Object obj = joinPoint.proceed();
			return obj;
		} finally {			
			// joinPoint 메소드 수행후
			long et = System.currentTimeMillis();  // 종료시간 기록
			System.out.println("[Around] " + signatureStr + " 종료, 경과시간: " + (et - st));
		}
		
	} // end aroundAdvice()
	
}


** [src/main/resources] aopCtx2.xml

<?xml version="1.0" encoding="UTF-8"?>
<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:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
	
	
	<!-- Proxy 객체 자동생성, @Aspect 있는 빈 객체들을 찾아서 공통 기능으로 등록 -->
	<aop:aspectj-autoproxy/>
	
	<bean id="logAop" class="com.lec.spring.aop02.LogAspect"/>
	
	<bean name="service21" class="com.lec.spring.aop02.MyService21"/>
	<bean name="service22" class="com.lec.spring.aop02.MyService22"/>


</beans>

 

[추가] Namespaces에서 aop와 context 추가하기


** [src/main/java] com.lec.spring.aop02 > AopMain02.java

package com.lec.spring.aop02;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.lec.beans.*;

public class AopMain02 {

	public static void main(String[] args) {
		System.out.println("Main 시작");
		AbstractApplicationContext ctx = 
				new GenericXmlApplicationContext("classpath:aopCtx2.xml");
		System.out.println("ctx 생성");

		Service service21 = ctx.getBean("service21", Service.class);
		Service service22 = ctx.getBean("service22", Service.class);
		
		service21.doAction();
		System.out.println();

		service22.doAction();
		System.out.println();
		
		((MyService21)service21).hahaha();
		
		ctx.close();
		System.out.println("Main 종료");
	} // end main

} // end class

 

** [src/main/java] com.lec.beans > abstract ServiceEx.java

package com.lec.beans;

public abstract class ServiceEx extends Service {

	public abstract void doWorking();
	public abstract void quitAction();

}

 

** [src/main/java] com.lec.spring.aop03 > MyServiceEx31.java

package com.lec.spring.aop03;

import com.lec.beans.ServiceEx;

public class MyServiceEx31 extends ServiceEx {

	@Override
	public void doWorking() {printInfo();}

	@Override
	public void quitAction() {printInfo();}

	@Override
	public void doAction() {printInfo();}

}


** [src/main/java] com.lec.spring.aop03 > MyServiceEx32.java

package com.lec.spring.aop03;

import com.lec.beans.ServiceEx;

public class MyServiceEx32 extends ServiceEx {

	@Override
	public void doWorking() {printInfo();}

	@Override
	public void quitAction() {printInfo();}

	@Override
	public void doAction() {printInfo();}

}


** [src/main/java] com.lec.spring.aop03 > LogAspect3.java

package com.lec.spring.aop03;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LogAspect3 {
	
	@Pointcut("within(com.lec.spring.aop03.*)")
	public void pc1() {}
	
	@Pointcut("within(com.lec.spring.aop02.*)")
	public void pc2() {}
	
	@Pointcut("execution(* com.lec.spring.aop*.My*.*Action(..))")
	public void pc3() {}
	
	@Pointcut("execution(* com.lec.spring.*3.My*.do*(..))")
	public void pc4() {}
	
	//@Before("pc1()")  // 3, 4, 5, 6, 7, 8
	//@Before("pc2()")  // 1, 2
	//@Before("pc3()")	// 1, 2, 3, 5, 6, 8
	//@Before("pc4()")	// 3, 4, 6, 7
	//@Before("pc1() || pc2()")		// 1, 2, 3, 4, 5, 6, 7, 8
	//@Before("pc1() && pc2()")		// 없음
	//@Before("!pc1()")				// 1, 2
	//@Before("pc3() && !pc4()")	// 1, 2, 5, 8
	@Before("!(pc3() && pc4())")	// 1, 2, 4, 5, 7, 8
	public void beforeAdvice() {
		System.out.print("[Advice] ");
	}

}


** [src/main/resources] aopCtx3.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
	
		
	<aop:aspectj-autoproxy/>
	
	<bean id="logAop" class="com.lec.spring.aop03.LogAspect3"/>
	
	<bean name="service21" class="com.lec.spring.aop02.MyService21"/>
	<bean name="service22" class="com.lec.spring.aop02.MyService22"/>

	<bean name="serviceEx31" class="com.lec.spring.aop03.MyServiceEx31"/>
	<bean name="serviceEx32" class="com.lec.spring.aop03.MyServiceEx32"/>


</beans>


** [src/main/java] com.lec.spring.aop03 > AopMain03.java

package com.lec.spring.aop03;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.lec.beans.*;

public class AopMain03 {

	public static void main(String[] args) {
		System.out.println("Main 시작");
		AbstractApplicationContext ctx = 
				new GenericXmlApplicationContext("classpath:aopCtx3.xml");
		System.out.println("ctx생성");

		
		Service service21 = ctx.getBean("service21", Service.class);
		Service service22 = ctx.getBean("service22", Service.class);
		
		ServiceEx serviceEx31 = ctx.getBean("serviceEx31", ServiceEx.class);
		ServiceEx serviceEx32 = ctx.getBean("serviceEx32", ServiceEx.class);
		
		
		service21.doAction();		// 1
		service22.doAction();		// 2
		
		serviceEx31.doAction();		// 3
		serviceEx31.doWorking();	// 4
		serviceEx31.quitAction();	// 5

		serviceEx32.doAction();		// 6
		serviceEx32.doWorking();	// 7
		serviceEx32.quitAction();	// 8
		
		ctx.close();
		System.out.println("Main 종료");
	} // end main

} // end class

 

 

6. PointCut expression
 : PointCut 설정에 사용되는 구문을 PointCut 표현식(expression)이라 하며 다양한 방법으로 지정 가능하다.

 


7. PointCut 표현식 구문

 : PCD(AspectJ 표현식) 

 


8. PCD(PointCut Designator)의 종류
** execution : 메소드를 기준으로 PointCut 설정

** within : 특정한 클래스 기준으로 PointCut 설정
** this : 주어진 인터페이스를 구현한 객체를 대상으로 PointCut 설정
** args : 특정한 매개변수를 가지는 대상으로 PointCut 설정
** @annotation : 특정한 어노테이션이 적용된 대상으로 PointCut 설정
** @target : 클래스에 특정 어노테이션이 있는 경우 PointCut 설정
** @args : 매개변수에 특정 어노테이션이 적용된 경우 PointCut 설정

 

 

9. STS08_AOP2[방법2] @Aspect 와 같은  어노테이션들로 구현 (*추천*)

** AOP 관련 dependency 설정 : 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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework.samples</groupId>
  <artifactId>STS08_AOP2</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>

		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>3.2.3.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<hibernate.version>4.2.1.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.11</junit.version>

	</properties>
	
	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		
		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		
		
		<!-- spring AOP -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-context-support</artifactId>
		    <version>${spring-framework.version}</version>
		</dependency>
		
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-aop</artifactId>
		    <version>${spring-framework.version}</version>
		</dependency>
		
		<dependency>
		    <groupId>org.aspectj</groupId>
		    <artifactId>aspectjweaver</artifactId>
		    <version>1.7.4</version>
		</dependency>
		
		<dependency>
		    <groupId>org.aspectj</groupId>
		    <artifactId>aspectjrt</artifactId>
		    <version>1.6.11</version>
		</dependency>


	</dependencies>	
</project>

 

** pom.xml 선택 후 우클릭 > Maven > Update Maven Project 클릭

 

** [arc/main/java] com.lec.beans > Logger.java

package com.lec.beans;

// log in / log out 동작과 같은
// 공통기능 / 관심기능(concern) 이 담긴 객체

// 나중에 Advice 로 사용되는 코드 

public class Logger {

	public void logIn() {
		System.out.println("## 로그인 처리 ##");
		
		try {			
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void logOut() {
		System.out.println("## 로그아웃 처리 ##");
		
		try {			
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void logAdvice() {
		System.out.print("[Advice]");
	}
	
}

 

** [arc/main/java] com.lec.beans > Service.java

package com.lec.beans;

public abstract class Service {
	public abstract void doAction();   // 추상메소드
	
	// 테스트용 : 메소드 호출정보 출력
	public void printInfo() {
		String className = this.getClass().getSimpleName();
		StackTraceElement[] stackTrace = new Throwable().getStackTrace();
		String methodName = stackTrace[1].getMethodName();
		System.out.println(className + " 의 " + methodName + "() 호출");
	}
	
}

 

** [arc/main/java] com.lec.spring.sop01 > MyService11.java

package com.lec.spring.aop01;

import com.lec.beans.Logger;
import com.lec.beans.Service;

public class MyService11 extends Service {

	// 관심사(공통기능) 코드가 함께 섞여 있는 경우.
	
	@Override
	public void doAction() {
		new Logger().logIn();  // 공통기능
		
		// 핵심기능
		System.out.println("MyService11 의 doAction()");
		
		new Logger().logOut();  // 공통기능
	}

}

 

** [arc/main/java] com.lec.spring.sop01 > MyService12.java

package com.lec.spring.aop01;

import com.lec.beans.Logger;
import com.lec.beans.Service;

public class MyService12 extends Service {

	// 관심사(공통기능) 코드가 함께 섞여 있는 경우.
	
	@Override
	public void doAction() {
		new Logger().logIn();  // 공통기능
		
		// 핵심기능
		System.out.println("MyService12 의 doAction()");
		
		new Logger().logOut();  // 공통기능
	}

}

 

** [arc/main/resources] aopCtx1.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


	<bean name="service1" class="com.lec.spring.aop01.MyService11"/>
	<bean name="service2" class="com.lec.spring.aop01.MyService12"/>


</beans>

 

** [arc/main/java] com.lec.spring.aop01 > AopMain01.java

package com.lec.spring.aop01;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.lec.beans.*;

public class AopMain01 {

	public static void main(String[] args) {
		System.out.println("Main 시작");
		AbstractApplicationContext ctx = 
				new GenericXmlApplicationContext("classpath:aopCtx1.xml");
		System.out.println("ctx생성");

		Service service1 = ctx.getBean("service1", Service.class);
		Service service2 = ctx.getBean("service2", Service.class);
		
		service1.doAction();	// 핵심코드
		System.out.println();

		service2.doAction();	// 핵심코드
		System.out.println();
		
		ctx.close();
		System.out.println("Main 종료");
	} // end main()

} // end class

 

** [src/main/java] com.lec.spring.aop02 > MyService21.java

package com.lec.spring.aop02;

import com.lec.beans.Service;

public class MyService21 extends Service {

	@Override
	public void doAction() {
		
		// 공통 기능 없다??
		
		printInfo();	// 핵심 기능
		
	}
	
	public void hahaha() {
		System.out.println("hahaha");
	}

}

 

** [src/main/java] com.lec.spring.aop02 > MyService22.java

package com.lec.spring.aop02;

import com.lec.beans.Service;

public class MyService22 extends Service {

	@Override
	public void doAction() {
		
		// 공통 기능 없다??
		
		printInfo();	// 핵심 기능
		
	}

}

 

** [src/main/resources] aopCtx2.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

	<!-- 공통 기능 클래스를 빈 객체로 생성 -->
	<bean id="logger" class="com.lec.beans.Logger"/>
	
	<bean name="service21" class="com.lec.spring.aop02.MyService21"/>
	<bean name="service22" class="com.lec.spring.aop02.MyService22"/>
	
	<aop:config>
	
		<!-- config 안에 aspect 들을 설정 -->
		<aop:aspect id="logAspect1" ref="logger">
			<!-- aspect의 pointcut 설정 -->
			<aop:pointcut expression="within(com.lec.spring.aop02.*)" id="pc1"/>
			<!-- aspect의 advice 설정 -->
			<aop:before pointcut-ref="pc1" method="logIn"/>
		</aop:aspect>

		<aop:aspect id="logAspect2" ref="logger">
			<aop:after pointcut-ref="pc1" method="logOut"/>
		</aop:aspect>
		
	</aop:config>
	

</beans>

 

** [src/main/java] com.lec.spring.aop02 > AopMain02.java

package com.lec.spring.aop02;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.lec.beans.*;

public class AopMain02 {

	public static void main(String[] args) {
		System.out.println("Main 시작");
		AbstractApplicationContext ctx = 
				new GenericXmlApplicationContext("classpath:aopCtx2.xml");
		System.out.println("ctx 생성");

		Service service21 = ctx.getBean("service21", Service.class);
		Service service22 = ctx.getBean("service22", Service.class);
		
		service21.doAction();
		System.out.println();

		service22.doAction();
		System.out.println();
		
		((MyService21)service21).hahaha();
		
		ctx.close();
		System.out.println("Main 종료");
	} // end main

} // end class

 

** [src/main/java] com.lec.beans > ServiceEx.java

package com.lec.beans;

public abstract class ServiceEx extends Service {

	public abstract void doWorking();
	public abstract void quitAction();

}

 

** [src/main/java] com.lec.spring.aop03 > MyService31.java

package com.lec.spring.aop03;

import com.lec.beans.ServiceEx;

public class MyServiceEx31 extends ServiceEx {

	@Override
	public void doWorking() {printInfo();}

	@Override
	public void quitAction() {printInfo();}

	@Override
	public void doAction() {printInfo();}

}


** [src/main/java] com.lec.spring.aop03 > MyService32.java

package com.lec.spring.aop03;

import com.lec.beans.ServiceEx;

public class MyServiceEx32 extends ServiceEx {

	@Override
	public void doWorking() {printInfo();}

	@Override
	public void quitAction() {printInfo();}

	@Override
	public void doAction() {printInfo();}

}

 

** [src/main/resources] aopCtx03.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

	<bean id="logger" class="com.lec.beans.Logger"/>
	
	<bean name="service21" class="com.lec.spring.aop02.MyService21"/>
	<bean name="service22" class="com.lec.spring.aop02.MyService22"/>

	<bean name="serviceEx31" class="com.lec.spring.aop03.MyServiceEx31"/>
	<bean name="serviceEx32" class="com.lec.spring.aop03.MyServiceEx32"/>
	
	<aop:config>
		<aop:pointcut expression="within(com.lec.spring.aop03.*)" id="pc1"/>
		<aop:pointcut expression="within(com.lec.spring.aop02.*)" id="pc2"/>
		<aop:pointcut expression="execution(* com.lec.spring.aop*.My*.*Action(..))" id="pc3"/>
		<aop:pointcut expression="execution(* com.lec.spring.*3.My*.do*(..))" id="pc4"/>
		
		<aop:aspect id="logAspect3" ref="logger">
			<!-- pc1 ~ pc4까지 적용해보기 -->
			<!-- 
			<aop:before method="logAdvice" pointcut-ref="pc4"/>
			-->
			
			<!-- pointcut-ref 대신 pointcut으로 직접 지정 가능 -->
			<aop:after method="logOut" pointcut="within(com.lec.spring.aop03.*)"/>
		</aop:aspect>
	</aop:config>
	
</beans>

 

** [src/main/java] com.lec.spring.aop03 > AopMain03.java

package com.lec.spring.aop03;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.lec.beans.*;

public class AopMain03 {

	public static void main(String[] args) {
		System.out.println("Main 시작");
		AbstractApplicationContext ctx = 
				new GenericXmlApplicationContext("classpath:aopCtx3.xml");
		System.out.println("ctx생성");

		
		Service service21 = ctx.getBean("service21", Service.class);
		Service service22 = ctx.getBean("service22", Service.class);
		
		ServiceEx serviceEx31 = ctx.getBean("serviceEx31", ServiceEx.class);
		ServiceEx serviceEx32 = ctx.getBean("serviceEx32", ServiceEx.class);
		
		
		service21.doAction();		// 1
		service22.doAction();		// 2
		
		serviceEx31.doAction();		// 3
		serviceEx31.doWorking();	// 4
		serviceEx31.quitAction();	// 5

		serviceEx32.doAction();		// 6
		serviceEx32.doWorking();	// 7
		serviceEx32.quitAction();	// 8
		
		ctx.close();
		System.out.println("Main 종료");
	} // end main

} // end class

 

 

10. Spring MVC 구조

1) Spring MVC Project
 : 스프링 프레임워크에서 제공하는 프로젝트 중에 MVC 웹어플리케이션 개발용 프로젝트

 

2) JSP MVC model2와 구조상으로 많이 비슷하나

   스프링에서 제공하는 다양한 메커니즘들로 인해, 개발과 유지보수에 더 좋다.

   그러한 이유로 오늘날 대부분의 기업용 웹 어플리케이션은 스프링 웹어플리케이션으로 작성된다.

 

 

11. STS09_MVC

** Spring MVC Project 생성

 : 우클릭 > New > Spring Legacy Proejct 클릭

> 프로젝트 이름 설정, pring MVC Project 템플릿 선택 > Next 클릭

> 최초인 경우 다운로드(Maven 필요 라이브러리) 여부 확인창 뜸, Yes 클릭

> base-package명 지정(반드시 3단계 이상 작성, base-package 명을 3단계로 하면 3번째가 컨텍스트 이름이 된다)

> 하단 부분의 Maven 필요 라이브러리 다운로드됨, 다 다운 받으면 작업하면 됨...!!

** 프로젝트 폴더 구성

   [컨트롤러] Dispatcher에서 전달된 요청을 처리

   [DispatcherServlet] 클라이언트의 요청을 최초에 받아 컨트롤러에게 전달

   [src/main/webapp] 웹 root

   [webapp/resources] 리소스

   [스프링 설정파일 *.xml] 스프링 컨테이너 설정 파일

   [뷰 *.jsp]

   [web.xml] DispatcherServlet 서블릿 맵핑, 스프링 설정 파일 위치 정의

   [pom.xml] Maven 설정 파일

 

** src > main > webapp > WEB-INF > 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>
		<filter-name>encodingFilter</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>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>                 
	</filter-mapping>
	

</web-app>

 

** src > main > webapp > WEB-INF > spring > sppServlet > servlet-context.xml

<?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/** 로 요청들어오는 건 DispatcherServlet 이 처리하지 말고
		/resources/ 폴더에서 찾게 하기 
	-->
	<resources mapping="/resources/**" location="/resources/" />
	<resources mapping="/myRes/**" location="/myRes/" />

	<!-- 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="com.lec.sts09_mvc" />
	
	
	
</beans:beans>

 

** [src/main/java] com.lec.sts09_mvc > HomeController.java

package com.lec.sts09_mvc;

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;

/**
 * Handles requests for the application home page.
 */
@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);
		
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate );
		
		return "home";
	}
	
}

 

** src > main > webapp > Hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello</title>
</head>
<body>
안녕하세요
</body>
</html>

 

** src > main > webapp > WEB-INF > views > home.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world!  
</h1>

<P>  The time on the server is ${serverTime}. </P>
<img src="<%= request.getContextPath() %>/myRes/img/bgdesert.jpg"/><br><br>

<img src="/sts09_mvc/resources/img/bgdesert.jpg"/><br><br>
<img src="<%= request.getContextPath() %>/resources/img/bgdesert.jpg"/><br><br>
<img src="${pageContext.request.contextPath }/resources/img/bgdesert.jpg"/><br><br>

</body>
</html>

 

 

12. 스프링 MVC 동작 흐름

1) 모든 Request는 DispatcherServlet이 받아서 일괄 관리하거나 처리  

 

2) DispatcherServlet은 request를 처리할 컨트롤러 선택(Handler Mapping) 
 : reqeust 한 URL을 분석하여, 어떤 컨트롤러 클래스에서 처리할지 선택(이 일을 수행하는 것은 HandlerMapping 객체)

 

3) request 처리, 결과는 ModelAndView
 : Spring MVC에서는 handler 수행결과(model, view)를 HandlerAdapter를 통해

   ModelAndView 객체에 담아 DiapatcherServlet에 넘긴다.  
   [참고! JSP MVC Model2의 request 결과는 request의 attribute에 넣어서 컨트롤러에 넘김]

 

4) ViewResolver 뷰(jsp) 선택
 : 컨트롤러의 수행 결과는 Model과 View이다. 

   예시에서 메소드는 Model은 Model 객체에 담았고 View는 "home"을 리턴,

   DispatcherServlet은 View 결과를 ViewResolver에게 넘겨주어 "/WEB-INF/views/home.jsp"라는 결과를 받아 온다.

 

5) view에 model을 넘겨주어 response
 : DispatcherServlet은 webapp(웹 루트) 밑에서 뷰를 찾고 그 view에 model을 넘겨 주어 response한다.

 

 

12. 한글 깨짐(스프링 인코딩 문제)

 : web.xml에 <filter> 추가

   <filter>
       <filter-name>encodingFilter</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>encodingFilter</filter-name>
       <url-pattern>/*</url-pattern>                 
   </filter-mapping>

 

 

13. 웹 어플리케이션은..? 
1) 원하는 형태의 request URL을 받아서


2) 그 URL에 따른 동작(handler)를 찾아서 (mapping) 수행하고


3) 원하는 뷰로 response한다.

 

 

14. @Controller 클래스 안의 @RequestMapping 지정된 메소드를 핸들러(Handler)라고도 한다.

 

 

15. STS10_Request

[프로젝트명] STS10_Request

[프로젝트] Spring Legacy Project
[템플릿] Spring MVC Project

[base-package] com.lec.sts10_request

 

** src > main > webapp > WEB-INF > 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>encodingFilter</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>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>                 
	</filter-mapping>


</web-app>

 

** [src/main/java] com.lec.sts10_request > HomeController 서블릿

package com.lec.sts10_request;

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;

/**
 * Handles requests for the application home page.
 */
@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);
		
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate );
		
		return "home";
	}
	
	@RequestMapping(value="/common")	// /common 으로 요청이 오면
	public String cccmmm() {			// cccmmm() 핸들러가 수행되고,
		return "comn";					// --> /WEB-INF/views/comn.jsp 를 리턴하면서 response 되게 한다.
	}
	
}

 

** [src/main/java] com.lec.sts10_request.controller > MemberController 서블릿

package com.lec.sts10_request.controller;

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

@Controller
@RequestMapping(value = "/member")  // -> /member 로 시작하는 request 만 처리
public class MemberController {
	
	@RequestMapping(value = "/save")  // -> /member + /save => /member/save
	public String saveMember() {
		return "member/save";
	}
	
	@RequestMapping(value = "/load")  //   -> /member/load
	public String loadMember() {
		return "member/load";
	}
	
//	@RequestMapping(value = "/search")  // -> /member/search  (중복!)
//	public String searchMember() {
//		return "member/search";
//	}
	
}

 

** src > main > webapp > WEB-INF > views > comn.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	String servlet_request_uri = (String)request.getAttribute("javax.servlet.forward.request_uri");
	String conPath = request.getContextPath();
	
	//System.out.println(servlet_request_uri);
	//System.out.println(conPath);
	
	String servlet_reqpath = servlet_request_uri.substring(conPath.length());
	
	String uri = request.getRequestURI();
	String reqPath = uri.substring(conPath.length());
	String url = request.getRequestURL().toString();
	
	// jsp 파일명
	String jspFile = uri.substring(uri.lastIndexOf("/") + 1, uri.length());
	String jspName = uri.substring(uri.lastIndexOf("/") + 1, uri.length() - 4);
	
	request.setAttribute("jspName", jspName);
%>    
    
    
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= jspName %></title>
<link rel="stylesheet" type="text/css" 
	href="${pageContext.request.contextPath }/CSS/sts_common.css">
</head>
<body>
<hr>
<div class="sts">
<b>Servlet</b><br>
request URI : <span><%= servlet_request_uri %></span><br>
context path : <span><%= conPath %></span><br>
request path : <span><%= servlet_reqpath %></span><br>
VIEW file : <span><%= jspFile %></span><br>
<hr>
<b>VIEW(JSP)</b><br>
url : <span><%= url %></span><br>
VIEW Path : <span><%= reqPath %></span><br>
uri : <span><%= uri %></span><br>
</div>


</body>
</html>

 

** src > main > webapp > WEB-INF > views > home.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
${serverTime}
<jsp:include page="/common"/>

 

** src > main > webapp > WEB-INF > views > member > search.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:include page="/common"/>

 

** src > main > webapp > WEB-INF > views > member > info.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
${mbAge }<br>
${mbName }<br>
<jsp:include page="/common"/>

 

** src > main > webapp > WEB-INF > views > member > find.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
${mbName }<br>
${mbDate }<br>
<jsp:include page="/common"/>

 

** src > main > webapp > WEB-INF > views > member > doMember.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:include page="/common"/>

 

** src > main > webapp > WEB-INF > views > member > save.jsp 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:include page="/common"/>


** src > main > webapp > WEB-INF > views > member > load.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:include page="/common"/>

 

** src > main > webapp > WEB-INF > spring > sppServlet > servlet-context.xml

<?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/" />
	<resources mapping="/CSS/**" location="/CSS/" />

	<!-- 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="com.lec.sts10_request" />
	
	
	
</beans:beans>

 

** src > main > webapp > CSS > sts_common.css

@charset "UTF-8";

div.sts span {
	color: blue;
}

 

 

16. 기본적인 Controller 클래스 제작 흐름
1) @Controller를 이용한 클래스 생성

2) @RequestMapping을 이용한 요청 경로 지정

3) 요청 처리 메소드(handler) 구현

4) 뷰 이름 혹은 ModelAndView 리턴

 

 

17. 핸들러 메소드 동작
1) @RequestMapping으로 request를 받아서

2) 필요한 동작들(ex: 트랜잭션) 수행, DAO 혹은 Command 등의 객체 사용

3) 결과는 Model에 담고 뷰 지정 > 합해서 ModelAndView로 담아 리턴 가능

 

 

18. jsp:include page의 주소 부분이 일반적인 jsp 주소로 기재되어 있지 않아서 에러 발생(이클립스 문제)
 : JSP 에러 검사 중 파일이 있는지를 캐치해주는 부분을 꺼주면 됨

 

원하는 프로젝트 선택 후 우클릭 > Properties 클릭

> Validation > JSP Syntax

> Enable project specific Settings 선택, included fragment file not found > Ignore 세팅

'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글

2020.06.29  (0) 2020.06.29
2020.06.23  (0) 2020.06.23
2020.06.19  (0) 2020.06.19
2020.06.18  (0) 2020.06.18
2020.06.17  (0) 2020.06.17