--------------------------------------[@AspectJ의 Pointcut 살펴보기-①]

 

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?
                                          name-pattern(param-pattern) throws-pattern?)

       return type pattern을 제외하고는 전부 optional이다

       modifiers-pattern은 advice가 적용될 메소드의 접근 지시자 형태를 정한다
       * 는 모든 메소드 public

       declaring-type-pattern은 인터페이스나 패키지 패턴을 나타낸다

       name-pattern은 메소드의 이름의 형태를 지정해 준다
       set*와 같이 하면 set으로 시작하는 모든 메소드를 나타낸다

       param-pattern은 조금 특이하다.
       ()은 파라미터가 없는 메소드를 가리키고
       (..)는 파라미터가 어떤 형태, 몇개등 상관없음을 나타낸다.
       다른 패턴들이 * 와일드 카드를 사용하는 것과는 차이가 있다.
       (*, String) 파라미터가 두개이고, 첫번째 파라미터의 타입은 상관이 없고
       두번째 파라미터의 타입이 String메소드를 나타낸다.

within(type-pattern)
       within은 Spring AOP가 메소드 execution 포인트컷만 지원하기 때문에
       해당 타입과 관련된 모든 메소드 실행시점을 가르킨다.
       AspectJ를 사용할 때는 훨씬 다양한 포인트컷(
              클래스 초기화 시점, 객체 초기화 시점,
              생성 실행 시점, 메소드 실행 시점
              이밖에도 변수들에 대한 포인트컷까지 적용되며,
              내부 클래스가 있을 경우 그것의 생성자나 기타 내부클래스와
              관련된 모든 joinpoint에도 적용된다)
       을 나타내게 된다.

within(com.xyz.service.*)의 경우는
       com.xyz.service패키지 안에 있는 모든 클래스의 
       모든 메소드의 실행시점을 나타낸다

 


--------------------------------------[@AspectJ의 Pointcut 살펴보기-②]

 

this(Type)
       this키워드에 바인딩 되는 현재 실행 중인 객체의 타입이 Type인 경우에
       모든 메소드 execution Join point를 나타낸다

target(Type)
       메소드가 호출되거나 필드가 접근되는 객체의 타입이 Type인 경우에
       그 객체의 모든 메소드 execution Join point를 나타낸다

args(Type or ".." or *)
       메소드의 전달인자가 ()안에 정의한 갯수나 타입에 매칭되는
       모든 메소드 execution Join Point를 나타낸다

@target(Type)
       타켓 객체(메소드가 호출되거나 필드가 접근되는 객체)에 @Type 어노테이션이
       붙어있을 때 그 객체의 모든 메소드 execution Join point를 나타낸다.

@within(Type)
       선언된 타입에 @Type 어노테이션이 붙어있을때 그 객체의 모든
       execution Join point를 나타낸다

@annotation(Type)
       실행되는 메소드에 @Type 어노테이션이 붙어있을때 그 메소드의
       execution Join point를 나타낸다

@args(Type)
       실행시 전달인자로 넘겨지는 것에 @Type 어노테이션이 붙어있을때
       그 메소드의 execution Join point를 나타낸다.

 

>>>>>>>>>>>>>>>> Advice 예제 2  >>>>>>>>>>>>>>>>>>

 

------------------------------------------------------------MannerAOP.java
package secondSpringAOP;

public class MannerAOP {
    public void beforeSaying(){
        System.out.println("당신의 이름은?");
    }
    public void afterreturnSaying(){
        System.out.println("정말 멋진 분이군요!!");
    }
    public void afterSaying(){
        System.out.println("사랑합니다:)");
    }
}
------------------------------------------------------------Human.java
package secondSpringAOP;

public interface Human {
    public String sayName(String name);
}
------------------------------------------------------------HongGilDong.java
package secondSpringAOP;

public class HongGilDong implements Human {
    @Override
    public String sayName(String name) {
        System.out.println(name+" 이라고 합니다.");
        return "난~~~동해번쩍 서해번쩍"+name+"이다";
    }
}
------------------------------------------------------------LeeSunShin.java
package secondSpringAOP;

public class LeeSunShin implements Human {
    @Override
    public String sayName(String name) {
        System.out.println(name+" 이라고 합니다.");
        return "난~~~민족의 영웅"+name+"이다";
    }
}
------------------------------------------------------------YuGwanSoon.java
package secondSpringAOP;

public class YuGwanSoon implements Human {
    @Override
    public String sayName(String name) {
        System.out.println(name+" 이라고 합니다");
        return "난 ~~~독립투사"+name+"이다";
    }
}
------------------------------------------------------------aopAppContext.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"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
  
      <bean id="hgd" class="secondSpringAOP.HongGilDong"/>                         
      <bean id="lss" class="secondSpringAOP.LeeSunShin"/>                         
      <bean id="ygs" class="secondSpringAOP.YuGwanSoon"/>
      <bean id="manner" class="secondSpringAOP.MannerAOP"/>
  
    <aop:config>
         <aop:aspect ref="manner">
             <aop:pointcut id="greeting"
                                  expression="execution(public * secondSpringAOP.Human.sayName(..))"/>
             <aop:before pointcut-ref="greeting" method="beforeSaying"/>
             <aop:after-returning pointcut-ref="greeting" method="afterreturnSaying"/>
             <aop:after pointcut-ref="greeting" method="afterSaying"/>
        </aop:aspect>
    </aop:config>                           
</beans>
------------------------------------------------------------TestSecondAOP.java
package secondSpringAOP;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSecondAOP {

    public static void main(String[] args) {
        BeanFactory bf=new ClassPathXmlApplicationContext("secondSpringAOP/aopAppContext.xml");
       
        Human human=(Human)bf.getBean("hgd");
        System.out.println(human.sayName("홍길동"));
        System.out.println("");
       
        human=(Human)bf.getBean("lss");
        System.out.println(human.sayName("이순신"));
        System.out.println("");
       
        human=(Human)bf.getBean("ygs");
        System.out.println(human.sayName("유관순"));
        System.out.println("");
       
    }
}
------------------------------------------------------------결과
당신의 이름은?
홍길동 이라고 합니다.
정말 멋진 분이군요!!
사랑합니다:)
난~~~동해번쩍 서해번쩍홍길동이다

 

당신의 이름은?
이순신 이라고 합니다.
정말 멋진 분이군요!!
사랑합니다:)
난~~~민족의 영웅이순신이다

 

당신의 이름은?
유관순 이라고 합니다
정말 멋진 분이군요!!
사랑합니다:)
난 ~~~독립투사유관순이다

 

------------------------------------------------------------[참조]
<aop:before> 메소드 실행 전에 적용
<aop:after-returning> 메소드가 정상 실행된 후에만 적용
<aop:after-throwing> 메소드가 예외를 발생시킬 때에만 적용(catch문과 비슷)
<aop:after> 메소드가 실행된 후 무조건 적용(finally문과 비슷)
<aop:around>모든 시점에 적용

Advice 설정에는 pointcut-ref속성 말고 pointcut 속성도 있는데 pointcut속성에는
<aop:pointcut>태그의 expression속성을 바로 설정해 줄 수 있다.

 

>>>>>>>>>>>>>>>>> Advice 예제 1 >>>>>>>>>>>>>>>>>>>


------------------------------------------------------------Service.java
package part1;

