★ DI (Dependency Injection)

스프링의 핵심 개념
객체사이의 의존 관계를 자기 자신이 아닌 외부에 의해서 설정된다는 개념이다
스프링에서는 설정파일을 사용하여 손쉽게 객체간의 의존관계를 설정하기에 스프링을 DI컨테이너라고 부르기도 한다.
DI 컨테이너는 어떤 클래스가 필요로 하는 인스턴스를 자동으로 생성, 취득하여 연결시켜주는 역활을 한다.
DI 컨테이너가 인스턴스를 생성하도록 하려면 프로그램 소스 내부에서 new 로 직접 생성하지 않고 설정파일에서 필요로 하는 클래스의 정보를 설정해주어야한다.

스프링은 각 클래스간의 의존관계를 관리하기 위한 방법
- Constructor Injection
- Setter Injection


★ Constructor Injection
: 생성자를 통해서 의존 관계를 연결시키는 것을 말한다.
: 생성자를 통해서 의존 관계를 연결하기 위해서는 XML 설정 파일에서 <bean>요소의 하위요소로
  <constructor-arg>를 추가해야 한다.

1. 객체를 전달할 경우에는 ref요소를 사용

[Foo.java]

public class Foo {
   private Bar bar;

   public Foo(Bar bar){
      this.bar = bar;
   }
}

[applicationContext.xml]

<bean id="foo"   class="Foo">
   <constructor-arg>
      <ref bean="bar" />
   </constructor-arg>
</bean>

<bean id="bar"   class="Bar" />


2. 전달인자가 2개이상인 경우
기본데이터 타입일 경우에는 <value>요소를 사용하여 의존관계를 연결시키기 위한 값을 지정

[Foo.java]
public class Foo {
 public   Foo(int a, String b){...}
}

[applicationContext.xml]

<bean id="foo"   class="Foo">
   <constructor-arg   index="1"   value="Hello" />
   <constructor-arg   index="0">
      <value>25</value>
   </constructor-arg>
</bean>

----------------------------------------------------------------

type 속성을 이용하여 지정

[applicationContext.xml]
<bean id="foo"   class="Foo">
   <constructor-arg   type="int"   value="25" />
   <constructor-arg   type="java.lang.String"   value="Hello" />
</bean>


★ Setter Injection
: setter메소드를 이용하여 의존 관계를 연결시키는 것을 말한다.
: <property>요소의 name 속성을 이용하여 값의 의존 관계를 연결시킬 대상이 되는 필드값을 지정한다

[Foo.java]

public class Foo {
   private Bar bar;

   public void setBar(Bar bar){
      this.bar = bar;
   }
}

[applicationContext.xml]

<bean   id="foo"   class="Foo">
   <property   name="bar"   ref="bar"></property>
</bean>

<bean   id="bar"   class="Bar" />


[실습]
Project : Chapter02
Project : Chapter02_SpringMaven


Project : Chapter02
Package   : sample01
Interface : MessageBean.java
Class     : MessageBeanImpl.java
            HelloSpring.java - main()

src       : applicationContext.xml


[문제 1]
Project    : Chapter02
Package    : sample02
Interface  : Calc.java
추상Method : public void calculate();
Class      : HelloSpring - main()
             CalcAdd.java
             CalcMul.java


[실행결과]
25 + 36 = xx
→ xml에서 CalcAdd를 빈(add)으로 Constructor Injection

25 * 36 = xx
→ xml에서 CalcMul를 빈(mul)으로 Setter Injection

-----------------------------------------

[문제 2]
Project    : Chapter02
Package    : sample03
Field      : name, kor, eng, math, tot, avg
Interface  : SungJuk.java
추상Method : public void calcTot();//총점계산
             public void calcAvg();//평균계산
             public void display();//출력
             public void modify();//수정

Class      : HelloSpring - main()
             SungJukImpl.java
             SungJukDTO.java
            

Constructor Injection를 이용하세요

[실행결과]
이름     국어 영어 수학    총점   평균
홍길동   97 100 95 xxx xx.xx

////////////////////////////////////////////////////

→ 수정하시오 (Setter Injection 이용)
이름 입력 : 코난
국어 입력 : 100
영어 입력 : 100
수학 입력 : 95

이름   국어   영어   수학   총점   평균
코난   100    100     98

-----------------------------------------
Package   : sample04
-----------------------------------------

★ 내용을 파일로 출력

