[웹 개발] 5. Spring

0woogie·2023년 8월 22일
0

STS

  • 스프링에 특화된 이클립스 (수정)
  1. OpenJDK 설치
  2. STS 설치
    https://dist.springsource.com/release/STS/index.html
    - Spring Tool Suite 3.9.8 >> "spring-tool-suite-3.9.8.RELEASE-e4.11.0-win32-x86_64.zip" 선택

Spring Module

2 Architecture Layer

그림 첨부

DI

프로젝트 생성

ee레벨에서는 src 폴더의 다각화가 필요

  • src/main/java: JavaCode
  • src/main/resources: 설정문서
  • src/test/java: 테스트 파일

HelloTestApp01

  • Hello와 Heltest 결합도 높음
  • HelloTestApp01에서 Hello 객체를 직접 생성하기 때문
  • 재사용성 안 좋음

HelloTestApp03UseSpring

  • DI 컨테이너 == "설정 문서를 읽어서 자바 클래스(Bean)를 생성하는 Program"
    - 여기서의 컨테이너는 BeanFactory (Tomcat 같은 것만 컨테이너가 아님!!)
  • 설정문서(hello.xml)로 Factory에서 Bean 생성
  • HelloTestApp03UseSpring는 getBean으로 Bean을 가져와서 사용
  • 개발자는 객체 생성하는 것이 아니라 Bean 설정 문서를 만듬

DAOTestApp04UsingSpring

  1. new 키워드가 사라졌다
  2. 실체클래스명(MemberDAOImpl)이 보이지 않고 ~~

MyBatis

MyBatis 설치


설치 -> mybatis.org
A: DAOImpl에서 DB에 접근하는 Level에서 필요
B: Full Stack Level에서 필요

작업의 흐름 (sp03_MyBatis_Sample)

  1. 테이블 세팅
create table mysawon(
num number constraint mysawon_num_pk primary key,
id varchar2(20) constraint mysawon_id_nn not null,
pwd varchar2(20),
name varchar2(40),
age number(3),
hiredate date,
constraint mysawon_id_uq unique(id));

create sequence mysawon_seq
increment by 1
start with 1;
  1. vo 작성 (MySawon.java)
  2. MyBatis Framework 설정문서를 등록
    • dbconn.properties (DB 서버 정보)
    • SqlMapConfig.xml (MyBatis Framework의 핵심 문서)
  3. ~~mapping.xml
    5-1. MySawonAppTest01.java 작성 (insert)
    5-2. MySawonAppTest01.java 작성 (selectList)

MyBatis Framework -> Business Logic Layer

(그림에서의 w: wiring, c: component)
(Project: sp04_MyBatis)

DI 흐름에 따른 개발 순서
1. 테이블
2. vo
3. SqlMapConfig.xml
4. MyBatisTestApp101
5. UserDAO
6. MyBatisUserDAOImpl
7. MyBatisTestApp102

Business Logic Layer

  • Business Logic Layer는 두 개로 나뉨
  1. Persistence Layer: 데이터를 raw하게 가져옴
  2. Service Layer: 가져온 데이터를 가공해서 클라이언트 쪽으로 넘겨줌

코드에서는 인터페이스로 소통하고
설정문서에서는 실체클래스가 노출된다.

DI 완성

  • MyBatisUserDAOImpl12
  • MyBatisUserServiceImpl12

Bean 5개 등록

xml -> annotation

  • MyBatisUserDAOImpl13
  • MyBatisUserServiceImpl13

workshop03

작업의 순서

  1. TABLE 작성
  2. vo 작성
  3. MyBatis Framework 설정문서
  4. MyBatisUnitTest
  5. DAO/~
    "sql의 id값이 기능의 이름이 된다"

Maven

버전 충돌 문제 발생

5: MyBatis
6: SpringDI + MyBatis
9~13: DI

각각에 필요한 라이브러리 끌어다 쓰다보니 충돌하는 문제 발생 -> mybatis-3.2.8 필요해짐

=> 충돌문제 때문에 maven 등장

Spring MVC

  • project 생성 ~ pom.xml

  • 그림 업로드
    빨간색 부분은 알아서 만들어준다

  1. container 올라갈때 dd(web.xml) 파일 읽어들임
  2. dd 파일을 이용해 appServlet 생성
  3. web.xml에서 beans.xml(빈 생성문서)을 찾아서

MyBatis Framework - Spring DI - SpringMVC 연결하기

  • sp08_Spring

작업의 순서

  1. TABLE 작성
  2. vo 작성
  3. MyBatis Framework 설정문서
  4. MyBatisUnitTest
  5. DAO/DAOImpl/Service/ServiceImpl 작성
    "sql의 id값이 template 기능의 이름이 된다"
    =============================
  6. index.jsp/FruitController 작성