public interface Service {
    public void first();
    public void first(String str);
    public void second();
    public String third();
    public void fourth();
    public void fifth();
}
------------------------------------------------------------ServiceImp.java
package part1;

public class ServiceImp implements Service {

    public ServiceImp(){
        System.out.println("생성자");
    }
    @Override
    public void first() {
        System.out.println("first()");
    }

    @Override
    public void first(String str) {
        System.out.println(str+"first()");
    }

    @Override
    public void second() {
        System.out.println("second()");
    }

    @Override
    public String third() {
        System.out.println("third()");
        return "JAVA";
    }

    @Override
    public void fourth() {
        System.out.println("fourth()");
    }

    @Override
    public void fifth() {
        int num[]=new int[3];
        num[4]=10;
    }

}
------------------------------------------------------------AopCommon.java
package part1;

import org.aspectj.lang.ProceedingJoinPoint;

public class AopCommon {
    public void commMethod1(){
        System.out.println("선행 공통메소드()");
    }
    public void commMethod2(){
        System.out.println("후행 공통메소드()");
    }
    public void commMethod3(Object ret){
        System.out.println("commMethod3:"+ret.toString());
    }
    public void commMethod4(ProceedingJoinPoint joinpoint){
        System.out.println("target 실행전");
        try{
            joinpoint.proceed();
        }catch(Throwable e){
            e.printStackTrace();
        }
        System.out.println("target 실행후");
    }
    public void commMethod5(ArrayIndexOutOfBoundsException thr){
        System.out.println("commMethod5:"+thr.toString());
    }
}
------------------------------------------------------------aop.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<!-- Aspect 빈 객체 선언 -->
<bean name="commAspect" class="part1.AopCommon"/>

<!-- Target 빈 객체 선언 -->
<bean name="svc" class="part1.ServiceImp"/>

<!-- advice 정의 -->
<aop:config>
  <aop:pointcut expression="execution(* part1.ServiceImp.first(..))"  id=one"/>
  <aop:pointcut expression="execution(* part1.ServiceImp.second(..))" id="two"/>
  <aop:pointcut expression="execution(* part1.ServiceImp.third(..))"  id="three"/>
  <aop:pointcut expression="execution(* part1.ServiceImp.fourth(..))" id="four"/>
  <aop:pointcut expression="execution(* part1.ServiceImp.fifth(..))"  id="five"/>
 
  <aop:aspect ref="commAspect">
    <aop:before method="commMethod1" pointcut-ref=one"/>
    <aop:after  method="commMethod2" pointcut-ref="two"/>
    <aop:after-returning method="commMethod3" pointcut-ref="three" returning="ret"/>
    <aop:around method="commMethod4" pointcut-ref="four"/>
    <aop:after-throwing method="commMethod5" pointcut-ref="five" throwing="thr"/>
  </aop:aspect>
</aop:config>

</beans>
------------------------------------------------------------ServiceMain.java
package part1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class ServiceMain {
    public static void main(String[] args) {
        ApplicationContext context=new FileSystemXmlApplicationContext("src/part1/aop.xml");
        Service svc=(Service)context.getBean("svc");
        //svc.first("korea");
        //svc.first();
        //svc.second();
        //svc.third();
        //svc.fourth();
        try{
            svc.fifth();
        }catch(ArrayIndexOutOfBoundsException ex){}
    }
}

 

----------------------------------------------------------aspect 라이브러리 설치
eclipse.org -> aspect검색
AspectJ Development Tools (AJDT) 클릭

Links -> AspectJ -> Downloads
Latest Stable Release -> aspectj-1.6.12.jar 다운후 압축풀기

 

----------------------------------------------------------스프링 라이브러리 다운로드
http://www.springsource.org/spring-framework
RELEASE SUMMARY
3.0.7 -> Download -> More
3.0.2.RELEASE 3개파일 다운후 압축풀기

 

-----------------------------------------------------------Commons Logging
스프링 프레임워크를 정상적으로 사용하려면 추가적으로 복사해야 하는 종속 라이브러리
라이브러리를 복사하지 않으면 서블릿을 찾지 못하는 오류가 발생한다.
apache.org
Commons -> Logging -> Download -> commons-logging-1.1.1-bin.zip

 

------------------------------------------------------------프로젝트 생성
Dynamic Web Project : testAspectj
프로젝트에서 오른쪽 버튼 -> Configure -> Convert to AspectJ Project
/WEB-INF/lib/ 아래 .jar복사

① /setup/aspectj-1.6.12/lib/ aspectj*.jar 3개파일
② /setup/spring-framework-3.0.2.RELEASE/spring-framework-3.0.2.RELEASE/dist/ 21개 파일
③ /setup/spring-framework-3.0.2.RELEASE-dependencies/org.aopalliance/
              com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar
④/setup/commons-logging-1.1.1-bin/commons-logging-1.1.1/commons-logging-1.1.1.jar 1개파일

 

 

>>>>>>>>>>>>>>> Spring 사용하는  간단 DI 예제 >>>>>>>>>>>>>>>>>>

 

----------------------------------------------------------------Greeting.java
package firstSpringAOP;

public interface Greeting {
    void sayHi();
}
----------------------------------------------------------------KoreanGreeting.java
package firstSpringAOP;

public class KoreanGreeting implements Greeting {
    @Override
    public void sayHi() {
        System.out.println("안녕!!");
    }
}
-----------------------------------------------------------------JapanGreeting.java
package firstSpringAOP;

public class JapanGreeting implements Greeting {
    @Override
    public void sayHi() {
        System.out.println("오하이오!!");
    }
}
--------------------------------------------------------------AmericanGreeting.java
package firstSpringAOP;

public class AmericanGreeting implements Greeting {
    @Override
    public void sayHi() {
        System.out.println("Hello!!");
    }
}
-------------------------------------------------------------applicationContext.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-2.0.xsd">
    <bean id="korea" class="firstSpringAOP.KoreanGreeting"/>                         
    <bean id="japan" class="firstSpringAOP.JapanGreeting"/>                         
    <bean id="usa"   class="firstSpringAOP.AmericanGreeting"/>                         
</beans>
------------------------------------------------------------TestFirstSpringAOP.java
package firstSpringAOP;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestFirstSpringAOP {
    public static void main(String[] args) {
        ApplicationContext ac=new ClassPathXmlApplicationContext(
                                  new String[]{"firstSpringAOP/applicationContext.xml"}
                              );
        Greeting greeting=(Greeting)ac.getBean("korea");
        greeting.sayHi();
       
        greeting=(Greeting)ac.getBean("japan");
        greeting.sayHi();

        greeting=(Greeting)ac.getBean("usa");
        greeting.sayHi();
    }
}
------------------------------------------------------------결과
안녕!!
오하이오!!
Hello!!

 

>>>>>>>>>>>>>>>>> Aspectj의 설치 및 셋팅 >>>>>>>>>>>>>>>>>>>


--------------------------------------------------이클립스에서 직접 설치 방법 및 순서
eclipse.org -> aspect검색
AspectJ Development Tools (AJDT) 클릭
다운로드
설치된 이클립스 버전 확인후
http://download.eclipse.org/tools/ajdt/37/update 경로복사

 