Package    : sample04
Interface  : MessageBean.java
Class      : MessageBeanImpl.java
             HelloSpring.java - main()

Interface : Outputter.java
Class     : FileOutputter.java - 파일로 출력

-------------------------------------------

 

 

 

 

 

 

 

★ 스프링 AOP(Aspect Oriented Programming) - 관점지향프로그램
          OOP(Object Oriented Programming) - 객체지향프로그램


Aspect란
어플리케이션의 핵심 기능은 아니지만, 어플리케이션을 구성하는 중요한 요소이고, 부가적인 기능을 담당하는 요소

Aspect = Advice + Pointcut
어드바이저는 단순한 형태의 애스펙트라고 볼 수 있다

AOP란
어플리케이션의 핵심적인 기능에서 부가적인 기능을 분리해서 애스펙트라는 모듈로 만들어서 설계하고 개발하는 방법을 AOP(Aspect Oriented Programming)이라고 한다

AOP는 새로운 프로그래밍 패러다임이 아니라, OOP를 돕는 보조적인 기술이다

어플리케이션의 핵심기능을 따라 코딩하지 않고, 핵심기능 대신, 부가적인 기능을 바라보고 집중해서 설계하고 개발할 수 있다
어플리케이션을 부가기능 관점에서, 새롭게 바라볼 수 있게 해준다라는 의미로 AOP를 관점 지향 프로그래밍이라고도 한다

스프링이 제공하는 AOP는 프록시를 이용한다
프록시를 통해 타겟 오브젝트의 메소드가 호출될 경우, 프록시가 제어를 가로채고, InvocationHandler와 같은 오브젝트를 통해 타겟 메소드의 실행 전 후로 부가적인 기능을 실행한다


AOP 기술의 원조인 AspectJ는 프록시를 사용하지 않는 대표적인 AOP 기술이다
타깃 오브젝트를 뜯어고쳐서 부가기능을 직접 넣어주는 방식을 사용한다
소스코드를 고치는 것이 아니라, 컴파일된 타깃 클래스의 파일 자체를 수정하거나 클래스가 JVM에 로딩되는 시점을 가로채서 바이트코드를 조작한다

프록시를 사용하지 않고 클래스 파일 조작과 같은 복잡한 방법을 사용하는 이유는
1. 스프링과 같은 DI컨테이너의 도움이 필요없다
스프링과 같은 컨테이너가 사용되지 않는 환경에서 AOP 적용이 가능하다

2. 프록시보다 훨씬 강력하고 유연하다
프록시 방식은 타깃 오브젝트가 생성되고 난 후부터 적용이 가능하다
하지만 AspectJ는 어떤 순간에든지 적용이 가능하다
클래스 바이트코드를 직접 조작하는 것이기 때문에 거의 제한이 없다

대부분의 부가기능은 프록시 방식을 사용해 메소드의 호출 시점에 부여하는 것으로도 충분하다
AspectJ와 같은 고급AOP 기술은 바이트코드 조작을 위해 JVM의 실행옵션을 변경하고, 별도의 바이트코드 컴파일러를 사용하고, 특별한 클래스 로더를 사용하는 등 번거로운 작업이 필요하다

: 일반적으로 스프링의 AOP를 사용하고, 스프링의 AOP 수준을 넘어서는 기능이 필요하다면 AspectJ를 사용하는 것이다

: 핵심관심사항과 공통관심사항을 기준으로 프로그래밍함으로써 공통 모듈을 여러 코드에 쉽게 적용

: 공통관심사항을 구현한 코드를 핵심 로직을 구현한 코드에 삽입하는 것

: 핵심로직을 구현할 때 트랜잭션 적용이나 보안 검사와 공통 기능을 삽입할 필요가 없다


※ AOP 용어
1. Target : 부가기능을 부여할 대상, 핵심기능이 담긴 클래스

2. Advice : 부가기능을 담음 모듈

3. Joinpoint : Advice를 적용 가능한 지점을 의미
               메소드 호출, 필드 값 변경 등
               스프링의 프록시 AOP에서 조인 포인트는 메소드의 실행 단계뿐이다
               타깃 오브젝트가 구현한 인터페이스의 모든 메소드가 조인 포인트가 된다

4. Pointcut : 조인 포인트를 선별하는 기능을 정의한 모듈
              가능한 조인 포인트들 중에 실제로 부가기능을 적용할 것들을 선별한다
              클래스를 선정하고, 그 안의 메소드를 선정하는 과정을 거친다
              실제로 Advice가 적용되는 Joinpoint를 나타낸다