web.xml

  • 한글 처리
  • classpath - webapp이 아닌 src 밑에서 파일을 찾게 됨

Bean 설정문서의 모듈화

itemservice.xml -> businessLogicBean.xml + presentationBean.xml

presentationBean.xml: Presentation Layer에 대한 빈 설정문서
businessLogicBean.xml: Business Logic Layer + MyBatis Framework에 대한 빈 설정문서

web.xml / businessLogicBean.xml / presentationBean.xml 코드 업로드
(web.xml <- WAS)
(businessLogicBean.xml / presentationBean.xml <- DI Container)

000

sp09_SpringMVC_Product

작업 순서

  1. pom.xml de1~7

동기화 문제

INSERT 문 작성시
PK에 해당하는 컬럼값이 디비에서 자동증가하는 값일 때는 주의해야 한다.
pvo와 rvo 동기화가 되지 않으면 문제가 발생
(Sequence Number, Sysdata: DB에서 자동적으로 증가되는 값들)
1) 먼저 디비에서 PK값을 증가시킨다
2) 증가된 그 값을 pvo에 setter로 주입
결과적으로 pvo와 디비테이블(rvo)을 완벽하게 동기화시킨다.

<insert id="addProduct" parameterType="myProduct">
	<selectKey keyProperty="id" order="BEFORE" resultType="int">
		SELECT myproduct_seq.nextVal FROM dual
	</selectKey>
	INSERT
	INTO myproduct(id, name, maker, price)
	VALUES(#{id}, #{name}, #{maker}, #{price})
</insert>

addProduct 호출 (INSERT) -> pvo에 id 값이 담기게 된다 -> 동기화 문제 해결

sp10

정적쿼리 -> 동적쿼리

SpringMVC에서 비동기통신 사용하기

  • 비동기처리 -> 결과페이지가 따로 없음
  • InternalResourceViewResolver 사용할 수 없음
  • BeanNameViewResolver 필요
  • sp12, sp13 -> sp11

sp11 기준

  1. Ajax 사용 (BookList.jsp)
  2. Controller 작성 (desc 작성)
  3. pom.xml에 의존 추가
<!-- 8. Ajax Json -->
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.1</version>
</dependency>
  1. servlet-context.xml
<beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
	<beans:property name="order" value="0" />		
</beans:bean>
	
<beans:bean name="JsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
	<beans:property name="contentType" value="text/html;charset=utf-8" />	</beans:bean>

AOP

Aspect Oriented Programming

  • 서비스가 호출되는 것을 AOP 메커니즘이 감지해서 위빙함
  • JoinPoint: Advice Class가 Target Class에 위빙하는 위치
  • PointCut: JoinPoint의 상세한 스펙

AspectJ

  • <aop:config> -> Annotation

  • AspectJ 적용 전
    - solv.xml

    <!-- Target(2) member, product || Advice(1) logging -->
    <bean id="member" class="spring.aop.solv.MemberService"/>
    <bean id="product" class="spring.aop.solv.ProductService"/>
    <bean id="logging" class="spring.aop.solv.LoggingAdvice"/>
    
    <!-- advice의 어떤 기능이 target 메소드 호출될 때 위빙되는지 자세히 설정 -->
    <aop:config>
        <aop:aspect id="loggingAspect" ref="logging">
            <aop:pointcut expression="execution(* spring.aop..*(..))" id="pc"/>
            <aop:around method="logPush" pointcut-ref="pc"/>
        </aop:aspect>
    </aop:config>
  • AspectJ 적용
    - Annotation 작성 (LoggingAdvice.java)

    @Aspect
    public class LoggingAdvice {
        private Log log = LogFactory.getLog(getClass());
    
        //target 메서드의 리턴타입이 String이고 spring 패키지 아래에 있는 모든 하위패키지 중에서
        //클래스 이름이 Product로 시작하는 클래스, 함수명이 delete로 시작하고 인자값이 1개 이상
        @Around("execution(String spring..Product*.delete*(..))")
        public void logPush(ProceedingJoinPoint pjp) throws Throwable{
            log.info("\ncheck...before logging...");
    
            Object ret=pjp.proceed();//target으로 위빙되는 시점
            System.out.println("target method return..."+ret);
        }
    }
- anno.xml

```
<!-- Target(2) member, product || Advice(1) logging -->
<bean id="member" class="spring.aop.anno.MemberService"/>
<bean id="product" class="spring.aop.anno.ProductService"/>
<bean id="logging" class="spring.aop.anno.LoggingAdvice"/>

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
```
profile
정리하고 다듬기 위한 공간

0개의 댓글