--------------------------------------------------------이클립에서 직접 업데이트 방법
Help -> Install New Software -> Work with ~~~ Add...
Name : aspect
Location : http://download.eclipse.org/tools/ajdt/37/update
Name 3개 전부 체크, 동의
설치된후 이클립스 재시작

 

----------------------------------------------------------------------이클립스
이클립스 -> 자바 프로젝트 : exAspectj

exAspectj 프로젝트 -> 오른쪽 -> Configure -> Convert to AspectJ Project
프로젝트명 앞에 AJ표시 되면 설치 완료

 

 

>>>>>>>>>>>>>> Aspectj를 사용하는 간단 AOP 예제 >>>>>>>>>>>>>>>>>>

 

----------------------------------------------------------------------GilDong.java
package firstAspectjAOP;

public class GilDong {
    private void say(){
        System.out.println("I am Gildong.");
    }
    public static void main(String[] args){
        new GilDong().say();
    }
}
----------------------------------------------------------------------Advice.aj
package firstAspectjAOP;

public aspect Advice {
    pointcut callsay():call(* GilDong.say(..));
    before():callsay(){
        System.out.println("Welcome");
    }
    after():callsay(){
        System.out.println("Good bye");
    }
}
----------------------------------------------------------------------결과
Welcome
I am Gildong.
Good bye

 

>>>>>>>>>>>>>>>> Spring Framework >>>>>>>>>>>>>>>


- 개요 : 유연한 특성을 가지는 프레임워크

 

* AOP
  . Aspect Oriented Programming 관점지향
  . 공통적인 기능을 한곳에서 정의
  . 새로운 기능을 적용하려고 하는 클래스를 수정할 필요없이
    그런 기능을 어디에 어떻게 적용할 것인지 선언적으로 정의 가능

               A        B        C
                    |
                    z 기능 추가해 (기존의 소스를 재코딩, 다시 컴파일, 재배치)

 
               D        E        F
                     |
                     z

               . 마감이 임박한 프로그램에
               . 새로운 기능이 추가되면 재코딩->재컴파일->재배포 하는 번거로움.
               . 기존의 소스를 건드리지 않고 z기능을 추가하는 기능
               . z기능을 따로 만들어서 필요한 위치에 집어 넣어줌
               . 들어갈 가능성이 있는 지점을 joinpoint라 한다 (즉 메소드가 끝나는 지점)
               . pointcut : 실제 끼어드는 순간
               . z기능 : code 또는 advice
               . 좀더 쉽게 구현하기 위해
               . spring AOP에 Aspectj를 함께 사용하면 환경설정이 훨씬 쉬워진다


* DI
  . Dependence Injection 의존성 주입
  . 인터페이스는 다형성을 이용해서 사용
  . 의존을 하고 있는 상황
  . 의존이 많이 발생하는 상황이 되면 빼도막도 못하는 상황이 발생
  . 의존을 낮추는 방향으로 프로그램 개발
  . 참조해서 객체 만들지마라
  . 객체를 만들어서 주입만 해줌
  . 객체를 주입받기 위해서 setter만 있으면 됨

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

 

1. AOP 용어 개요

 

- 핵심관심 : Major ConCern
                 예) 게시판에 글쓰기, 글보기, 글삭제, 글수정...
- 횡단관심 : Cross-Cutting Concern
                 예) 로깅, 인증, 예외처리...
- 기존의 코드 : 핵심 관심과 횡단 관심이 결합되어 있는 형태는
                     =>유지보수 어려움이 있다
               (중복발생, 지저분함, 생산성 저하, 재사용 힘듬, 변화 힘듬)

                    Code : 핵심관심을 구현한 것
                    Advice : 횡단관심을 구현한 것
                    Joinpoint : Advice가 Code에 끼어 들 수 있는 순간들
                    Pointcut : Joinpoint중에서 실제 Advice가 Code에 끼어드는 순간
                    Aspect : Advice + Pointcut
                    weaving : Code에 Aspect를 적용하는 과정

 

2. AOP 용어

 

  1) 결합점 (Join point)

    인스턴스의 생성시점, 메소드를 호출하는 시점, Exception이 발생하는 시점과 같이
    애플리케이션이 실행될 때 특정작업이 실행되는 시점을 의미한다.

 

  2) 교차점 (pointcut)

    충고가 어떤 결합점에 적용되어야 하는지 정의.
    명시적인 클래스의 이름, 메소드의 이름이나 클래스나 메소드의 이름과
    패턴이 일치하는 결합점을 지정 가능토록 해준다
    (스프링 설정파일 안에서 XML로 작성)

 

  3) 충고 (Advice)

    충고는 교차점에서 지정한 결합점에서 실행(삽입)되어야 하는 코드이다.
    Aspect의 실제 구현체

 

  4) 에스팩트 (Aspect)

    에스팩트는 AOP의 중심단위. Advice와 pointcut을 합친 것이다.
    구현하고자 하는 횡단 관심사의 기능. 애플리케이션의 모듈화 하고자 하는 부분

 

  5) 대상(target)

    충고를 받는 클래스를 대상(target)이라고 한다.
    대상은 사용자가 작성한 클래스는 물론, 별도의 기능을 추가하고자 하는
    써드파티 클래스가 될 수 있다.

 

  6) 엮기 (Weaving)

    에스펙트를 대상 객체에 적용하여 새로운 프록시 객체를 생성하는 과정을 말한다.
    Aspect는 대상 객체의 지정된 결합점에 엮인다.

 

3. Advice의 종류

 

- Before advice : joinpoint이전에 실행이 되며 예외를 던지지 않는 이상
                         joinpoint이후에 실행될 작업을 막을 방법이 없다

- After returning advice : joinpoint가 정상적으로 완료된 후에 실행이 된다.
                                   예외를 던지는 상황은 정상적인 상황에서 제외된다.

- After throwing advice : 어떤 메소드가 예외를 던지면 실행이 된다.

- Around advice : 메소드 호출과 같이 joinpoint를 감싸는 Advice. advice중에 가장 능력이 좋다
                          메소드 호출 전과 후에 어떤 것을 실행할 수 있다.
                          joinpoint 이 후에 실행될 작업을 계속 수행할지 말지 정할 수 있다.
                         수행하지 않을 때는 자신이 수행할 메소드 대신에 값을 반환하거나 예외를 던질 수 있다.

- 이중에서 필요한 기능을 수행할 수 있는 가장 최소화된 능력을 발휘하는
  Advice를 사용하는 것을 권장한다
  예를 들어) 어떤 메소드가 값을 반환한 이후 cache를 업데이트 하려고 할 때
                 Around advice를 사용할 수도 있겠지만 After returning advice를 사용한다
  이렇게 가장 구체적인 Advice타입을 사용하는 것은 잠재적으로 발생할 에러를 방지 할수 있다.

 

 

 

 

-------------------------------------------/WEB-INF/struts-config.xml
        <action
            path="/List"
            type="board.action.ListAction">
            <forward name="list" path="/list.jsp"/>
        </action>

-------------------------------------------ListAction.java
package board.action;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import board.dao.BoardDAO;
import board.form.BoardUtilForm;