5. Proxy : 클라이언트와 타깃 사이에 존재하면서 부가기능을 제공하는 오브젝트
           클라이언트는 타깃을 요청하지만, 클라이언트에게는 DI를 통해 타깃 대신 프록시가 주입된다
           클라이언트의 메소드 호출을 대신 받아서 타깃에게 위임하며, 그 과정에서 부가기능을 부여한다
           스프링 AOP는 프록시를 이용한다

6. Advisor : 포인트컷과 어드바이스를 하나씩 갖고 있는 오브젝트
             AOP의 가장 기본이 되는 모듈이다
             스프링은 자동 프록시 생성기가 어드바이저 단위로 검색해서 AOP를 적용한다

7. Aspect : 다수의 포인트컷과 어드바이스의 조합으로 만들어진다
            보통 싱글톤 형태의 오브젝트로 존재한다
            어드바이저는 아주 단순한 애스펙트라고 볼 수 있다

8. Weaving : Advice를 핵심로직코드에 적용하는 것을 Weaving라고 한다.


: Advice를 Weaving하는 3가지 방식
- 컴파일 시에 Weaving
  AspectJ에서 사용하는 방식
  AOP가 적용된 클래스 파일이 생성된다

- 클래스 로딩 시에 Weaving
  AspectJ 5/6 버전이 컴파일 방식과 클래스 로딩방식을 함께 지원

- 런타임 시에 Weaving
  소스코드나 클래스 정보 자체를 변경하지 않는다
  프록시를 이용한다(핵심로직을 구현한 객체에 직접 접근하는 것이 아니라 중간에 프록시를 생성하여 프록시를 통해서 핵심로직을 구현한 객체에 접근한다.)
  프록시는 메소드가 호출될 때에만 적용할 수 있다(필드값 변경에 대해서는 적용 불가능)


: 스프링은 자체적으로 프록시 기반의 AOP를 지원한다
  메소드 호출 Joinpoint만 지원(필드값 변경과 같은 Joinpoint는 불가능)

: 스프링 AOP는 자바 기반이다.
  AspectJ는 Aspect를 위한 별도의 문법이 필요하다

: 대상 객체의 메소드를 실행하기 전/후에 원하는 기능을 삽입(Around Advice)하는데 캐시기능, 성능 모니터링 기능과 같은 Aspect를 구현


Project : Chapter03
          Chapter03_SpringMaven

Project : Chapter03
Package : sample01(XML)
Interface : MessageBean.java
Class     : HelloSpring.java - main()
     MessageBeanImpl.java
     LoggingAdvice.java  - 공통관심사항

src : acQuickStart.xml


Project : Chapter03_SpringMaven
Package : sample01(어노테이션)
Interface : MessageBean.java
Class : HelloSpring.java
 MessageBeanImpl.java
 LoggingAdvice.java 

src : acQuickStart.xml


★ 필요한 JAR
aspectjweaver-1.8.10.jar

spring-aop-4.2.5.RELEASE.jar
spring-beans-4.2.5.RELEASE.jar
spring-context-4.2.5.RELEASE.jar
spring-core-4.2.5.RELEASE.jar
spring-expression-4.2.5.RELEASE.jar

commons-logging-1.2.jar

-----------------------------------------
인터페이스를 구현하면 기본적으로 스프링은 인터페이스에 기초하여 프록시를 만든다
MessageBean bean = (MessageBeanImpl)context.getBean("messageBeanImpl"); - error
MessageBean bean = (MessageBean)context.getBean("messageBeanImpl");


만약
인터페이스 없이 바로 클래스로 적용하려면
MessageBean bean = (MessageBeanImpl)context.getBean("messageBeanImpl");
<aop:config proxy-target-class="true">
</aop:config> 
-----------------------------------------

 

 

 

 

 

 

 

★ 스프링과 JDBC

: 스프링은 JDBC를 비롯하여 ORM프레임워크(myBatis, 하이버네이트, JPA(Java Persistence API))를 지원한다

: 스프링의 목표는 인터페이스에 의한 개발인데 DAO는 데이터베이스에서 데이터를 읽거나 쓰는 수단을 제공하기 위해 존재하며, 반드시 인터페이스를 통해 외부에 제공돼야 한다.
서비스 객체는 인터페이스를 통해서 DAO에 접근한다
서비스 객체를 특정 데이터 액세스 구현체에 결합시키지 않음으로써 테스트를 용이하게 한다
DAO인터페이스는 DAO구현과 서비스 객체 사이에서 느슨한 결합이 유지될 수 있게 한다