public class ListAction extends Action{
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm    form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception{
       
        BoardDAO boardDao=new BoardDAO();
        Connection conn=getConnection();
        int offset=0;
        String offset_get=request.getParameter("offset");
        if(offset_get==null){
            offset=0;
        }
        else{
            offset=Integer.parseInt(offset_get);
        }
       
        int limit=10;
        int rcnt=0;
        List list=null;
        BoardUtilForm boardUtilForm=null;
       
        try{
            rcnt=boardDao.boardCount(conn);
            request.setAttribute("rcnt", rcnt);
            list=boardDao.getBoardList(offset,limit,conn);
        }catch(Exception e){
            throw new ServletException(e);
        }finally{
            if(conn!=null) try { conn.close(); } catch(SQLException e){}
        }
       
        request.setAttribute("list", list);
        return mapping.findForward("list");
    }
   
    private Connection getConnection() throws Exception{
        Context initCtx=new InitialContext();
        DataSource ds  =(DataSource)initCtx.lookup("java:comp/env/jdbc/oracle");
        return ds.getConnection();
    }
}

-------------------------------------------BoardDAO.java 추가
    public List getBoardList(int offset,int limit,Connection conn) throws SQLException{
        Statement stat=null;
        ResultSet rs=null;
        String sql=null;
        List boardList=new ArrayList();
       
        try{
            stat=conn.createStatement();
            sql=" Select a.* ";
            sql+="       From ( ";
            sql+="             Select ROWNUM as RNUM, b.* ";
            sql+="             FROM ( ";
            sql+="                    Select * From board2 Order By idx desc ";
            sql+="                  ) b ";
            sql+="             ) a ";
            sql+="             Where a.RNUM >"+offset+" ";
            sql+="             And a.RNUM<="+(offset+limit)+" ";
            rs=stat.executeQuery(sql);
           
            while(rs.next()){
                BoardDTO BoardDto=new BoardDTO(
                                  rs.getInt("idx"),
                                  rs.getString("name"),
                                  rs.getString("email"),
                                  rs.getString("homepage"),
                                  rs.getString("title"),
                                  rs.getString("content").replace("\n", "<br>"),
                                  rs.getString("pwd"),
                                  rs.getString("wdate").substring(0,10),
                                  rs.getInt("hit")                     
                                  );
                boardList.add(BoardDto);
            }   
        }catch(Exception e){}
        finally{
            rs.close();
            stat.close();
        }
       
        return boardList;
    }
}

-------------------------------------------list.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ page import="util.*" %>    
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>
   
<!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>글목록</title>
  <script type="text/javascript">
  <!--
 function send(f){
   if(f.search.value==""){
    alert("검색어 입력!!");
    f.search.focus();
    return false;
   }
   f.submit();
  }
  //-->
  </script>
</head>
<body>
<br/>* 글목록<br/><br/>
글갯수 : <bean:write name="rcnt"/>
<br/>
<table border=1>
<tr>
  <td>번호</td>
  <td>일자</td>
  <td>제목</td>
  <td>이름</td> 
  <td>조회</td>
</tr>

<logic:notEmpty name="list">
  <logic:iterate id="boardList" name="list">
    <tr>
      <td><bean:write name="boardList" property="idx"/></td>
      <td><bean:write name="boardList" property="wdate"/></td>
      <td><a href="Content.do?idx=<bean:write name="boardList" property="idx"/>"><bean:write name="boardList" property="title"/></a></td>
      <td><bean:write name="boardList" property="name"/></td>
      <td><bean:write name="boardList" property="hit"/></td>
    </tr>
  </logic:iterate>
</logic:notEmpty>
</table>
<br/>

<%
int pagelink=1;
String pagelink_get=request.getParameter("pagelink");
if(pagelink_get==null){
 pagelink=1;
}
else{
 pagelink=Integer.parseInt(pagelink_get);
}

Integer rcnt=(Integer)request.getAttribute("rcnt");
PagingCount pc=new PagingCount(rcnt.intValue());
out.println(pc.showPaging(pagelink, "List.do"));
%>
<br/>

<%--
<html:form method="post" action="Search.do" focus="search">
<table border=1>
<tr>
  <td>
    <html:select property="find">
      <html:option value="name">이름</html:option>
      <html:option value="title">제목</html:option>
      <html:option value="content">내용</html:option>
    </html:select>
    <html:text property="search"></html:text>
    <html:button property="btn" onclick="send(this.form)">검색</html:button>
  </td>
</tr>
</table>
</html:form>
--%>

<br/>
<a href="Write.do">글쓰기</a>
</body>
</html>

-------------------------------------------PagingCount.java
package util;

public class PagingCount  {
   
    int links=10 ;
    int limit=10;  
    int totalpage = 0 ;
   
    public PagingCount() {
        super();
   
    }

    public PagingCount(int numrows) {
        super();
   
        this.totalpage=((numrows-1)/limit)+1 ;
    }
   
    public PagingCount(int numrows, int links, int limit) {
        super();
        this.links = links;
        this.limit = limit;
        this.totalpage=((numrows-1)/limit)+1 ;
    }


    public int countOffset (int page) {
       
        int offset=(page-1) * this.limit;
        return offset ;
    }
   
    public String showPaging(int pagelink,String pagename) {
       
   String str = "";
       
    str="<TABLE width=\"550\" border=\"1\" align=\"center\">";
    str=str+"<TR><TD align=\"center\" bgcolor=\"#CCCCCC\">";
           
       
            int bpage = 0 ;
            int boffset = 0 ;

            int cpage = 0 ;
            int coffset = 0 ;

            int vpage = 0 ;
            int noffset = 0 ;

            int loffset = 0 ;

   
//          <!-- 1 페이지 -->
            if(pagelink != 1 ){
                str=str+"[<A HREF="+pagename+"?pagelink=1&offset=0><FONT SIZE=2 COLOR=red>처음</FONT></A>]";
            }
            else{
                str=str+"[<FONT SIZE=2 COLOR=gray>처음</FONT>]";
           
            }

//          <!-- 이전10 -->
            bpage=pagelink - 10 ;
            boffset= countOffset (bpage);
            if(pagelink > links){
                str = str + "[<A HREF="+pagename+"?pagelink="+bpage+"&offset="+boffset+"><FONT SIZE=2 COLOR=blue>이전10</FONT></A>]"  ;  
           
            }
            else{
                str = str + "[<FONT SIZE=2 COLOR=gray>이전10</FONT>]"  ;
           
            }
//          <!-- 링크페이지 -->
            vpage = pagelink ;        // 현재페이지를 잠깐 다른변수에 아래서 사용함
            pagelink= ((pagelink-1)/links)*links+1  ;   // 시작 페이지 구하기
            for(cpage=pagelink; cpage < pagelink+links; cpage++) {
             if(cpage>totalpage){ 
               break ;
             }
             coffset=countOffset (cpage);
              if(cpage!=vpage){
                  str = str + "[<A HREF="+pagename+"?pagelink="+cpage+"&offset="+coffset+"><FONT SIZE=2 COLOR=black>"+cpage+"</FONT></A>]"  ;
           
              }
              else{
                  str = str + "[<FONT SIZE=2 COLOR=red>"+cpage+"</FONT>]"  ;
           
              }
            }

//          <!-- 다음10 -->
//           for문을 빠져 나왔을때 cpage의 값은 1만큼 더 증가되어있기 때문에 그냥 사용한다. 
            noffset=countOffset (cpage);
            if((totalpage-pagelink) >= links){
                str = str + "[<A HREF="+pagename+"?pagelink="+cpage+"&offset="+noffset+"><FONT SIZE=2 COLOR=blue>다음10</FONT></A>]"  ;
           
            }
            else{
                str = str + "[<FONT SIZE=2 COLOR=gray>다음10</FONT>]"  ;
           
            }

//          <!-- 마지막페이지 -->
            loffset=countOffset (totalpage);

            if(vpage!=totalpage){
                str = str + "[<A HREF="+pagename+"?pagelink="+totalpage+"&offset="+loffset+"><FONT SIZE=2 COLOR=red>마지막</FONT></A>]"  ;
           
            }
            else{
                str = str + "[<FONT SIZE=2 COLOR=gray>마지막</FONT>]"  ;
           
            }
           
            str = str + "</TD></TR></TABLE>"  ;
       
      return str ;
    }  
    public String showPaging(int pagelink,String pagename,String find,String search) {
       
           String str = "";
               
            str="<TABLE width=\"550\" border=\"1\" align=\"center\">";
            str=str+"<TR><TD align=\"center\" bgcolor=\"#CCCCCC\">";
                   
               
                    int bpage = 0 ;
                    int boffset = 0 ;

                    int cpage = 0 ;
                    int coffset = 0 ;

                    int vpage = 0 ;
                    int noffset = 0 ;

                    int loffset = 0 ;

           
//                  <!-- 1 페이지 -->
                    if(pagelink != 1 ){
                        str=str+"[<A HREF="+pagename+"?pagelink=1&offset=0&find="+find+"&search="+search+"><FONT SIZE=2 COLOR=red>처음</FONT></A>]";
                    }
                    else{
                        str=str+"[<FONT SIZE=2 COLOR=gray>처음</FONT>]";
                   
                    }

//                  <!-- 이전10 -->
                    bpage=pagelink - 10 ;
                    boffset= countOffset (bpage);
                    if(pagelink > links){
                        str = str + "[<A HREF="+pagename+"?pagelink="+bpage+"&offset="+boffset+"&find="+find+"&search="+search+"><FONT SIZE=2 COLOR=blue>이전10</FONT></A>]"  ;  
                   
                    }
                    else{
                        str = str + "[<FONT SIZE=2 COLOR=gray>이전10</FONT>]"  ;
                   
                    }
//                  <!-- 링크페이지 -->
                    vpage = pagelink ;        // 현재페이지를 잠깐 다른변수에 아래서 사용함
                    pagelink= ((pagelink-1)/links)*links+1  ;   // 시작 페이지 구하기
                    for(cpage=pagelink; cpage < pagelink+links; cpage++) {
                     if(cpage>totalpage){ 
                       break ;
                     }
                     coffset=countOffset (cpage);
                      if(cpage!=vpage){
                          str = str + "[<A HREF="+pagename+"?pagelink="+cpage+"&offset="+coffset+"&find="+find+"&search="+search+"><FONT SIZE=2 COLOR=black>"+cpage+"</FONT></A>]"  ;
                   
                      }
                      else{
                          str = str + "[<FONT SIZE=2 COLOR=red>"+cpage+"</FONT>]"  ;
                   
                      }
                    }

//                  <!-- 다음10 -->
//                   for문을 빠져 나왔을때 cpage의 값은 1만큼 더 증가되어있기 때문에 그냥 사용한다. 
                    noffset=countOffset (cpage);
                    if((totalpage-pagelink) >= links){
                        str = str + "[<A HREF="+pagename+"?pagelink="+cpage+"&offset="+noffset+"&find="+find+"&search="+search+"><FONT SIZE=2 COLOR=blue>다음10</FONT></A>]"  ;
                   
                    }
                    else{
                        str = str + "[<FONT SIZE=2 COLOR=gray>다음10</FONT>]"  ;
                   
                    }

//                  <!-- 마지막페이지 -->
                    loffset=countOffset (totalpage);

                    if(vpage!=totalpage){
                        str = str + "[<A HREF="+pagename+"?pagelink="+totalpage+"&offset="+loffset+"&find="+find+"&search="+search+"><FONT SIZE=2 COLOR=red>마지막</FONT></A>]"  ;
                   
                    }
                    else{
                        str = str + "[<FONT SIZE=2 COLOR=gray>마지막</FONT>]"  ;
                   
                    }
                   
                    str = str + "</TD></TR></TABLE>"  ;
               
              return str ;
            }  
       
}
   
-----------------------------------------------

 

- 스트럿츠 다운
   http://struts.apache.org/downloads.html
   Struts 1.3.10 -> struts-1.3.10-all.zip 다운 및 압축풀기

 

- 이클립스에서 struts1 라이브러리 추가 순서
   프로젝트 미리 생성하지 말고 war파일 설치함과 동시에 프로젝트 생성할 것
   (.war 대부분 샘플용으로 압축해서 배포됨)
   New -> import -> Web -> WAR ->
   D:\해당경로\struts-1.3.10-all\struts-1.3.10\apps\struts-blank-1.3.10.war

   프로젝트명 : struts1Board

-----------------------------------------------[테이블생성]
create table board2(
     idx int primary key,
     name varchar(10),
     email varchar(50),
     homepage varchar(50),
     title varchar(50),
     content varchar(2000),
     pwd varchar(10),
     wdate date,
     hit int
);
create sequence board2_idx_seq;

------------------------------------------------[결과확인]
http://localhost:9090/struts1Board/Write.do

------------------------------------------------BoardForm.java
package board.form;

import org.apache.struts.action.ActionForm;

public class BoardForm extends ActionForm {
    int idx;
    String name;
    String email;
    String homepage;
    String title;
    String content;
    String pwd;
    String wdate;
    int hit;

    getter와 setter 생성   

}

-----------------------------------------------BoardUtilForm.java
package board.form;

public class BoardUtilForm {
    private int rcnt;
    private int limit;
    private int pagelink;

    getter와 setter생성

}

-----------------------------------------------BoardDTO.java
package board.dto;

import java.io.Serializable;

public class BoardDTO implements Serializable {
    int idx;
    String name;
    String email;
    String homepage;
    String title;
    String content;
    String pwd;
    String wdate;
    int hit;
  
    기본생성자
    인자 있는 생성자
    getter와 setter생성  
   
}

-----------------------------------------------BoardDAO.java
package board.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import board.dto.BoardDTO;
import board.form.BoardForm;

public class BoardDAO {
    public BoardDAO() { }
   
    public int boardCount(Connection conn) throws SQLException{
        int rcnt=0;
       
        Statement stat=null;
        ResultSet rs=null;
        String sql=null;
        try{
            stat=conn.createStatement();
            sql=" SELECT count(*) from board2 ";
            rs=stat.executeQuery(sql);
            if(rs.next()){
                rcnt=rs.getInt(1);
            }
        }catch(Exception e){
            System.out.print(e+"보드카운트");
        }finally{
            rs.close();
            stat.close();
        }
        return rcnt;
    }
   
}

-----------------------------------------------/WEB-INF/web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
  <!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <display-name>Struts Blank Application</display-name>
 
  <!-- Standard Action Servlet Configuration -->
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
 </servlet>


  <!-- Standard Action Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>


  <!-- The Usual Welcome File List -->
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>