서비스 객체         → DAO 인터페이스
UserInsertAction         UserDAO               
                           ↑
                      DAO 구현 객체
                        UserDAOImpl


: 스프링은 데이터베이스 연동을 위한 템플릿 클래스를 제공함으로써
Connection, Statement(PreparedStatement), ResultSet등을 생성하고 처리한 다음 close(반환)하는 JDBC의 중복된 코드를 줄일 수 있다

: JDBC는 무조건 SQLException의 예외만 발생하므로 정확히 Connection에서 발생했는지 아니면 Statement에서 발생했는지 따져봐야한다. JdbcTemplate클래스는 SQLException이 발생하면 스프링이 제공하는 예외 클래스중 알맞는 것으로 변환해서 발생한다.
스프링은 JDBC보다 다양한 예외 계층을 제공하고 어떤 퍼시스턴스 솔루션과도 연관성을 갖지 않는다
스프링을 사용하면 퍼시스턴스 기술과 관계없이 일관성있게 예외를 발생시킬 수 있다

: 스프링의 DataAccessException는 비검사형 예외(try~catch블럭을 사용하지 않아도 컴파일이 되는 예외)로서 반드시 잡아서 처리할 필요가 없다

: 스프링이 제공하는 DataSource를 설정하는 3가지 방법

1. 커넥션풀을 이용한 DataSource 설정
스프링이 직접적으로 커넥션풀을 제공하진 않지만 DBCP(Jakarta Commons Database Connection Pool) API와 같은 커넥션 풀 라이브러리를 이용
DBCP에는 풀링 기능을 제공하는 다양한 데이터 소스가 포함되 있지만 BasicDataSource가 가장 많이 사용된다

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
     <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
     <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
     <property name="username" value="java8" />
     <property name="password" value="itbank" />
     <property name="initialSize" value="5" /> → 해당 풀이 시작될 때 생성할 커넥션 수, 0은 무제한
     <property name="maxActive" value="10" /> → 해당 풀에서 동시에 제공할 수 있는 최대 커넥션 수, 0은 무제한
</bean>


2. JNDI을 이용한 DataSource 설정
WebLogic이나 JBoss와 같은 JEE 어플리케이션 서버를 사용할 경우
톰캣이난 Resin등의 웹 컨테이너를 사용할 경우

<jee:jndi-lookup id="dataSource" jndi-name="oracle" resource-ref="true" />
<jee:jndi-lookup>태그를 이용 - 스프링2.0부터 지원
jndi-name 프로퍼티는 JDNI에 있는 리소스의 이름을 지정한다
jndi-name프로퍼티만 지정된 경우에는 데이터소스는 지정된 jndi-name을 그대로 이용해서 검색한다
자바 애플리케이션 서버에서 가동되는 경우에는  resource-ref=true이면 jndi-name값의 앞에 "java:comp/env"가 붙은 이름을 사용한다

<jee:jndi-lookup>태그를 사용하지 않고 JndiObjectFactoryBean클래스를 이용할 수 있다


3. DriverManager을 이용한 DataSource 설정
: 스프링에 설정할 수 있는 가장 단순한 데이터 소스는 JDBC드라이버를 통해 정의된 것이다

- DriverManagerDataSource
애플리케이션이 커넥션을 요청할 때마다 새로운 커넥션을 반환한다
DBCP의 BasicDataSource와는 달리 커넥션은 풀링되지 않는다
멀티스레드에서도 동작은 하지만 커넥션이 필요할 때마다 새로 커넥션을 생성하므로 심각한 성능 저하를 유발한다.

- SingleConnectionDataSource
커넥션을 요청하면 항상 동일한 커넥션을 반환한다
커넥션 풀링 기능은 없지만 오직 하나의 커넥션만을 풀링하는 데이터소스
사용할 수 있는 커넥션이 오직 하나뿐이라서 멀티스레드 애플리케이션에서는 제대로 동작하지 않을 것이다

: 스프링의 JDBC 프레임워크는 자원관리와 예외 처리를 대신 해주므로 JDBC코드가 훨씬 간결해진다
스프링은 단순 반복적인 데이터 액세스 코드를 템플릿 클래스 뒤로 추상화해 숨긴다