-------------------------------------------/WEB-INF/struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>

    <form-beans>
        <form-bean
            name="boardForm"
            type="board.form.BoardForm"/>
    </form-beans>

    <action-mappings>
            <!-- Default "Welcome" action -->
            <!-- Forwards to Welcome.jsp -->
        <action
            path="/Welcome"
            forward="/pages/Welcome.jsp"/>

        <action
            path="/Write"
            forward="/write.jsp"/>

</struts-config>

-------------------------------------------write.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>

<html:html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>게시판글쓰기</title>
  <script type="text/javascript">
  <!--
   function trans(f){
        f.submit();
   }
  //-->
  </script>
</head>
<body>
<br/>* 글쓰기 * <br/>

<html:form method="post" action="WriteOk.do" focus="name">
<table border=1>
<tr>
  <td>이름</td>
  <td><html:text property="name" size="30"></html:text></td>
</tr>
<tr>
  <td>이메일</td>
  <td><html:text property="email" size="30"></html:text></td>
</tr>
<tr>
  <td>홈페이지</td>
  <td><html:text property="homepage" size="30"></html:text></td>
</tr>
<tr>
  <td>제목</td>
  <td><html:text property="title" size="50"></html:text></td>
</tr>
<tr>
  <td>본문</td>
  <td><html:textarea property="content" rows="10" cols="50"></html:textarea></td>
</tr>
<tr>
  <td>암호</td>
  <td><html:password property="pwd" size="10"></html:password></td>
</tr>
<tr>
  <td colspan=2>
    <html:button property="btn" onclick="trans(this.form)">글올리기</html:button>
    <html:reset>다시쓰기</html:reset>
  </td>
</tr>

</table>
</html:form>

<br/>

<a href="./List.do">리스트</a>

</body>
</html:html>

-------------------------------------------/WEB-INF/struts-config.xml
        <action
            path="/WriteOk"
            type="board.action.WriteAction"
            name="boardForm"
            scope="request"
            validate="false"
            input="/write.jsp">
            <forward name="ok" redirect="true" path="/List.do"/>
        </action>

-------------------------------------------WriteAction.java
package board.action;

import java.rmi.ServerException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import board.dao.BoardDAO;
import board.form.BoardForm;

public class WriteAction extends Action{
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm    form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception{
       
        BoardDAO boardDao=new BoardDAO();
        BoardForm boardForm=(BoardForm) form;
        Connection conn=getConnection();
        try{
            boardDao.boardInsert(boardForm,conn);
        }catch(Exception e){
            throw new ServletException(e);
        }finally{
            if(conn!=null) try { conn.close(); } catch(SQLException e){}
        }
        return mapping.findForward("ok");
    }

    private Connection getConnection() throws Exception{
        Context initCtx=new InitialContext();
        DataSource ds  =(DataSource)initCtx.lookup("java:comp/env/jdbc/oracle");
        return ds.getConnection();
    }
   
}

-------------------------------------------BoardDAO.java 추가
    public void boardInsert(BoardForm boardform,Connection conn) throws SQLException{
        Statement stat=conn.createStatement();
        String sql="";
       
        String name=boardform.getName();
        String email=boardform.getEmail();
        String homepage=boardform.getHomepage();
        String title=boardform.getTitle();
        String content=boardform.getContent();
        String pwd=boardform.getPwd();
        try{
            sql=" INSERT INTO board2 ";
            sql+=" VALUES(board2_idx_seq.nextval";
            sql+=" ,'"+name+"'";
            sql+=" ,'"+email+"'";
            sql+=" ,'"+homepage+"'";
            sql+=" ,'"+title+"'";
            sql+=" ,'"+content+"'";
            sql+=" ,'"+pwd+"'";
            sql+=",sysdate,0)";
           
            sql=new String(sql.getBytes("8859_1"),"euc-kr");
            stat.executeUpdate(sql);
            //System.out.println(sql);
        }catch(Exception e){
            System.out.print(e);
        }finally{
            stat.close();
        }
    }

 

----------------------------------------------------[스트럿츠 기본]


1. 스트럿츠
- JSP모델2 MVC구조로 개발할 수 있는 기반을 제공하는 프레임 워크이다
- XML기반의 Controller역할을 담당한다

 

2. 스트럿츠로 구현하는 MVC

1) Model : 상태정보를 가지고 있는 자바빈즈(DTO)와
               상태에 변화를 줄 수 있는 로직을 담고 있는 자바빈즈(DAO)가 수행한다

2) View : 뷰 역할은 JSP를 사용한다.
             스트럿츠에서는 스트럿츠의 다른 컴포넌트들과 쉽고 편리하게 결합될 수 있는
             태그라이브러리를 제공하는데 이를 이용하면 JSP코드가 가독성이 높아지고 소스가 간단해 진다

3) Controller : 컨트롤러 역할은 ActionServlet과 Action클래스에서 호출하는 클래스가 이에 해당한다
                     요청 컨트롤러 서블릿을 따로 만들 필요가 없고 ActionServlet이 그 역할을 해주고 있으며
                     ActionServlet에서 실제 로직을 수행하는 액션 클래스를 실행한다
                     컨트롤러의 역할 가운데 하나인 리소스(주로 jsp)포워드는 어떻게 하느냐?
                     스트럿츠 설정파일 struts-config.xml파일에서 지정한 액션 매핑을 이용한다.

 

3. 스트럿츠의 단점
- 기능이 너무 다양해서 설정파일의 복잡도가 높다


-----------------------------------------------------스트럿츠 다운
http://struts.apache.org/downloads.html
Struts 1.3.10 -> struts-1.3.10-all.zip 다운 및 압축풀기

 

이클립스에서 struts1 라이브러리 추가 순서
프로젝트 미리 생성하지 말고 war파일 설치함과 동시에 프로젝트 생성할 것
(.war 대부분 샘플용으로 압축해서 배포됨)

New -> import -> Web -> WAR ->
D:\jsp2_week\setup\struts-1.3.10-all\struts-1.3.10\apps\struts-blank-1.3.10.war
프로젝트명 : struts1Test

 

-----------------------------------------------/WEB-INF/web.xml
<web-app>
  <display-name>Struts Blank Application</display-name>
 
  <!-- Standard Action Servlet Configuration -->
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
 </servlet>


  <!-- Standard Action Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

</web-app>

-----------------------------------------------/WEB-INF/struts-config.xml
    <action-mappings>
        <action
            path="/HelloAction"
            type="test.HelloAction"
            forward="/hello.jsp">
            <forward name="tohello" path="/hello.jsp"/>
    </action-mappings>

 

action은 *.do로 시작하므로 *에 들어가는 값이 path의 HelloAction일때
즉 웹에서 HelloAction.do를 요청하면 struts-config.xml의 action-mapping의 path가

HelloAction인 action이 실행된다

-------------------------------------------------------
struts-config.xml은 항상 다음의 순서로만 작성되어야 한다
<struts-config>
   <data-sources/>
   <form-beans/>
   <global-exceptions/>
   <global-forwards/>
   <action-mappings>
   <controller/>
   <message-resources/>
   <plug-in/>
</struts-config>

--------------------------------------------------------결과확인

http://localhost:9090/struts1Board/LoginForm.do

 

--------------------------------------------------------스트럿츠 클래스의 활용

1. action을 사용한 로그인

 

1) 구현할 파일
    struts-config.xml (controller)
    LoginAction.java (command)
    LoginDTO.java (dto)
    LoginDAO.java(connection pool)
    LoginForm.jsp
    Logon.jsp
    Fail.jsp

 

2) struts-config.xml

        <action
            path="/LoginForm"
            forward="/login/LoginForm.jsp"/>

        <action
            path="/Login"
            type="login.LoginAction"
            validate="false"
            scope="request">
            <forward name="logon" path="/login/Logon.jsp"/>
            <forward name="fail" path="/login/Fail.jsp"/>
         </action>

 

path : *.do의 .do를 제외한 '*'
forward : 해당 위치로 이동
Type : 자바클래스를 실행한다
validate : true일 경우 유효성 검사를 하는데 이때 ActionForm클래스 안에 있는
               validate메소드가 실행된다(직접코딩)
reset : ActionForm클래스 안의 파라미터를 모두 리셋시킨다
scope : 모델에서 넘어오는 값을 리턴 받아 request, session, application등의 형태를
            scope에 저장하여 view페이지를 지정한 뒤 리턴한다.

첫번째 action은 기본 action으로 path에 따라 forward되며
두번째 action은 path에 따라 자바클래스를 돌고 forward된다

-------------------------------------------------[Struts의 주요 클래스]

1. ActionServlet
   - servlet.
   - 모든 클라이언트의 요청을 제일 먼저 맞이한다.
   - 톰캣 구동시 같이 메모리에 로딩
   - init() 메소드를 통해 /WEB-INF/struts-config.xml
     파일에 있는 내용들을 ServletContext 객체에 저장

2. Action
   - 실제적인 비즈니스 로직 처리를 담당한다

   - Controller로서 Model 영역과 접점을 가지는 객체.

   - 사용자의 HTTP 요청에 반응하는 객체로서, struts-config.xml에 저장된

     action element에 따라 객체가 생성됨. 이때 객체는 매번 생성되는 것이

     아니라 단 한번 생성되어 재 사용된다.

   - 보통 직접 Action 클래스를 사용하지 않고 Action 클래스를 상속받는 클래스를

     제작하게 되고 Action 클래스가 가지고 있는 execute() 메소드를 오버라이딩하게 한다.

   - 실제 개발자는 Model과의 작업을 위해 execute() 메소드에서

     Model쪽 Manager 객체를 생성하고 관련 비즈니스 메소드를 호출하는 작업을 한다.

3. RequestProcessor
   - 요청 파라미터 값을 자동으로 ActionForm에 저장한다
   - ActionServlet의 분석 결과에 따라 Action을 선택한다
   - ActionServlet을 대신하여 Action의 execute() 메소드를 호출하는 역할.
   - execute() 메소드 호출 결과인 ActionForward에 따라 View를 연결한다.
   예) /login.do를 사용작 요청하면 struts-config에서 /login으로 지정된 action을 찾아 수행한다

4. ActionForward

   - Controller의 execute() 호출 결과로서, 페이지 이동에 대한 정보를 객체화 한 것.

   - 객체를 통해 forward할 것인지, redirect할 것인지 정해진다.

5. ActionForm

   - HTTP 요청에 따라 파라미터를 처리하기 위한 클래스.

   - 테이터를 저장하고 전달하는 DTO(Data Transfer Object) 객체.

   - ActionForm을 상속받는 형태로 작성.

   - ActionForm 객체의 필드는 자동으로 세팅된다.

   - reset() 메소드로 필드 초기화

   - validate() 메소드로 유효성 검증
   - 유효성 여부에 따라 Action 수행 여부가 결정된다

   - 보통의 Bean 클래스처럼 필드에 접근처리할 수 있는 setter, getter를 작성하면 된다.

6. ActionMapping

   - 사용자 HTTP 접근에 따라 어떠한 Action 객체가 사용되어야 하는지, 그 Action 처리 후

     어느 페이지로 이동해야 하는지에 대한 정보가 struts-config.xml에 있다.

     이 ActionMapping은 그 중에서 이동할 페이지에 대한 맵핑을 가진 객체이다.

     지정된 이름의 forward를 찾아서 ActionForward 객체를 돌려주게 된다.

7. ActionMessages

   - 각종 메시지를 처리하는 클래스. (에러 포함)

8. ActionMessage

   - 한 개의 메시지 처리.

9. ActionErrors

   - 각종 에러 메시지를 처리하는 클래스

   - ActionMessages를 상속받고 있음.

10. ActionError

   - 한 개의 에러 메시지 처리.

 

>>>>>>>>>>>>>>>>>> 1. ActionForm을 사용한 로그인 >>>>>>>>>>>


>>>>>>>>>>>>>>>>>>>>>>>> 작성순서 >>>>>>>>>>>>>>>>>>>>>>>>>

 

------------------------------------------------------------결과확인
http://localhost:9090/struts1Test/LoginForm.do


--------------------------------------/WebContent/login/LoginForm.jsp
<%@ 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>LoginForm.jsp</TITLE>
</HEAD>

<BODY>
<form name="frm" method="post" action="Login.do">
      아이디 : <input type="text" name="id" /><br/>
      비번 :    <input type="password" name="passwd" /><br/>
                  <input type="submit" value="확인" />
</form>

</BODY>
</HTML>
--------------------------------------/WebContent/login/Logon.jsp
<%@ 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>logon.jsp</title>
</head>
<body>
      로그인 성공<br/>
      <%=request.getParameter("id") %><br/>
      <%=request.getParameter("passwd") %><br/>
</body>
</html>
--------------------------------------/WebContent/login/Fail.jsp
<%@ 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>Fail.jsp</title>
</head>
<body>
      로그인 실패
</body>
</html>
---------------------------------------LoginDAO.java
package login;

import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class LoginDAO {
   
    private Connection getConnection() throws Exception{
        Context initCtx=new InitialContext();
        DataSource ds  =(DataSource)initCtx.lookup("java:comp/env/jdbc/oracle");
        return ds.getConnection();
    }
   
    public boolean isLogin(LoginDTO dto){
        String id=dto.getId();
        String passwd=dto.getPasswd();

        if(id.equals("user")&&passwd.equals("1234")){
            return true;           
        }
        else{
            return false;
        }
    }
}
---------------------------------------LoginDTO.java
package login;

public class LoginDTO {
   
    private String id;
    private String passwd;
   
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPasswd() {
        return passwd;
    }
    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
    @Override
    public String toString() {
        return "LoginBean [id=" + id + ", passwd=" + passwd + "]";
    }
   
}
---------------------------------------LoginAction.java
package login;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class LoginAction extends Action {
    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
       
        System.out.println("LoginAction");
       
        LoginDTO dto=new LoginDTO();
        dto.setId(request.getParameter("id"));
        dto.setPasswd(request.getParameter("passwd"));

        LoginDAO dao=new LoginDAO();
        boolean result=dao.isLogin(dto);
       
        if(result){
            return mapping.findForward("logon");
        }
        else{
            return mapping.findForward("fail");
        }
    }
}


>>>>>>>>>>>>>>>>>> 2. ActionForm을 사용한 로그인 >>>>>>>>>>>

 

- 장점 : DAO에서 request.getParameter()를 쓰지 않고, ActionForm을 쓴다

- LoginActionForm.java 추가

 