1. JdbcTemplate
스프링의 가장 기본적인 JDBC 템플릿
색인된 파라미터(indexed parameter)기반의 쿼리를 통해 데이터베이스를 쉽게 액세스하는 기능을 제공

2. NamedParameterJdbcTemplate
SQL과 값들을 색인된 파라미터 대신 명명된 파라미터(named parameter)로 바인딩하여 쿼리를 수행할 수 있게 해준다

 

jdbcTemplate을 DAO에 와이어링

public class UserDAOImpl implements UserDAO {
     private JdbcTemplate jdbcTemplate;

     public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
          this.jdbcTemplate = jdbcTemplate;
     }
}

<bean id="userDao" class="user.dao.UserDAOImpl">
     <property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
     <constructor-arg ref="dataSource" />
</bean>
---------------------------------------------------
SimpleJdbcTemplate 빈을 각 DAO 클래스의 프로퍼티에 연결해 줘야 했다
그런데 여러개의 DAO클래스를 작성하는 경우라면 많은 중복코드가 발생한다
모든 DAO 객체에 대해 SimpleJdbcTemplate 프로퍼티를 갖는 공통부모클래스를 작성한다


★ 스프링이 제공하는 기반클래스
JdbcTemplate - JdbcDaoSupport
NamedParameterJdbcTemplate - NamedParameterJdbcDaoSupport
SimpleJdbcTemplate - SimpleJdbcDaoSupport


SimpleJdbcDaoSupport 에서는 getSimpleJdbcTemplate()메소드를 제공하므로
SimpleJdbcTemplate을 편리하게 사용할 수 있다

-----------------------------------------------------
public class jdbcMemberDAO extends SimpleJdbcDaoSupport  implements MemberDAO {
 public void insertArticle(MemberDTO dto){
       getSimpleJdbcTemplate().update(...)
 }
}


<bean id="memberDao" class="com.dao.jdbcMemberDAO">
     <property name="dataSource" ref="dataSource" />
</bean>
-----------------------------------------------------

SimpleJdbcDaoSupport로 부터 jdbcMemberDAO를 상속받은 dataSource프로퍼티에 데이터소스를 직접 와이어링할 수 있다
jdbcMemberDAO에 그 자신의 dataSource프로퍼티가 설정되면 jdbcMemberDAO는 자신이 사용할 SimpleJdbcTemplate 인스턴스를 내부적으로 생성해 둔다.
따라서 JdbcTemplate빈을 스프링에 명시적으로 선언할 필요가 사라진다

<bean id="memberDao" class="com.dao.jdbcMemberDAO">
     <property name="dataSource" ref="dataSource" />
</bean>
-----------------------------------------------------

Project : Chapter04
          Chapter04_SpringMaven

Package  : user.main
Class    : HelloSpring.java - main()

Package   : user.action
Interface : UserAction.java - public void execute();
Class     : UserInsertAction.java
            UserSelectAction.java
            UserUpdateAction.java
            UserDeleteAction.java

Package   : user.bean
Class     : UserDTO.java

Package   : user.dao
Interface : UserDAO.java
Class     : UserDAOImpl.java
 
src
     applicationContext.xml

-----------------------------------------------------
★ JAR  3개 추가

commons-collections-4.1.jar
commons-dbcp-1.4.jar
commons-pool-1.6.jar

spring-jdbc-4.3.10.RELEASE.jar
spring-tx-4.3.10.RELEASE.jar

ojdbc6.jar

-----------------------------------------------------
★ 테이블 작성

create table usertable (
     name   varchar2(30),
     id   varchar2(30) primary key,
     pwd   varchar2(30)
);
-----------------------------------------------------

 

 

 

 

 

 

★ 스프링 MVC

: 스프링 MVC도 컨트롤러를 사용하여 클라이언트의 요청을 처리한다
  스프링에서 DispatcherServlet 이 MVC에서 C(Control) 부분을 처리한다.
  개발자가 처리할 부분은 클라이언트의 요청을 처리할 컨트롤러와 응답화면을 전송할 JSP나 Velocity 템플릿 등 뷰 코드이다
  DispatcherServlet, HandlerMapping, ViewResolver등은 스프링이 기본적으로 제공하는 구현 클래스를 사용한다.

: 스프링 MVC의 구성 요소
1. DispatcherServlet
클라이언트의 요청을 전달 받는다
컨트롤러에게 클라이언트의 요청을 전달하고 Controller가 리턴한 결과값을 View에 전달하여 응답을 생성하도록 한다.

2. HandlerMapping
클라이언트의 요청 URL을 어떤 Controller가 처리할지를 결정한다

3. Controller
클라이언트의 요청을 처리한 뒤 결과를 DispatcherServlet에 알려준다.
스트럿츠의 Action과 동일한 역활을 수행한다.

4. ModelAndView
컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담는다.

5. ViewResolver
컨트롤러의 처리 결과를 생성할 뷰를 결정한다.

6. View
컨트롤러의 처리 결과 화면을 생성한다.
JSP나 Velocity 템플릿 파일등을 뷰로 사용한다.

 

Project : Chapter06 (Dynamic Web Project) - *.jar
          project명에서 우클릭 - Spring Tools - Add Spring Project Nature

          Chapter06_DynamicSpringMaven (Dynamic Web Project) - pom.xml
          project명에서 우클릭 - Spring Tools - Add Spring Project Nature
          project명에서 우클릭 - Configure - Convert to Maven Project

          Chapter06_SpringWebMaven (Spring Project)


[실행]
http://localhost:8080/Chapter06/hello.do

Package : com.controller
Class   : HelloController.java

Folder  : WEB-INF
          web.xml
          dispatcher-servlet.xml

Folder  : view
          hello.jsp


★ web.xml
1. web.xml에 DispathcerServlet 설정을 통해 스프링 설정 파일을 지정합니다.
2. *.do로 들어오는 클라이언트의 요청을 DispatcherServlet이 처리하도록 했다
3. DispatcherServlet은 WEB-INF/서블릿이름-servlet.xml 파일로부터 스프링 설정 정보를 읽어온다.


<servlet>
 <servlet-name>dispatcher</servlet-name>
   <servlet-class>
  org.springframework.web.servlet.DispatcherServlet
   </servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>dispatcher</servlet-name>
   <url-pattern>*.do</url-pattern>
 </servlet-mapping>

-------------------------------------------------------------
★ HelloController.java

1. 컨트롤러를 구현하려면 @Controller 어노테이션을 클래스에 적용한다.
2. @RequestMapping 어노테이션을 이용해서 클라이언트의 요청을 처리할 메소드를 지정한다.
3. ModelAndView.setViewName()메소드를 이용해서 컨트롤러의 처리 결과를 보여줄 뷰 이름을 지정한다.


package com.controller;

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

@Controller
public class HelloController {
 
 @RequestMapping("/hello.do")
 public ModelAndView hello(){
  ModelAndView mav = new ModelAndView();
  mav.setViewName("hello");
  mav.addObject("greeting","Hello Spring MVC");
  return mav;
 }

}

-------------------------------------------------------------
★ dispatcher-servlet.xml

1. DispatcherServlet은 스프링 컨테이너에서 컨트롤러 객체를 검색하기 때문에 스프링 설정파일에 컨트롤러를 빈으로 등록해주어야 한다
2. DispatcherServlet은 뷰이름과 매칭되는 뷰 구현체를 찾기 위해 ViewResolver를 사용한다.
3. 스프링 MVC는 JSP, Velocity, FreeMarker등의 뷰 구현 기술과의 연동을 지원하는데, JSP를 뷰 기술로 사용할 경우 InternalResourceViewResolver 구현체를 빈으로 등록해주면 된다.
4. ViewResolver가 /view/뷰이름.jsp를 뷰JSP로 사용한다는 의미이다


<bean id="helloController"
 class="com.controller.HelloController"/>

<bean id="viewResolver"
 class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 <property name="prefix" value="/view/" />
 <property name="suffix" value=".jsp" />
</bean>

-------------------------------------------------------------

★ /view/hello.jsp

<body>
인사말 : ${greeting }
</body>

-------------------------------------------------------------

[문제1]
Project : Chapter06_1
Package : com.controller
Class   : SumController

Package : com.bean
Class   : SumDTO

Foler   : sum
File    : input.jsp
          result.jsp

스프링 설정 파일
/WEB-INF/dispatcher-servlet.xml → /WEB-INF/dispatcher-config.xml

[실행결과]
http://localhost:8080/Chapter06_1/input.do

input.jsp    --------->  result.jsp

 X : ㅁ                  25 + 36 = xx
 Y : ㅁ

 계산(submit)
 result.do