>>>>>>>>>>>>>>>>>>>>>>>>작성순서>>>>>>>>>>>>>>>>>>>>>

---------------------------------/WebContent/actionform/LoginForm.jsp

---------------------------------/WebContent/actionform/Logon.jsp

---------------------------------/WebContent/actionform/Fail.jsp

파일 3개는 위의 내용과 동일

 

--------------------------------------------------LoginActionForm.java
package actionform;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;

public class LoginActionForm extends ActionForm {
    private String id;
    private String passwd;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPasswd() {
        return passwd;
    }
    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
   
    //유효성검사, id와 passwd에 값이 들어있지 않을때 에러발생
    @Override
    public ActionErrors validate(ActionMapping mapping,
            HttpServletRequest request) {
        System.out.println("validate호출");
        if(id==null || id.length()==0){
            System.out.println("아이디 입력바람!!");
        }
        if(passwd==null || passwd.length()==0){
            System.out.println("비번 입력바람!!");
        }
        return null;
    }
   
    //세션에 저장되어 있는 LoginActionForm을 초기화 한다
    @Override
    public void reset(ActionMapping mapping, HttpServletRequest request) {
        this.id=null;
        this.passwd=null;
    }
}

--------------------------------------------------LoginAction.java
package actionform;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import login.LoginDAO;
import login.LoginDTO;

public class LoginAction extends Action {
    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        //request.getParameter("id")가 없어지고
        //ActionForm이 파라미터 값을 받아 유효성 검사를 한 후에 넘겨준다
        //validate가 true일때
       
        LoginActionForm laf=(LoginActionForm)form;
        String id=laf.getId();
        String passwd=laf.getPasswd();
       
        LoginDTO dto=new LoginDTO();
        dto.setId(id);
        dto.setPasswd(passwd);
       
        LoginDAO dao=new LoginDAO();
        boolean result=dao.isLogin(dto);
       
        if(result){
            return mapping.findForward("logon");
        }
        else{
            return mapping.findForward("fail");
        }                      
    }
}
---------------------------------------------/WEB-INF/struts-config.xml

ActionForm을 쓸때는 form-bean의 name과 action의 name이 같아야 한다

<struts-config>
    <form-beans>
        <form-bean
            name="ActionForm"
            type="actionform.LoginActionForm"/>
    </form-beans>


   <action-mappings>
          
        <action
            path="/LoginActionForm"
            forward="/actionform/LoginForm.jsp"/>

        <action
            name="ActionForm"
            path="/ActionForm"
            type="actionform.LoginAction"
            validate="true"
            scope="request">
            <forward name="logon" path="/actionform/Logon.jsp"/>
            <forward name="fail" path="/actionform/Fail.jsp"/>
         </action>

    </action-mappings>
</struts-config>
----------------------------------------------------------------결과확인
http://localhost:9090/struts1Test/LoginActionForm.do


 

--------------------------------------------/WEB-INF/CommandPro.properties 추가
/mvc2bbs/deleteForm.do=my.action.DeleteFormAction

------------------------------------------------------------DeleteFormAction.java
package my.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DeleteFormAction implements CommandAction {

    @Override
    public String requestPro(HttpServletRequest request,
                    HttpServletResponse response) throws Throwable {
        int num=Integer.parseInt(request.getParameter("num"));
        String pageNum=request.getParameter("pageNum");
       
        request.setAttribute("num", new Integer(num));
        request.setAttribute("pageNum", new Integer(pageNum));
       
        return "deleteForm.jsp";       
    }
}
------------------------------------------------------------deleteForm.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ include file="/view/color.jspf" %>
<!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">
<link href="style.css" rel="stylesheet" type="text/css">
<title>게시판</title>
<script language="javaScript">
function deleteSave(){
    if(document.delForm.passwd.value==''){
        alert("비밀번호를 입력하십시요.");
        document.delForm.passwd.focus();
        return false;
    }
}
</script>
</head>
<body bgcolor="${bodyback_c }">
<center><b>글삭제</b></center>
<br/>
<form method="post" name="delForm" action="/mvc2bbs/deletePro.do?pageNum=${pageNum }" onsubmit="return deleteSave()">
<table border="1" align="center" cellspacing="0" cellpadding="0" width="360">
    <tr height="30">
        <td align="center" bgcolor="${value_c }">
            <b>비밀번호를 입력해주세요.</b>
        </td>
    </tr>
    <tr height="30">
        <td align="center"> 비밀번호:
            <input type="password" name="passwd" size="8" maxlength="12">
            <input type="hidden" name="num" value="${num }">
        </td>
    </tr>
    <tr height="30">
        <td align="center" bgcolor="${value_c }">
            <input type="submit" value="글삭제">
            <input type="button" value="글목록" onClick="document.location.href='/mvc2bbs/list.do?pageNum=${pageNum}'">
        </td>
    </tr>  
</table>
</form>
</body>
</html>
--------------------------------------------/WEB-INF/CommandPro.properties 추가
/mvc2bbs/deletePro.do=my.action.DeleteProAction

------------------------------------------------------------DeleteProAction.java
package my.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import my.board.BoardDBBean;

public class DeleteProAction implements CommandAction {

    @Override
    public String requestPro(HttpServletRequest request,
            HttpServletResponse response) throws Throwable {
        request.setCharacterEncoding("euc-kr");
       
        int num=Integer.parseInt(request.getParameter("num"));
        String pageNum=request.getParameter("pageNum");
        String passwd=request.getParameter("passwd");
       
        BoardDBBean dbPro=BoardDBBean.getInstance();
        int check=dbPro.deleteArticle(num,passwd);
       
        //해당뷰에서 사용할 속성
        request.setAttribute("pageNum", new Integer(pageNum));
        request.setAttribute("check", new Integer(check));
       
        return "deletePro.jsp";//해당뷰
    }

}
------------------------------------------------------------BoardDBBean.java추가
//글삭제
public int deleteArticle(int num, String passwd)throws Exception{
    Connection conn=null;
    PreparedStatement pstmt=null;
    ResultSet rs=null;
    String dbpasswd="";
    int x=-1;
    try{
        conn=getConnection();
        pstmt=conn.prepareStatement("SELECT passwd FROM board WHERE num=?");
        pstmt.setInt(1, num);
        rs=pstmt.executeQuery();
                   
        if(rs.next()){
            dbpasswd=rs.getString("passwd");
            if(dbpasswd.equals(passwd)){
                pstmt=conn.prepareStatement("DELETE FROM board WHERE num=?");
                pstmt.setInt(1, num);
                pstmt.executeUpdate();
                x=1;//글삭제 성공
            }
            else{
                x=0;//비밀번호 틀림
            }
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }finally{
        if(rs!=null)try{rs.close();}catch(SQLException e){}
        if(pstmt!=null)try{pstmt.close();}catch(SQLException e){}
        if(conn!=null)try{conn.close();}catch(SQLException e){}
    }
    return x;
}//deleteArticle
------------------------------------------------------------deleteProjsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${check==1}">
    <meta http-equiv="Refresh" content="0;url=/mvc2bbs/list.do?pageNum=${pageNum }">
</c:if>
<c:if test="${check==0}">
     비밀번호가 다릅니다.
    <br>
    <a href="javascript:history.go(-1)">[글 삭제폼으로 돌아가기]</a>
</c:if>

 

 

+ Recent posts