-------------------------------------------------------------
[문제2]
Project : Chapter06_1
Package : com.controller
Class   : SungJukController

Package : com.bean
Class   : SungJukDTO

Foler   : sungJuk
File    : input.jsp
          result.jsp

스프링 설정 파일
/WEB-INF/mvc-config.xml

[실행결과]
http://localhost:8080/Chapter06_1/sungJuk/input.do

input.jsp    ------------     result.jsp

 이름 : ㅁ                   *** xxx 성적 ***
 국어 : ㅁ               총점 : xxx
 영어 : ㅁ                    평균 : xx.xxx
 수학 : ㅁ

 계산(submit)
 /sungJuk/result.do


** 스프링 설정 파일의 경로와 파일명을 바꿀 수 있고 여러개로 만들 수 있다

/WEB-INF/dispatcher-servlet.xml(스프링 설정 파일)의 이름도 바꾸고 2개로 나누어 본다

/WEB-INF/dispatcher-config.xml - SumController
       ↓
/WEB-INF/mvc-config.xml - SungjukController

 

 

 


 

[문제1]
Project : Chapter06_1
Package : com.controller
Class   : SumController

Package : com.bean
Class   : SumDTO

Foler   : sum
File    : input.jsp
          result.jsp

스프링 설정 파일
/WEB-INF/dispatcher-servlet.xml → /WEB-INF/dispatcher-config.xml

[실행결과]
http://localhost:8080/Chapter06_1/input.do

input.jsp    --------->  result.jsp

 X : ㅁ                  25 + 36 = xx
 Y : ㅁ

 계산(submit)
 result.do

-------------------------------------------------------------

 


프로젝트 생성
web.xml 생성
서블릿 작성
dispatcher-config.xml 만들기
콘트롤러 생성
주소확인
콘트롤러
sum폴더 생성
input.jsp 생성
result.jsp 생성

 

---------------------------------------------------------------------

>>> web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>Chapter06_1</display-name>
 
 
  <servlet>
  <servlet-name>dispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  
  <!--
    스프링 설정 파일 :
   /WEB-INF/dispatcher-servlet.xml
    WAC의 이름 또는 위치를 바꾸고 싶을때
   -->
  
   <init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>/WEB-INF/dispatcher-config.xml</param-value>
   </init-param>
  
  </servlet>
 

  
  <servlet-mapping>
  <servlet-name>dispatcher</servlet-name>
  <url-pattern>*.do</url-pattern>
  </servlet-mapping>
 
 
 
 
 
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

>>> dispatcher-config.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"
 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-4.3.xsd">

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- <property name="prefix" value="/view/"></property> // 많이 안씀 -->
<property name="suffix" value=".jsp"></property>
</bean>

<bean id="SumController" class="com.controller.SumController"></bean>


</beans>

>>> controller(com.controller-SumController.java)

 

package com.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class SumController { //POJO형식 -> 순수한 자기만의 클래스 (extends implement 모두 안해줌)
 
 //http://localhost:9090/Chapter06_1/input.do
 @RequestMapping(value="/input.do", method = RequestMethod.GET)  // get방식
 public ModelAndView input() {
  ModelAndView mav = new ModelAndView();
  mav.setViewName("/sum/input");
  return mav;
 }
 
 
 @RequestMapping(value="/result.do", method = RequestMethod.GET)  // get방식
 public ModelAndView result() {
  ModelAndView mav = new ModelAndView();
  mav.setViewName("/sum/result");
  return mav;
 }

}

 

>>>>>> input.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<form action="result.do" method=get>
<!-- //<form action="http://localhost:9090/Chapter06_1/result.do" method=get> -->

<table border="1" align="center">
<tr>
<td> X<input type=text name="x" > </td>
</tr>
<tr>
<td> Y<input type=text name="y"> </td>
</tr>
<tr>
<td align="center"> <input type=submit value="result"> <input type=reset value="취소" > </td>
</tr>
</table>
</form>

</body>
</html>

 

 

>>>>> result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
${param.x } + ${param.y } = ${param.x + param.y}
</body>
</html>

 

>>>> 결과

http://localhost:9090/Chapter06_1/input.do

 

 

 

 

@RequestMapping("download.do")
public void download(HttpServletResponse response, @RequestParam("id")String id) throws Exception {
// id를 이용해 db에서 파일 fullPath 와 ofn 얻어오기
String ofn = service.getOfn(id);
String fullPath = service.getFilePath(id);
File target = new File(fullPath);
byte[] b = new byte[1024 * 1024 * 10];
DataOutputStream dos = new DataOutputStream(new FileOutputStream(target));

response.reset();
response.setContentType("application/octet-stream");

String fileName = new String(ofn.getBytes("utf8"), "8859_1");
response.setHeader("Content-Disposition", "attatchment; filename = " + fileName);
response.setHeader("Content-length", String.valueOf((int)target.length()));

FileInputStream fis = new FileInputStream(target);
ServletOutputStream sos = response.getOutputStream();

int num;
while((num = fis.read(b,0,b.length)) != -1) {
sos.write(b,0,num);
}
sos.flush();
sos.close();
fis.close();



}

<%@page import="java.sql.Timestamp"%>
<%@page import="java.sql.Date"%>
<%@page import="java.sql.Time"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
 pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
 <table border=1 align=center width=630>


  <tr>
   <th colspan=4>Message List
  </tr>

  <tr>
   <th>
   <th>Message
   <th>Name
   <th>Wdate
  </tr>
  <%

Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String id = "web10";
String pw = "web10";
Connection con = DriverManager.getConnection(url, id, pw);

String sql = "select * from message";
PreparedStatement pstat = con.prepareStatement(sql);
ResultSet rs = pstat.executeQuery();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/mm/dd");


while(rs.next()) {
 
 Timestamp t = rs.getTimestamp("wdate");
 long messageTime = t.getTime();
 Date wdate = new Date(messageTime);
 String wdateString = sdf.format(wdate);
 
 // sdf.format(new Date(rs.getTimestamp("wdate")));
 %>

  <tr>
   <td><%=rs.getInt("seq")%>
   <td><%=rs.getString("message")%>
   <td><%=rs.getString("name")%>
   <td><%=wdateString%>
  </tr>

  <%
}

con.close();


%>


 </table>

</body>
</html>

 

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Input</title>
</head>
<body>

<form action=recv.jsp method=get>
<table border=1>

<tr>
<th colspan=2> Input Message
</tr>

<tr>
<td> Name:
<td> <input type=text name=name placeholder="이름을 입력하세요.">
</tr>

<tr>
<td colspan=2>
<textarea placeholder="메시지을 입력하세요." name=text rows=5 cols=30></textarea>
</tr>

<tr>
<td colspan=2 align = center> <input type=submit id=ok value="OK">
</tr>

</table>
</form>

</body>
</html>

 

17.12.15 웹3일차

자바스크립트 이벤트 처리

이벤트란

====== 버튼 처리 문법

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>

<input type=button value=pop id=popBtn>


<script type="text/javascript">

document.getElementById("popBtn").onclick = function(){
 alert("pop");
}

</script>

</body>
</html>

====== 페이지 이동문법

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>

<input type=button value=pop id=popBtn>


<script type="text/javascript">

document.getElementById("popBtn").onclick = function(){
 location.href = "http://www.naver.com"; //페이지 이동문법
  
}

</script>

</body>
</html>


========= 버튼 클릭 후 페이지 팝업 사이즈 지정
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>

<input type=button value=pop id=popBtn>


<script type="text/javascript">

document.getElementById("popBtn").onclick = function(){

 window.open("http://www.naver.com","","width=500,heigt=500");
  
}

</script>

</body>
</html>

======

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>

<script type="text/javascript">

window.onload = function(){
 
 window.open("http://www.google.com","","width=500,height=500");
}

</script>
</body>
</html>

=====

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>

<script type="text/javascript">

window.onunload = function(){
 for(var i = 0;i<5;i++){
 
 
 window.open("http://www.google.com","","width=500,height=500");
}
}

</script>
</body>
</html>
=======

 

========================== jsp 시작


jsp

서블릿은 문서를 요청받으면 바로 만들어서 보냄

 


 

 

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>

<p id=target>target</p>
<input type=button value=pop id=pop>


<script type="text/javascript">

document.getElementById("pop").onclick = function(){

 window.open("exam08.html","","width=300,height=200");
}

</script>
</body>
</html>

 

//////////////////////////////

 

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>

<p id=target>target</p>
<input type=button value=pop id=pop>


<script type="text/javascript">

document.getElementById("pop").onclick = function(){

 window.open("exam08.html","","width=300,height=200");
}

</script>
</body>
</html>

 

+ Recent posts