달력

092017  이전 다음

  •  
  •  
  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

Java WebService 를 이용할때 Axis 나 CXF 를 자주 이용하게 되는데,

프로젝트 셋팅할 때 Logging 설정을 미리 해 놓으면 웹서비스의 요청/응답에 대한 XML 흐름을 log4j 등을 

이용하여 볼 수 있지만, 만약 못해놓은 상태에서 급하게 봐야 한다면 다음과 같이 설정 하고

Fiddler2 를 이용하면 요청/응답의 XML 흐름을 볼 수 있다.


Main 메소드 또는 웹서비스를 호출하는 수정 가능한 클래스에 프록시 Property 설정 추가.

System.setProperty("http.proxyHost", "localhost");

System.setProperty("http.proxyPort", "8888");


그리고 Fiddler2 를 띠워보면 아래와 같이 나온다.

XML 이 깨지면 Notepad++ 같은 툴을 이용하던, Eclipse, Visual studio 등을 이용하여 Formatting 하여 이쁘게 보면 됨.


신고
Posted by Tornado tornado

[출처] http://www.rgagnon.com/javadetails/java-0490.html



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

For a single file, a thread is launched to check the lastModified value and compare it with the previous value.

import java.util.*;
import java.io.*;

public abstract class FileWatcher extends TimerTask {
  private long timeStamp;
  private File file;

  public FileWatcher( File file ) {
    this.file = file;
    this.timeStamp = file.lastModified();
  }

  public final void run() {
    long timeStamp = file.lastModified();

    if( this.timeStamp != timeStamp ) {
      this.timeStamp = timeStamp;
      onChange(file);
    }
  }

  protected abstract void onChange( File file );
}

import java.util.*;
import java.io.*;

public class FileWatcherTest {
  public static void main(String args[]) {
    // monitor a single file
    TimerTask task = new FileWatcher( new File("c:/temp/text.txt") ) {
      protected void onChange( File file ) {
        // here we code the action on a change
        System.out.println( "File "+ file.getName() +" have change !" );
      }
    };

    Timer timer = new Timer();
    // repeat the check every second
    timer.schedule( task , new Date(), 1000 );
  }
}

For a directory, a thread is launched where we keep the Files in a Map, we check the current lastModifed value of a given file and compare it with the value stored in the Map. Also a special check is made to detect if a File is deleted.

import java.util.*;
import java.io.*;

public abstract class DirWatcher extends TimerTask {
  private String path;
  private File filesArray [];
  private HashMap dir = new HashMap();
  private DirFilterWatcher dfw;

  public DirWatcher(String path) {
    this(path, "");
  }

  public DirWatcher(String path, String filter) {
    this.path = path;
    dfw = new DirFilterWatcher(filter);
    filesArray = new File(path).listFiles(dfw);

    // transfer to the hashmap be used a reference and keep the
    // lastModfied value
    for(int i = 0; i < filesArray.length; i++) {
       dir.put(filesArray[i], new Long(filesArray[i].lastModified()));
    }
  }

  public final void run() {
    HashSet checkedFiles = new HashSet();
    filesArray = new File(path).listFiles(dfw);

    // scan the files and check for modification/addition
    for(int i = 0; i < filesArray.length; i++) {
      Long current = (Long)dir.get(filesArray[i]);
      checkedFiles.add(filesArray[i]);
      if (current == null) {
        // new file
        dir.put(filesArray[i], new Long(filesArray[i].lastModified()));
        onChange(filesArray[i], "add");
      }
      else if (current.longValue() != filesArray[i].lastModified()){
        // modified file
        dir.put(filesArray[i], new Long(filesArray[i].lastModified()));
        onChange(filesArray[i], "modify");
      }
    }

    // now check for deleted files
    Set ref = ((HashMap)dir.clone()).keySet();
    ref.removeAll((Set)checkedFiles);
    Iterator it = ref.iterator();
    while (it.hasNext()) {
      File deletedFile = (File)it.next();
      dir.remove(deletedFile);
      onChange(deletedFile, "delete");
    }
  }

  protected abstract void onChange( File file, String action );
}

import java.io.*;

public class DirFilterWatcher implements FileFilter {
  private String filter;

  public DirFilterWatcher() {
    this.filter = "";
  }

  public DirFilterWatcher(String filter) {
    this.filter = filter;
  }
  
  public boolean accept(File file) {
    if ("".equals(filter)) {
      return true;
    }
    return (file.getName().endsWith(filter));
  }
}

The example watches the c:/temp folder for any activities on any *.txt files.
import java.util.*;
import java.io.*;

public class DirWatcherTest {
  public static void main(String args[]) {
    TimerTask task = new DirWatcher("c:/temp", "txt" ) {
      protected void onChange( File file, String action ) {
        // here we code the action on a change
        System.out.println
           ( "File "+ file.getName() +" action: " + action );
      }
    };

    Timer timer = new Timer();
    timer.schedule( task , new Date(), 1000 );
  }
}

신고
Posted by Tornado tornado

스프링 프레임워크에서 아무런 동작이 필요없이 View 를 보여줄 경우 아래와 같이 하면.. 간단히 해결.

Ant 경로와 같이 줄 경우 하위 경로의 매핑도 자동으로 .. ㅎ

<bean id="urlFilenameViewController"       

                class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />

<bean id="urlMapping2" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <value>/**/*.do=urlFilenameViewController</value> </property> <property name="order" value="2" /> </bean>


위와같이 설정 후 JSP 파일경로(.do)를 호출하면 하위 경로 매핑하여 View 로 이동시켜줌.



신고
Posted by Tornado tornado
[url] http://www.ibm.com/developerworks/kr/library/ws-pojo-springcxf/


소개

이번 글에서는 CXF와 스프링을 사용해 주문 처리 웹 서비스를 구축하고 개발한다. 이 웹 서비스는 고객에게 주문을 받아 처리하고, 유효한지 점검해 유일한 주문 ID를 반환한다. 이 글을 읽은 후에 웹 서비스를 구축하고, 개발하는 데 CXF의 개념과 특징을 적용할 수 있을 것이다.

시스템 요구사항

이번 글에 나오는 예제를 실행하려면 컴퓨터에 다음 소프트웨어가 설치, 구성되어 있는지 확인해야 한다.

  • 자바(Java) 5 이상
  • 톰캣(Tomcat) 5 이상
  • 앤트(Ant) 빌드 툴
  • CXF 바이너리 배포판 2.1

위 배포판을 설치한 다음에는 다음 환경 변수를 구성하자.

  • JAVA_HOME(자바)
  • CATALINA_HOME(톰캣)
  • ANT_HOME(앤트)
  • CXF_HOME(CXF)

예제를 위해 CXF_HOME=C:\apache-cxf-2.1로 설정하고, PATH 환경 변수에 다음 내용을 추가하자.

  • JAVA_HOME\bin
  • CATALINA_HOME\bin
  • ANT_HOME\bin

왜 CXF일까?

아파치 CXF(Apache CXF)는 웹 서비스를 편리하게 구축하고, 개발하는 데 필요한 견고한 기반을 제공하는 오픈 소스 프레임워크다. 이를 이용해 성능과 확장성이 높은 서비스를 만들 수 있다. 만든 서비스는 JBoss, IBM® WebSphere®나 BEA WebLogic 톰캣과 같은 좀 더 진보된 서버 인프라뿐만 아니라 톰캣과 스프링 기반 경량급 컨테이너에 배포할 수도 있다.

특징

프레임워크는 다음과 같은 특징을 제공한다.

  • 웹 서비스 표준 지원: CXF는 다음 웹 서비스 표준을 지원한다.
    • JAX-WS(Java API for XML Web Services)
    • SOAP
    • WSDL(Web Services Description Language)
    • MTOM(Message Transmission Optimization Mechanism)
    • WS-Basic Profile
    • WS-Addressing
    • WS-Policy
    • WS-ReliableMessaging
    • WS-Security
  • 프론트엔드 모델링(front-end modeling): CXF는 다양한 프론트엔드 API를 사용해 웹 서비스를 생성하도록 해주는 프론트엔드 모델링 개념을 제공한다. 이 API는 간단히 팩토리 빈(factory beans)을 사용하고, JAX-WAS 구현을 통해 웹 서비스를 생성하도록 해준다. 또한 동적 웹 서비스 클라이언트도 생성할 수 있게 해준다.
  • 도구 지원: CXF는 자바 빈, 웹 서비스, WSDL 간에 변환을 해주는 다양한 도구를 제공한다. 메이븐(Maven)과 앤트(Ant)에 대한 통합 지원 기능을 제공하며, 스프링과의 자연스러운(seamlessly) 통합도 지원한다.
  • RESTful 서비스 지원: CXF는 RESTful(Representational State Transfer) 개념을 지원하며, 자바 플랫폼에 대한 JAX-RS 구현을 지원한다(이번 연재의 Part 2에서 RESTful 서비스에 대한 더 많은 정보를 제공하겠다).
  • 다양한 전송과 바인딩(binding) 지원: CXF는 XML에서 CSV(Comma Separated Value)에 이르기까지 여러 종류의 전송을 지원한다. 또한 JAXB(Java Architecture for XML Binding)와 SOAP과 HTTP 프로토콜 바인딩 외에 AEGIS 데이터 바인딩도 지원한다.
  • XML 이외의 바인딩 지원: CXF는 JSON(JavaScript Object Notation)과 CORBA(Common Object Request Broker Architecture) 같은 XML 이외의 바인딩을 지원한다. JBI(Java Business Integration) 아키텍처와 SCA(Service Component Architecture) 또한 지원한다.

웹 서비스 개발하기

JAX-WS 프론트엔드를 사용해 주문 처리 웹 서비스를 만들어 이를 스프링 빈(bean)으로 등록하는 방법을 확실하게 살펴보자. 자바 클래스를 먼저 개발하고, 이 클래스에 웹 서비스를 의미하는 애노테이션을 붙이는 코드 우선 접근법을 사용한다. 이를 위해서는 대체로 다음 단계를 따르면 된다.

  1. 서비스 종단 인터페이스(SEI: Service Endpoint Interface)를 만들고 웹 서비스로 노출되는 메서드를 정의한다.
  2. 구현 클래스를 만들고 웹 서비스 애노테이션을 붙인다.
  3. beans.xml을 만들고 JAX-WS 프론트엔드를 사용해 스프링 빈으로 서비스 클래스를 정의한다.
  4. 스프링과 CXF를 통합하는 web.xml을 만든다.

먼저 주문 처리 웹 서비스 SEI를 만들어보자.

주문 처리 웹 서비스 SEI 만들기

OrderProcess라는 이름으로 SEI를 만들자. 이 SEI는 order 빈을 받아 문자열을 반환하는 processOrder 메서드를 갖게 된다.processOrder 메서드의 목적은 고객에게 주문을 받아 유일한 주문 ID를 반환하도록 처리하는 것이다.


Listing 1. OrderProcess SEI
                
package demo.order;

import javax.jws.WebService;

@WebService
public interface OrderProcess {
  String processOrder(Order order);
}

Listing 1에서 볼 수 있는 것처럼, OrderProcess SEI는 웹 서비스 애노테이션이 붙은 단순한 표준 자바 인터페이스다. @WebService 애노테이션은 간단하게 인터페이스를 웹 서비스 인터페이스로 만들어준다. OrderProcess SEI는 하나의 processOrder 메서드를 갖는다. 이 메서드는 매개변수로 Order를 받아 문자열로 주문 ID를 반환한다.


Listing 2. OrderProcess 서비스 구현
                
package demo.order;

import javax.jws.WebService;

@WebService(endpointInterface = "demo.order.OrderProcess")
public class OrderProcessImpl implements OrderProcess {

 public String processOrder(Order order) {
  return order.validate();
 }
}

SEI 구현 작성하기

이전 절에서 SEI 구현을 작성하면서 구현 클래스인 OrderProcessImpl이 웹 서비스가 되도록 애노테이션을 더해 붙였고, 이전 단계에서 만들었던 SEI의 완전한 클래스 이름(fully qualified name)을 값으로 갖는 endpointInterface 속성을 제공했다. 이 값은 이 클래스가OrderProcess SEI를 구현했다는 것을 의미한다. SEI를 구현했으므로 주문 ID를 반환하는 processOrder 메서드 구현을 제공해야 한다.

우리는 SEI와 SEI의 구현체를 만들었다. 이제 CXF를 사용해 JAX-WS 프론트엔드를 사용하는 실제 서비스 컴포넌트를 만들 수 있다.


Listing 3. beans.xml 환경 구성 파일
                
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

 <import resource="classpath:META-INF/cxf/cxf.xml" />
 <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> 

 <jaxws:endpoint 
  id="orderProcess" 
  implementor="demo.order.OrderProcessImpl" 
  address="/OrderProcess" />
	  
</beans>

CXF의 환경 구성 파일 생성하기

CXF 환경 구성 파일은 실제로 빈 정의를 포함하는 스프링 환경 구성 파일이다. JAX-WS 프론트엔드 환경 구성을 사용해 OrderProcess웹 서비스에 대한 빈 정의를 만들자. beans.xml에 나오는 <jaxws:endpoint> 태그는 OrderProcess 웹 서비스를 JAX-WS 엔드포인트로 지정해준다. 이 웹 서비스를 공개(publish)하는 데 CXF가 내부적으로 JAX-WS를 사용하는 건 매우 효과적인 방법이다.<jaxws:endpoint>에 구현 클래스 이름인 OrderProcessImpl과 주소를 제공해야 한다. 여기서 제공하는 주소는 웹 컨텍스트(web context)와 관련 있다.


Listing 4. web.xml 환경 구성 파일
                
<web-app>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>WEB-INF/beans.xml</param-value>
 </context-param>

 <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>

 <servlet>
  <servlet-name>CXFServlet</servlet-name>
  <display-name>CXF Servlet</display-name>
  <servlet-class>
   org.apache.cxf.transport.servlet.CXFServlet
  </servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>CXFServlet</servlet-name>
  <url-pattern>/*</url-pattern>
 </servlet-mapping>
</web-app>

마지막으로 다음 작업을 해야 한다.

  • CXF 환경 구성 파일을 불러오는 web.xml 파일 만들기
  • 환경 구성 파일을 불러오는 스프링 컨텍스트 로더(context loader) 사용하기
  • 클라이언트 프로그램에서 오는 모든 요청을 제어하는 CXFServlet 등록하기

이제 서버측 컴포넌트가 필요로 하는 개발은 대충 마무리됐다. 이제 OrderProcess 서비스에 요청을 보내는 클라이언트 컴포넌트를 개발할 수 있다.

클라이언트 개발하기

Listing 5에서 봤던 것처럼, 서버 종단 지점을 쉽게 만들 수 있는 것처럼 클라이언트 빈을 만드는 것도 매우 쉽다. JaxWsProxyFactoryOrderProcess 웹 서비스에 대한 클라이언트 빈을 만드는데 사용된다. 팩토리 빈은 서비스 클래스(OrderProcess)와 서비스의 URL을 요구한다. 그러므로 클라이언트 빈 스텁(stub)이 되는 OrderProcess는 팩토리 빈 참조를 사용해 생성된다.


Listing 5. client-bean.xml 클라이언트 웹 환경 구성 파일
                
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws 
http://cxf.apache.org/schema/jaxws.xsd">

 <bean id="client" class="demo.order.OrderProcess" 
  factory-bean="clientFactory" factory-method="create"/>
	
 <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
  <property name="serviceClass" value="demo.order.OrderProcess"/>
  <property name="address" value="http://localhost:8080/orderapp/OrderProcess"/>
 </bean>
	  
</beans>

스프링 컨텍스트(context)를 사용해 정의한 클라이언트 빈을 받아온 다음, processOrder 메서드를 호출하는 자바 메인 프로그램을 만들어보자.


Listing 6. 클라이언트 코드
                
public final class Client {

 public Client() {
 }

 public static void main(String args[]) throws Exception {
  ClassPathXmlApplicationContext context 
   = new ClassPathXmlApplicationContext(new String[] 
     {"demo/order/client/client-beans.xml"});

  OrderProcess client = (OrderProcess)context.getBean("client");
    Order order = new Order();

  String orderID = client.processOrder(order);
  System.out.println("Order ID: " + orderID);
  System.exit(0);
 }
}

프로그램 실행하기

프로그램을 실행하기 전에, 루트 C:\ 폴더 밑에 그림 1에서 보는 것처럼 디렉터리 구조를 만들고, 이번 글의 앞에서 다뤘던 컴포넌트를 넣어두자.

  • 자바 코드는 패키지 폴더에 포함
  • beans.xml과 web.xml은 web\web-inf 폴더에 포함
  • client-beans.xml은 demo\order\client 폴더에 포함

그림 1. 코드 디렉터리 구조
코드 디렉터리 구조 

OrderProcess 웹 서비스와 클라이언트를 구축하고, 배포하고, 실행하는 데 앤트(Ant) 도구를 사용한다. 코드는 톰캣 서버에 배포된다. c:\orderapp 폴더 아래 ant deploy 커맨드를 사용해 코드를 배포하자.

애플리케이션 폴더(c:\orderapp)는 앤트 빌드 파일을 갖고 있다. 위 명령을 실행한 후에 orderapp 코드는 orderapp.war 파일로 톰캣 서버 환경에 배포된다. 이제 CATALINA_HOME\bin 폴더에서 catalina start 명령을 입력해 톰캣 웹 서버를 시작하자.

톰캣의 webapps 폴더에 orderapp 폴더가 생성된다. 서버가 시작된 후에 ant client 명령을 입력해 애플리케이션을 시작하자. 주문 ID가 화면에 출력된다(그림 2).


그림 2. 프로그램이 출력한 화면
프로그램이 출력한 화면 

결론

이번 글에서는 간단한 CXF 프레임워크의 특징과 코드를 작성해야 하는 별다른 노력 없이도 웹 서비스를 만들 수 있는 방법을 설명했다. 빈 컨텍스트 파일을 사용하는 CXF와 스프링 통합에 대해서도 배웠다. 또한 프레임워크가 실제로 웹 서비스 인프라스트럭처 컴포넌트를 만드는 의미를 추상화한 방법과, 오로지 웹 서비스를 생성하는 데만 집중할 수 있도록 어떤 전문적이면서 간편한 셸 API를 제공하는지를 알아 봤다

이제 CXF를 사용하는 웹 서비스 생성의 기본을 살펴봤으니, Part 2에서는 CXF와 스프링을 사용해 RESTful 서비스를 POJO로 노출하는 방법을 살펴볼 생각이다.


신고
Posted by Tornado tornado
기본 문서를 읽지 않으므로 인해 이런 기초적인 문제에서 난관에 봉착함.




 <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
     <property name="mappings">
         <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
             <property name="locations">
              <list>
               <value>classpath:config/spring/web/xxx.properties</value>
               <value>classpath:config/spring/web/yyy.properties</value>
              </list>              
             </property>
         </bean>
     </property>
 </bean>
신고
Posted by Tornado tornado

[link] http://openframework.or.kr/framework_reference/spring-security/1.x/html/index.html


Acegi Security

참조 가이드

Ben Alex

1.0.5


차례

시작하는 말
I. 전체적인 아키텍처
1. 소개
1.1. Acegi Security란 무엇인가?
1.2. Acegi Security의 내력
1.3. 릴리즈 번호 부여 체계
2. 기술적 개요
2.1. 런타임 환경
2.2. 공유 컴포넌트(Shared Components)
2.3. 인증(Authentication)
2.4. 안전 객체(Secure Objects)
2.5. 결론
3. 보조 인프라스트럭처
3.1. 지역화(Localization)
3.2. 필터
4. 채널 보안
4.1. 개요
4.2. 설정
4.3. 결론
5. 태그 라이브러리(Tag Libraries)
5.1. 개요
5.2. 설정
5.3. 사용법
II. 인증(Authentication)
6. 공통적인 인증 서비스
6.1. 메커니즘, 제공자(Providers), 진입점(Entry Points)
6.2. UserDetails와 연관 타입
인 메모리(In-Memory) 인증
JDBC 인증
6.3. 동시 세션 처리
6.4. 인증 태그 라이브러리
7. DAO 인증 제공자
7.1. 개요
7.2. 설정
8. JAAS(Java 인증 및 권한부여 서비스) 제공자
8.1. 개요
8.2. 설정
JAAS CallbackHandler
JAAS AuthorityGranter
9. Siteminder 인증 메커니즘
9.1. 개요
9.2. 설정
10. Run-As 인증 대체
10.1. 개요
10.2. 설정
11. 폼 인증 메커니즘
11.1. 개요
11.2. 설정
12. BASIC 인증 메커니즘
12.1. 개요
12.2. 설정
13. 다이제스트(Digest) 인증
13.1. 개요
13.2. 설정
14. 익명 인증
14.1. 개요
14.2. 설정
15. Remember-Me 인증
15.1. 개요
15.2. 설정
16. X509 인증
16.1. 개요
16.2. Acegi Security로 X509 사용하기
16.3. 설정
17. LDAP 인증
17.1. 개요
17.2. Acegi Security로 LDAP 사용하기
LdapAuthenticator 구현체
LDAP 서버에 연결하기
LDAP 검색 객체(LDAP Search Objects)
17.3. 설정
18. CAS 인증
18.1. 개요
18.2. CAS 작동 방식
18.3. 선택적 CAS 서버 설치
CAS 2.0 버전
CAS 3.0 버전
18.4. CAS 클라이언트 설정
18.5. 고급 이슈
19. 컨테이너 어댑터 인증
19.1. 개요
19.2. 어댑터 인증 제공자
19.3. Jetty
19.4. JBoss
19.5. Resin
19.6. Tomcat
III. 권한 부여(Authorization)
20. 공통적인 권한부여 개념
20.1. 권한부여(Authorities)
20.2. 호출전(Pre-Invocation) 처리
20.3. 호출후 처리(After-Invocation Handling)
ACL-Aware AfterInvocationProviders
ACL-Aware AfterInvocationProviders (기존 ACL 모듈)
20.4. 권한 부여 태그 라이브러리
21. Secure Object 구현
21.1. AOP 연합(MethodInvocation) 보안 인터셉터
21.2. AspectJ (JoinPoint) 보안 인터셉터
21.3. FilterInvocation 보안 인터셉터
22. 도메인 객체 보안
22.1. 개요
22.2. 주요 개념
23. 기존 ACL 모듈의 도메인 객체 보안
23.1. 개요
23.2. Basic ACL 패키지
IV. 기타 리소스
24. 예제 애플리케이션
24.1. 연락처 예제
24.2. 튜토리얼 예제
25. 커뮤니티 지원
25.1. 이슈 트랙킹을 위한 JIRA 사용
25.2. 참여하기
25.3. 더 자세한 정보
신고
Posted by Tornado tornado

URL ==> http://urlrewritefilter.googlecode.com/svn/trunk/src/doc/manual/3.2/index.html

아파치의 MOD_REWRITE 모듈과 똑같은 동작을 하는 URL Rewriter Filter 입니다~

Manual

Community support is available at urlrewrite google group.

Read examples of usage and a sample of the ant task report. If you have feedback, or conf you want to share with the world email me. If you have any suggestions/examples for this manual please post them to the group.

Install

  1. Download the zip (or tar.gz) and extract it into your context's directory ie, so that urlrewrite.xml goes into the WEB-INF directory.
  2. Add the following to your WEB-INF/web.xml (add it near the top above your servlet mappings (if you have any)): (see filter parameters for more options)
    
        <filter>
            <filter-name>UrlRewriteFilter</filter-name>
            <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>UrlRewriteFilter</filter-name>
            <url-pattern>/*</url-pattern>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>FORWARD</dispatcher>
        </filter-mapping>
            
  3. Add your own configuration to the WEB-INF/urlrewrite.xml that was created.
  4. Restart the context.

You can visit http://127.0.0.1:8080/rewrite-status (or whatever the address of your local webapp and context) to see output (note: this page is only viewable from localhost).

Filter Parameters

There are a few advanced filter parameters for enabling conf file reloading etc. There are self-explanatory.


    <filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>

        <!-- set the amount of seconds the conf file will be checked for reload
        can be a valid integer (0 denotes check every time,
        -1 denotes no reload check, default -1) -->
        <init-param>
            <param-name>confReloadCheckInterval</param-name>
            <param-value>60</param-value>
        </init-param>

        <!-- if you need to the conf file path can be changed
        it is specified as a path relative to the root of your context
        (default /WEB-INF/urlrewrite.xml) -->
        <init-param>
            <param-name>confPath</param-name>
            <param-value>/WEB-INF/urlrewrite.xml</param-value>
        </init-param>

        <!-- sets up log level (will be logged to context log)
        can be: TRACE, DEBUG, INFO (default), WARN, ERROR, FATAL, log4j, commons, slf4j,
        sysout:{level} (ie, sysout:DEBUG)
        if you are having trouble using normal levels use sysout:DEBUG
        (default WARN) -->
        <init-param>
            <param-name>logLevel</param-name>
            <param-value>DEBUG</param-value>
        </init-param>

        <!-- you can change status path so that it does not
        conflict with your installed apps (note, defaults
        to /rewrite-status) note, must start with / -->
        <init-param>
            <param-name>statusPath</param-name>
            <param-value>/status</param-value>
        </init-param>

        <!-- you can disable status page if desired
        can be: true, false (default true) -->
        <init-param>
            <param-name>statusEnabled</param-name>
            <param-value>true</param-value>
        </init-param>

        <!-- you may want to allow more hosts to look at the status page
        statusEnabledOnHosts is a comma delimited list of hosts, * can
        be used as a wildcard (defaults to "localhost, local, 127.0.0.1") -->
        <init-param>
            <param-name>statusEnabledOnHosts</param-name>
            <param-value>localhost, dev.*.myco.com, *.uat.mycom.com</param-value>
        </init-param>

        <!-- you may want to allow more hosts to look at the status page
        statusEnabledOnHosts is a comma delimited list of hosts, * can
        be used as a wildcard (defaults to "localhost, local, 127.0.0.1") -->
        <init-param>
            <param-name>statusEnabledOnHosts</param-name>
            <param-value>localhost, dev.*.myco.com, *.uat.mycom.com</param-value>
        </init-param>

        <!-- defaults to false. use mod_rewrite style configuration file (if this is true and confPath
        is not specified confPath will be set to /WEB-INF/.htaccess) -->
        <init-param>
            <param-name>modRewriteConf</param-name>
            <param-value>false</param-value>
        </init-param>

        <!-- load mod_rewrite style configuration from this parameter's value.
                note, Setting this parameter will mean that all other conf parameters are ignored.
            <init-param>
                <param-name>modRewriteConfText</param-name>
                <param-value>
                    RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R]
                    RewriteRule ^/([uge])/([^/]+)$ /$1/$2/ [R]
                </param-value>
            </init-param>
        -->

        <!-- defaults to false. allow conf file to be set by calling /rewrite-status/?conf=/WEB-INF/urlrewrite2.xml
                designed to be used for testing only
            <init-param>
                <param-name>allowConfSwapViaHttp</param-name>
                <param-value>false</param-value>
            </init-param>
        -->

    </filter>

    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

Note, setting logLevel to log4j or commons will cause the built in loging to call either log4j or commons-logging as if they were the logging framework, obviously you will need to have the jar for log4j or commons-logging in your classpath.

Configuration File WEB-INF/urlrewrite.xml

<urlrewrite>   <rule>   <outbound-rule>   <class-rule>
<name>   <note>   <condition>   <from>   <to>   <set>   <run>  
Back References   Variables   Functions  

Configuration is done via a simple XML file that lives in your WEB-INF folder. It should be named urlrewrite.xml. It may be helpful to read the UrlRewriteFilter DTD (Document Type Definition). Please also make sure you look at the examples. A simple configuration file looks like:


    <?xml version="1.0" encoding="utf-8"?>

    <!DOCTYPE urlrewrite
        PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
        "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">

    <urlrewrite>

        <rule>
           <from>^/some/olddir/(.*)$</from>
           <to type="redirect">/very/newdir/$1</to>
        </rule>

        <rule match-type="wildcard">
           <from>/blog/archive/**</from>
           <to type="redirect">/roller/history/$1</to>
        </rule>

    </urlrewrite>

The urlrewrite.xml file must have a root element called "urlrewrite" and must contain at least one "rule" element.

A "rule" must contain a "from" and a "to", and can have zero or more "condition" elements and zero or more and/or "set" elements.

When a "rule" is processed against an incoming request, all the "condition" elements must be met, then the "from" will be applied to the request URL and the final URL generated by applying the "to" to the "from" pattern. So long as the rule has matched then the "set" will be run.

When executing a rule the filter will (very simplified) loop over all rules and for each do something like this psuedo code:


    Pattern.compile(<from> element);
    pattern.matcher(request url);
    matcher.replaceAll(<to> element);
    if ( <condition> elements match && matcher.find() ) {
        handle <set> elements (if any)
        execute <run> elements (if any)
        perform <to> element (if any)
    }

<urlrewrite> element

The top level element.

Attribute Possible Value Explanation
default-match-type
(optional)
regex (default) All rules and thier conditions will be processed using the Java Regular Expression engine (unless match-type is specified on a rule).
wildcard All rules and thier conditions will be processed using the Wildcard Expression engine (unless match-type is specified on a rule).
decode-using
(optional)
header,utf8 (default) When URL is decoded request.getCharacterEncoding() will be used, if that is empty UTF-8 will be used.
null Do not decode at all. (note, this means the literal string null e.g. decode-using="null")
header Only use request.getCharacterEncoding() to decode.
[encoding] Only use a specific character encoding eg, ISO-8859-1. See Java Charset Object for all character encodings.
header,[encoding] When URL is decoded request.getCharacterEncoding() will be used, if that is empty a specific character encoding eg, ISO-8859-1. See Java Charset Object for all character encodings.
use-query-string
(optional)
false (default) The query string will not be appended to the url that the "from" element matches against.
true The query string will be appended to the url that the "from" element matches against.
use-context
(optional)
false (default) The context path will not be added to the url that the "from" element matches against.
true The context path will be added to the url that the "from" element matches against.

<rule> element

Zero or more. The basis of a rule.

Attribute Possible Value Explanation
enabled
(optional)
true (default) Enable this rule.
false Disable this rule.
match-type
(optional)
regex (default) This rule and it's conditions will be processed using the Java Regular Expression engine.
wildcard This rule and it's conditions will be processed using the Wildcard Expression engine.

In the following example requests for /world/usa/nyc will be transparently forwarded to /world.jsp


    <rule match-type="regex">
       <from>^/world/([a-z]+)/([a-z]+)$</from>
       <to>/world.jsp</to>
    </rule>

    <rule match-type="wildcard">
       <from>/world/*/*</from>
       <to>/world.jsp</to>
    </rule>

<outbound-rule> element

Zero or more. This is very similar to a normal rule but it is used for rewriting urls that go through response.encodeURL().

Attribute Possible Value Explanation
enabled
(optional)
true (default) Enable this rule.
false Disable this rule.
encodefirst
(optional)
false (default) Run encodeURL() after running this outbound rule.
true Run encodeURL() before running this outbound rule.

May contain "run", "from", "to" and "set" element(s) also. Example:


    <outbound-rule>
        <from>^/world.jsp?country=([a-z]+)&amp;city=([a-z]+)$</from>
        <to>/world/$1/$2</to>
    </outbound-rule>

Using the example above JSP's with the code
<a href="<%= response.encodeURL("/world.jsp?country=usa&amp;city=nyc") %>">nyc</a>
will output
<a href="/world/usa/nyc">nyc</a>

Or JSTL
<a href="<c:url value="/world.jsp?country=${country}&amp;city=${city}" />">nyc</a>
will output
<a href="/world/usa/nyc">nyc</a>

Note, If you are using JSTL (ie, <c:url) this will work also.

<name> element

An optional element used for documenting the name of the rule. This can be used with rule and outbound-rule. See ant task.


    <rule>
        <name>World Rule</name>
        <from>^/world/([a-z]+)/([a-z]+)$</from>
        <to>/world.jsp?country=$1&amp;city=$2</to>
    </rule>

<note> element

A simple optional element used for documentation of the rule. This can be used with rule and outbound-rule. See ant task.


    <rule>
        <name>World Rule</name>
        <note>
            Cleanly redirect world requests to JSP,
            a country and city must be specified.
        </note>
        <from>^/world/([a-z]+)/([a-z]+)$</from>
        <to>/world.jsp</to>
    </rule>

<condition> element

An element that lets you choose condtions for the rule. Note, all conditions must be met for the rule to be run (unless "next" is set to "or" obvoiusly).

Value can be any Regular Expression.

Attribute Possible Value Explanation
type
(optional)
header (default) If used, the header name must be specified in the "name" attribute.
method The method of the request. GET, POST, HEAD etc.
port The port that the web application server is running on.
time Current time at the server (this will be the number of seconds since 00:00:00 1970-01-01 UTC otherwise known as unix time).
i.e. (new Date()).getTime()
This can be used for making sure content goes live only at a time you set.
year Current year at the server.
i.e. (Calendar.getInstance()).get(Calendar.YEAR)
month Month at the server. January is 0
i.e. (Calendar.getInstance()).get(Calendar.MONTH)
dayofmonth Day of the month at the server. March first is 1
i.e. (Calendar.getInstance()).get(Calendar.DAY_OF_MONTH)
dayofweek Day of the week at the server. Saturday is 1, Sunday is 7
i.e. (Calendar.getInstance()).get(Calendar.DAY_OF_WEEK)
ampm AM or PM time at the server.
i.e. (Calendar.getInstance()).get(Calendar.AM_PM)
hourofday The hour of the day (24 hour clock) at the server. 10pm is 22
i.e. (Calendar.getInstance()).get(Calendar.HOUR_OF_DAY)
minute The minute field of the current time at the server.
i.e. (Calendar.getInstance()).get(Calendar.MINUTE)
second The second field of the current time at the server.
i.e. (Calendar.getInstance()).get(Calendar.SECOND)
millisecond The millisecond field of the current time at the server.
i.e. (Calendar.getInstance()).get(Calendar.MILLISECOND)
attribute Will check the value of a request attribute (don't confuse this with parameter!), name must be set when using this type.
i.e. request.getAttribute([name])
auth-type Will check the value of a request attribute (don't confuse this with parameter!)
i.e. request.getAuthType()
character-encoding The character encoding of the imcoming request.
i.e. request.getCharacterEncoding()
content-length The length of the imcoming request (can be useful if you want to deny large requests).
i.e. request.getContentLength()
content-type The type of the imcoming request. (this is probably not that useful)
i.e. request.getContentType()
context-path The context path of the imcoming request.
i.e. request.getContextPath()
cookie The value of a cookie, note, name must be specified to use this
i.e. request.getCookies() the find we the one with [name] specified and check the value.
parameter A tidier way of checking request parameters than looking for them in the query string. This will check for the parameter in GET or POST, note, name must be specified.
i.e. request.getParameter([name])
path-info i.e. request.getPathInfo()
path-translated i.e. request.getPathTranslated()
protocol The protocol used to make the request, e.g. HTTP/1.1
i.e. request.getProtocol()
query-string The query string used to make the request (if any), e.g. id=2345&name=bob
i.e. request.getQueryString()
remote-addr The IP address of the host making the request, e.g. 123.123.123.12
i.e. request.getRemoteAddr()
remote-host The host name of the host making the request, e.g. 123qw-dsl.att.com (note, this will only work if your app server is configured to lookup host names, most aren't).
i.e. request.getRemoteHost()
remote-user The login of the user making this request, if the user has been authenticated, e.g. bobt
i.e. request.getRemoteUser()
requested-session-id Returns the session ID specified by the client, e.g. 2344asd234sada4
i.e. request.getRequestedSessionId()
requested-session-id-from-cookie Whether the requested session ID is from a cookie or not
i.e. request.isRequestedSessionIdFromCookie()
requested-session-id-from-url Whether the requested session ID is from the URL or not
i.e. request.isRequestedSessionIdFromURL()
requested-session-id-valid Whether the requested session ID is valid or not
i.e. request.isRequestedSessionIdValid()
request-uri Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request
i.e. request.getRequestURI()
request-url Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and server path, but it does not include query string parameters.
i.e. request.getRequestURL()
session-attribute (note, name must be set)
i.e. session.getAttribute([name])
session-isnew Weather the session is new or not.
i.e. session.isNew()
server-name The host name of the server to which the request was sent (from the host header not the machine name).
i.e. request.getServerName()
scheme The scheme used for the request, e.g. http or https
i.e. request.getScheme()
user-in-role (Note, the value for this cannot be a regular expression)
i.e. request.isUserInRole([value])
name
(optional)
(can be anything) If type is header, this specifies the name of the HTTP header used to run the value against.
next
(optional)
and (default) The next "rule" and this "rule" must match.
or The next "rule" or this "condition" may match.
operator
(optional)
equal (default) Equals. The operator to be used when the condition is run, the regular expression matches or the values are equal.
notequal Not equal to. (i.e. request value != condition value). Note, this operator only work with numeric rule types.
greater Greater than. (i.e. request value > condition value). Note, this operator only work with numeric rule types.
less Less than. (i.e. request value < condition value). Note, this operator only work with numeric rule types.
greaterorequal Greater to or equal to. (i.e. request value >= condition value). Note, this operator only work with numeric rule types.
lessorequal Less than or equal to. (i.e. request value <= condition value). Note, this operator only work with numeric rule types.

Examples:


    <condition name="user-agent" operator="notequal">Mozilla/[1-4]</condition>

    <condition type="user-in-role" operator="notequal">bigboss</condition>

    <condition name="host" operator="notequal">www.example.com</condition>

    <condition type="method" next="or">PROPFIND</condition>
    <condition type="method">PUT</condition>

<from> element

You must always have exactly one from for each rule or outbound-rule. Value can be a regular expression in the Perl5 style. Note, from url's are relative to the context.

Attribute Possible Value Explanation
casesensitive
(optional)
false (default) This value will be matched using case insentitive match. ie, "/WellingtoN" will match "/wellington".
true This value will be matched using case sentitive match. ie, "/aAa" will NOT match "/aaa".

Example:


    <from>^/world/([a-z]+)$</from>

<to> element

Value can be a regular replacement expression in the Perl5 style.

Attribute Possible Value Explanation
type
(optional)
forward (default) Requests matching the "conditions" for this "rule", and the URL in the "from" element will be internally forwarded to the URL specified in the "to" element. Note: In this case the "to" URL must be in the same context as UrlRewriteFilter. This is the same as doing:
RequestDispatcher rq = request.getRequestDispatcher([to value]);
rq.forward(request, response);
passthrough Identical to "forward".
redirect Requests matching the "conditions" and the "from" for this rule will be HTTP redirected. This is the same a doing:
HttpServletResponse.sendRedirect([to value]))
permanent-redirect The same as doing:
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", [to value]);

(note, SC_MOVED_PERMANENTLY is HTTP status code 301)
temporary-redirect The same as doing:
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
response.setHeader("Location", [to value]);

(note, SC_MOVED_TEMPORARILY is HTTP status code 302)
pre-include
post-include
proxy The request will be proxied to the full url specified. commons-http and commons-codec must both be in the classpath to use this feature.
last
(optional)
false (default) The rest of the "rules" will be processed if this one succeeds.
true No more "rules" will be processed if this one is a match.
encode
(optional)
false (default if under rule) response.encodeURL([to]) will be run on the to url before performing the rewrite.
true (default if under outbound-rule) response.encodeURL([to]) will NOT be called.
context
(optional)
If your application server is configured to allow "cross context" communication then this attribute can be used to forward (and only forward, not redirect or other "to" types) requests to a named servlet context.

On Tomcat, for instance, the application contexts in the server configuration (server.xml or context.xml) need the option crossContext="true". For instance, the two applications mentioned before ("app" and "forum") have to be defined as:

<Context docBase="app" path="/app" reloadable="true" crossContext="true"/>
<Context docBase="forum" path="/forum" reloadable="true" crossContext="true"/>

Note, "to" can be null ie, <to>null</to>, this will mean that the request will go no further if the rule is matched (ie, this filter will not call chain.doFilter).

If "to" is set to -, no substitution will take place and the request will go on like nothing happened (ie, this filter will call chain.doFilter).


    <to>/world.jsp?country=$1</to>

To elements can contain backreferences and variables.

Backreferences


    %N

Provides access to the grouped parts (parentheses) of the pattern from the last matched Condition in the current rule. N must be less than 10 and greater than 0 (i.e. %1, %2, %3 etc).

Variables


    %{VARIABLE-NAME}

Any valid condition type can be used as a variable name. ie, '%{port}' will be translated to '80', '%{year}' to '2005', '%{cookie:myCookie}' would be translated to 'myCookieValue' (assuming the user had a cookie named myCookie with the value myCookieValue).

Valid types are condition types, see condition for a full description.

Functions


    ${FUNCTION:PARAMS}

Functions can be places in set and to elements.

name example example returns
replace ${replace:my cat is a blue cat:cat:dog} my dog is a blue dog
replaceFirst ${replaceFirst:my cat is a blue cat:cat:dog} my cat is a blue dog
escape ${escape:a b c} a+b+c
unescape ${unescape:a+b+c} a b c
lower ${lower:Hello World} hello world
upper ${upper:hello} HELLO
trim ${trim: abc def } abc def

<set> element

Allows you to set varous things if the rule is matched.

Attribute Possible Value Explanation
type
(optional)
request (default) The same as request.setAttribute([name], [value]) (note, name must be set).
session The same as request.getSesison(true).setAttribute([name], [value]) (note, name must be set).
response-header The same as response.setHeader([name], [value]) (note, name must be set).
cookie Value can be in the format "[value][:domain[:lifetime[:path]]]". This sets a cookie on the client's browser. The cookie's name is specified by the name attribute. The domain field is the domain of the cookie, such as '.apache.org',the optional lifetime is the lifetime of the cookie in seconds, and the optional path is the path of the cookie (note, name must be set).
status The same as response.setStatus([value])
content-type The same as response.setContentType([value])
charset The same as response.setCharacterEncoding([value])
expires Will set the Expires HTTP header by adding the time specified and current time (this is mod_expires style). Syntax "{num type}*". Units can be (singular or plural); years, months, weeks, days, hours, minutes, seconds.
eg, "1 day 2 seconds", "3 hours", "1 year 1 hour"
locale The same as response.setLocale([value]) specify the Locale in the format (valid locales are, zh, zh-CN, zh-CN-southern i.e. "-" separating the language, country and variant (if any)).
parameter Enables you to override a request.getParameter(String) wuth a custom value
method Enables you to override request.getMethod() with a custom value
name
(optional)
(can be anything) If type is request, session, response-header, cookie this specifies the name item.

In the following example a request attribute "client" will be set to "AvantGo" or "Samsung SCH-6100", this can be fetched in a servlet or JSP using request.getAttribute("client").


    <rule>
        <condition name="user-agent">Mozilla/3\.0 (compatible; AvantGo .*)</from>
        <from>.*</from>
        <set name="client">AvantGo</set>
    </rule>
    <rule>
        <condition name="user-agent">UP\.Browser/3.*SC03 .* </from>
        <from>.*</from>
        <set name="client">Samsung SCH-6100</set>
    </rule>

It is also possible to use regular replacement expressions as part of the value similar to their usage in <to> elements:


    <rule>
        <from>/products/(.*)/(.*)/index.html</from>
        <set name="urlrewrite.product.slug">$1</set>
        <set name="urlrewrite.product.id">$2</set>
        <to>/products?slug=$1&id=$2</to>
    </rule>

<run> element

Allows you to run a method on an object when a rule and it's conditions are matched.

Attribute Possible value Explanation
class The class you want to run a method on. Must be a fully qualified name.
method (optional) run (default) The method you want to run, the method must have the parameters (HttpServletRequest, HttpServletResponse) e.g. run(HttpServletRequest request, HttpServletResponse response)
Note, if init(ServletConfig) or destroy() is found they will be run at when creating or destroying an instance.
neweachtime (optional) false (default) One instance for each UrlRewriteFilter instance.
true A new instance of the class will be created before running each time set to true.

When the rule in the following example is matched, WorldServlet.goGet(HttpServletRequest, HttpServletResponse) will be invoked, the request will then be forwarded to /world-presentation.jsp.


    <rule>
        <from>^/world/[a-z]+/[a-z]+$</from>
        <run class="com.blah.web.WorldServlet" method="doGet" />
        <to>/world-presentation.jsp</to>
    </rule>

Note, you can specify init-param's the same way you would for a servlet.


    <run class="com.blah.web.MyServlet" method="doGet">
        <init-param>
            <param-name>someParamName</param-name>
            <param-value>10</param-value>
        </init-param>
    </run>

If the method being called throws an Exception the original exception will be re-thrown as if it were the original if it extends RuntimeException (eg, NullPointer), other exceptions are wrapped in a ServletException and thrown so your container can handle them.

<class-rule> element

Allows you to run a method every time a request come in for 100% dynamic rules. See the org.tuckey.web.filters.urlrewrite.sample package for an example.

Attribute Explanation
class The class you want to run a method on. Must be a fully qualified name.
method (optional, default matches) The method you want to run, the method must have the parameters (HttpServletRequest, HttpServletResponse) e.g. run(HttpServletRequest request, HttpServletResponse response)
Note, if init(ServletConfig) or destroy() is found they will be run at when creating or destroying an instance.
last (optional, default true If false more rules will be processed following this rule even if it is matched (so that a better match may be found).

Example:


    <class-rule class="com.blah.web.MyRuleClass" />

Tips

  • When you want to put an "&" in a rule you must enter it as the XML entity "&amp;"
  • For simplicity you might want to start all from's with a ^ and end them with a $.
    In regular expressions ^ specifies the start of the string and $ specifies the end.
    ie, a request for /my/url/path will NOT match <from>^/url/$</from> but it will match <from>/url/</from>
  • If using <outbound-rule> remember all urls in your code must be encoded e.g. <a href="<%= response.encodeURL("/some/olddir/b.jsp") %>">my link</a>
  • Regular expressions are complex and a bit tricky at times, read regular expression syntax for Java.
  • If you find regular expressions difficult use Wildcards.
  • "Context" is important. If you have an app with the context "/myapp" and you request the url "/myapp/somefolder/somepage.jsp", the container tells UrlRewriteFilter that the url is "/somefolder/somepage.jsp". This can be confusing, but basically your rules and conditions should not contain the context path (it will be handled by the container).

Wildcard Matching Engine

The wildcard matching engine can be used instead of regex. It is supported in conditions and rules where match-type is set to wildcard (or default-match-type is set on the urlrewrite element

e.g. /big/url/* will match /big/url/abc.html but will NOT match /big/url/abc/dir/ or /big/url/abc/.

/big/url/** will match /big/url/abc.html, /big/url/abc/dir/ and /big/url/abc/.

You can also use Regular expression style variable replacement, each match of a * will be available for use in to and set elements using simple $1 $2 variables.

e.g. /my/big/url/* will match /my/big/url/abc.html and $1 will be set to abc.html.

Added in 3.0

Ant Task

An Ant task has been written to allow validate the conf file and generation of documentation. You can view a sample.

Paste the following into your build.xml file, then change the dest and conf to point to the correct places. Note, the urlrewrite jar file will need to be in your classpath.


    <target name="urlrewrite-doc" depends="compile"
        description="UrlRewriteFilter validation and documenting">

    <taskdef name="urlrewritedoc" classpath="lib/urlrewrite-3.2.0.jar"
        classname="org.tuckey.web.filters.urlrewrite.UrlRewriteDocTask" />
    <urlrewritedoc
        conf="${build.home}/WEB-INF/urlrewrite.xml"
        dest="urlrewrite-conf-overview.html" />
    </target>

mod_rewrite Style Configuration

Sample web.xml snippet:


     <filter>
         <filter-name>UrlRewriteFilter</filter-name>
         <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>

         <!-- defaults to false. use mod_rewrite style configuration file (if this is true and confPath
         is not specified confPath will be set to /WEB-INF/.htaccess) -->
         <init-param>
             <param-name>modRewriteConfText</param-name>
             <param-value><![CDATA[

                 # redirect mozilla to another area
                 RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
                 RewriteRule  ^/no-moz-here$                 /homepage.max.html  [L]

             ]]></param-value>
         </init-param>

     </filter>

     <filter-mapping>
         <filter-name>UrlRewriteFilter</filter-name>
         <url-pattern>/*</url-pattern>
         <dispatcher>REQUEST</dispatcher>
         <dispatcher>FORWARD</dispatcher>
     </filter-mapping>

OR alternately set modRewriteConf to true in filter parameters and add a WEB-INF/.htaccess file with your mod_rewrite style configuration in it.


    <filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>

        <!-- defaults to false. use mod_rewrite style configuration file (if this is true and confPath
        is not specified confPath will be set to /WEB-INF/.htaccess) -->
        <init-param>
            <param-name>modRewriteConf</param-name>
            <param-value>true</param-value>
        </init-param>

    </filter>

    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

Sample: WEB-INF/.htaccess


     # redirect mozilla to another area
     RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
     RewriteRule  ^/no-moz-here$                 /homepage.max.html  [L]
 

Documentation for the original mod_rewrite library mostly applies, differences are documented below.

Attribute Explanation
RewriteLogLevel Specified as int, trasnlated as: <= 1 - FATAL, 2 - ERROR, 3 - INFO, 4 - WARN, >= 5 DEBUG
RewriteLog SYSOUT, SYSERR, log4j, commons (if not set context logging will be used)
RewriteRule Supported but note: Certain flags not supported:
  • chain flag [C] not supported
  • env flag [E] not supported
  • next flag [N] not supported
  • nosubreq flag [NS] not supported
  • qsappend flag [QSA] not supported
  • Skip flag [S] not supported
RewriteBase Not supported
RewriteLock Not supported
RewriteMap Not supported
RewriteOptions Not supported
신고
Posted by Tornado tornado

빨간색 라인이 중요포인트..


 <target name="copy" depends="mkdir">
  <tstamp>
   <format property="build.time" pattern="yyyy-MM-dd HH:mm:ss" offset="-5" unit="minute" />
  </tstamp>

  <copy todir="${dist.class.dir}" includeEmptyDirs="false">
   <fileset dir="${dist.class.bin.dir}">
    <date datetime="${build.time}" when="after" pattern="yyyy-MM-dd HH:mm:ss" />
   </fileset>
  </copy>

 </target>

신고
Posted by Tornado tornado

[URL] http://www.techbrainwave.com/?p=973

신고
Posted by Tornado tornado
[link] http://java.decompiler.free.fr/

자바 디컴파일러.

GUI, Eclipse Plugin 을 제공.


신고
Posted by Tornado tornado
[link] http://ehcache.org/

자바로 만들어진 캐시 라이브러리, 

간단한 설정으로 캐시를 사용할 수 있음.

로깅시 slf4j 가 필요함. -->  http://www.slf4j.org/download.html 에서 받으면 된다.

참고로  ServletFilter ZipStream 도 있음. 

 

신고
Posted by Tornado tornado
대칭암호화알고리즘 소개 및 DES, Blowfish샘플코드
 
대칭암호화알고리즘이 무엇인지 간략히 소개하고, JCA-JCE및 간단한 두가지 알고리즘을 획득하여 암호화 하는 방법을 소개하고자 한다. ( 2003/06/23 ) 241
Written by ienvyou - 최지웅
1 of 1
 


오랫만이 쓰는 아티클인것 같다. 여기서는 우선 맛보기로 간단하게 암호화에 대한 내용 및
대칭암호방법에 대한 내용을 설명하도록 하겠다.

요즘 같이 인터넷이 보편화되고 개방형 시스템들이 존재하게 되면서 개인의 정보및
비밀에 대한 정보보호가 굉장한 이슈로 대두되어지고 있다.

우리가 사용하게 되는 자바는 java.security및 javax.crypto패키지를 통하여 암호를 쉽게
사용할 수 있는 기능을 제공한다. 
만약 당신이 어떠한 데이터를 다른 사람에게 전달하던 도중 그 메시지를 다른 사람이 보게
된다면? 그게 만약 신용카드나 결제정보, 중요한 문서일수도 있는 것이다.
그러한 것들에 대한 침입위험으로부터 정보가 보호되어지기 위해서는 무언가의 수단이
필요하게 될것이다. 자바측에서도 코드정책에 대한 보안이 필요하겠지만 우선은
기본적인 사항만을 여기서 논하겠다.

기본적인 자바의 코드보안정책으로서 final class라든지, 패키지보안, jar파일 sign, 
serialization부분의 transient등에 대한 설명은 여기서 논의하지 않도록 하겠다.

▶ 대칭암호화 알고리즘

기본적으로 이 글을 읽는 사람이라면 학교다닐때 한번쯤은 친한 친구와의 의사소통이나
대화를 하는데에 있어서 남들이 알지 못하는 방법으로 대화를 하고 싶었던 적이 있을것이다.
(놀새~만 그랬나?) 
가령 내가 고등학교를 다닐때 친구와 이야기를 할때 모든 단어를 표현하고자 할때
중성을 뒤로 빼서 그것을 이용하여 한글자를 더 만들고 거기에 ㅅ받침을 이용하여 의사소통을
한적도 있었다. (예: 비둘기 --> 비시 두술 기시) 처럼말이다..

위의 예를 든것도 일종의 암호화의 한 방법이라고 할 수 있는데 일반 사람들이 듣기에는
어떠한 논리에 의하여 말을 하는 것인지 처음에는 알아듣지를 못하다가 단어를 적어주거나
한참후에야 그러한 원리가 있었음을 알게 된다.

위와 같이 암호화와 같은 정보를 이용하여 다시 복호화 할수 있는 데 좀 더 쉽게 예를 들어보자면
다음과 같을 수 있다.


A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
|                               
D E F G H I J K L M N O P Q R S T U V W X Y Z A B C 

각각의 문자를 3자리씩 뒤로 옮겨진 것 처럼 보여질 수 있는데  만약 HI, CAROUSER라는 단어는
KL, FDURXVIU 라는 단어로 바뀌게 되면 같은 패턴에 의하여 다시 복호화 되어질수 있는 
특징을 가지고 있다.
즉 메시지를 암호화와 복호화를 하기 위해서는 알고리즘과 키가 정의되어야 한다.

▶ 대칭암호화 알고리즘의 종류
  1. DES & TripleDES : DES(Data Encryption Standard)는 "Lucifer"라는 이름의 IBM에서 최초개발되었다. 또한 미국에서 최초 국가표준이 되었으며, 56비트키를 가지고 암복호화를 사용했다. 하지만 컴퓨터가 발전을 함에 있어서 56비트키의 경우 어느정도의 시간만 확보가 된다면 풀어낼수 있기 때문에 좀더 완벽한 보안을 위하여 Triple DES가 고안되어졌다.
  2. TripleDES : 이는 기존의 DES암호화 알고리즘방식을 다른키에 세번 적용시킨것이며, 첫번째 암호화과정, 두번째 복호화과정, 세번째는 또 다른 암호화 과정을 거치도록 하고 있다. 그래서 이름이 DESede(DES encryption, decryption, encryption)이 되었으며, 각각의 과정에 따라 56비트의 배수로 암호화 복잡도가 증가되게 되어있다.
  3. Blowfish : 1993년 Bruce Schneier에 의해 고안된 블록암호로서 DES보다 빠르고 안전한 기법을 제공한다. 최대 키의 비트수를 448비트까지 확장할수있다는 특징을 가지고 있다.
  4. RC4 : "Civest's Code 4"를 의미하며 1987년 RSA Data Security에서 발표되었다. 보통 이기법으로 TCP/IP연결을 안전하게 하는 SSL을 구현하는 데 많이 쓰인다(키의 길이 40비트 또는 128비트)
위과 같이 대칭암호화의 경우는 모든 알고리즘이 같은 방식으로 동작을 하게 되는데 문제는 메시지를 보내고 받는 사람이 같은 키를 가지게 되며, 중간에 그 키가 노출이 되었을 땐 이미 우리의 메시지는 남에게 읽힐수 있는 문제점을 가지고 된다. 즉 비밀키가 노출되게 되면 암호화된 메시지또한 동시에 노출될 수 있다는 단점을 가지고 있다. ▶ DES방식의 샘플코드 우리는 여기서 간단하게 DES방식을 이용하여 암복호화 프로그램을 하나 예제로 보도록 한다. 기본적으로 자바측에서 제공할수 있는 암호에 관련된 패키지는 JCA(java cryptograhpy arch.)와 JCE(java cryptography extension)을 사용할 수 있다. JCA는 기본적으로 Java2 Runtime Environment의 일부이며, JCA는 그것의 확장패키지이다. 기본적인 JCA에서는 전자서명, 메시지 다이제스트, 키생성기등의 클래스를 가지고 있으며 그러한 기본적인 클래스들을 우리가 사용하고자 했을 때 new에 의한 생성이 아니라 이미 아키텍쳐가 가지고 있는 암호화 기법에 의하여 factory형태의 클래스에게 생성을 요청하여야 한다. 기본적인JCE같은 경우 당신이 JDK1.3.1을 사용한다면 패키지를 썬에서 다운로드 받을수있으며 jdk1.4버젼을 사용한다면 이미 포함되어져 있으니 그냥 코딩을 해도 무방할 듯 하다. 우선 아래의 코드를 보기 전에 중요한 클래스를 살펴보아야 할 필요가 있는데 그것은 바로 javax.crypto.Cipher라는 클래스로서 데이터를 암호화하고 복호화하는데 사용되는 기본적인 엔진부분이다. 몇가지의 메소드만을 살펴보겠는데 우선 getIntance(), init(), update(), doFinal()로서 암호화 알고리즘의 생성, Cipher인스턴스의 초기화, 암복호화, 암호화된 배열을 획득을 하는 메소드들이다. 또한 javax.crypto.KeyGenerator클래스는 암호화와 복호화에 필요한 키를 생성해내는 데 쓰이며 getInstance(), init(), generateKey()의 메소드 정도면 Cipher에 필요한 키를 만들어낼 수 있다.

import java.security.*;
import javax.crypto.*;

public class SimpleExample {
    public static void main(String [] args) throws Exception {
        if( args.length != 1) {
            System.out.println("Usage : java SimpleExample text ");
            System.exit(1);
        }
        String text = args[0];

        System.out.println("Generating a DESded (TripleDES) key...");

        // Triple DES 생성
        KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
        keyGenerator.init(168);	// 키의 크기를 168비트로 초기화
        Key key = keyGenerator.generateKey();

        System.out.println("키생성이 완료되었음");

        // Cipher를 생성, 사용할 키로 초기화
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);

        byte [] plainText = text.getBytes("UTF8");

        System.out.println("Plain Text : ");
        for (int i = 0; i < plainText.length ; i++)	{
            System.out.print(plainText[i] + " ");
        }

        // 암호화 시작
        byte [] cipherText = cipher.doFinal(plainText);

        // 암호문서 출력

        System.out.println("\nCipher Text : ");
        for (int i = 0; i < cipherText.length ; i++)	{
            System.out.print(cipherText[i] + " ");
        }

        //복호화 모드로서 다시 초기화
        cipher.init(Cipher.DECRYPT_MODE, key);

        //복호화 수행

        byte [] decryptedText = cipher.doFinal(cipherText);
        String output =  new String(decryptedText, "UTF8");
        System.out.println("\nDecrypted Text : " + output);
    }
};
위의 코드로서 간단하게 살펴볼 수 있는데, 출력되는 생성되는 키에 따라 결정되므로 매번 다른 결과의 암호화된 문자열을 볼 수 있는 특징을 가지고 있다. Blowfish의 대칭암호화 기법또한 같은 방법에 의하여 만들어낼 수 있는데 단순히 위의 코드상에서의 변화는 KeyGenerator에서 "Blowfish"와 Cipher에서 인스턴스를 얻어낼때 단순히 "Blowfish/ECB/PKCS5Padding"을 이용하여 처리하면 128비트의 키를 이용한 암복호화를 테스트해볼 수 있다. ▶ Conclusion 기본적으로 가장 기본적인 암호화 방법을 살펴보았으며 기본적인 대칭알고리즘의 개념이 무엇인지만 알고 있어도 놀새~가 여러분들을 보는 기준에서 별 무리가 없어 보일듯 하다. 다음에 쓸 것으로는 유닉스 패스워드의 형태로 많이 쓰이는 메시지 다이제스트방법을 간단한 자바코딩을 이용하여 처리해보겠다. 위의 경우 웹사이트를 직접 만들었을 경우 사용자들에 대한 user id, password를 데이터베이스에 직접저장하는 것이 아니라 universal key의 개념으로 변환하여 처리하는 샘플을 보도록 하겠다..

신고
Posted by Tornado tornado

출처 : http://www.laj.ca/projects/PrincipalAuthenticator/doc/uml/

 

 

Tomcat Authentication and Authorization Sequences

From the base Tomcat Authentication Sequence (using JAAS you can see the changes made by both JBoss and the IIS Connector. The important bit to note here is on the ISAPI Connector DLL Sequence. Due to the dll injecting a Principal into the request for Tomcat, all of Tomcat's regular authenticator valves fail to authorize the user. This is because, by default, they check to see if a Principal already exists in the session and return if it does.

The Tomcat IIS Authenticator Sequence shows how using the Tomcat IIS Authenticator Valve makes tomcat continue the authentication and authorization. Authentication is 'checked' by verifying that the NTLM provided Principal is not-null. Authorization is performed by passing the Principal to the Security Realm. The security realm can then populate the user's Principal with the Role's the user is granted base on the implementation of the Realm.

JBoss will now be able to use any LoginModule to populate the user's roles since it's security realm (registered in Tomcat) will now be called.

 

신고
Posted by Tornado tornado

출처 : http://www.bluestudios.co.uk/blog/?p=237


Recently I came across a small problem with setting up Oracle UCM 10gR3 on a MSSQL2005 instance.
Using the net.sourceforge.jtds.jdbc.Driver class.

The DBAs had setup a clustered SQL environment and had given me MSSQLDB0001\ARCHIVETR.
ARCHIVETR being the SQL instance which I needed to install the UCM to.

For future reference all you need to do is append ‘;instance=ARCHIVETR’ to the connection string like the following:

jdbc:jtds:sqlserver://<SQLServer>:<PORT>/<DBName>;instance=<SQLInstanceName>

Example:
jdbc:jtds:sqlserver://MSSQLDB0001:1433/UCM;instance=ARCHIVETR

신고
Posted by Tornado tornado
status.index가 핵심이군....
홀짝 구별하려면 status.odd 로 하면 될것 같음.




<s:iterator value="model.targetBranchList" status="status">
    <s:property value="branchName" />
    <s:if test="#status.index <= (model.targetBranchList.size() - 2)">,</s:if>
</s:iterator>
신고
Posted by Tornado tornado
출처 : http://www.ociweb.com/mark/programming/WAX.html

삽질 끝????

Introduction

What's the best way to read a large XML document? Of course you'd use a SAX parser or a pull parser. What's the best way to write a large XML document? Building a DOM structure to describe a large XML document won't work because it won't fit in memory. Even if it did, it's not a simple API to use. There hasn't been a solution that is simple and memory efficient until now.

Writing API for XML (WAX) is a free, open-source, library for writing XML documents. I created it because I got an OutOfMemoryError while trying to output a large XML document from an application I wrote using JDOM, another Java-based XML library. I searched for other libraries that could write large XML documents but couldn't find any that were as simple to use as I thought they should be.

WAX is released under the LGPL with the intention of making its use unencumbered. It is well-tested and ready for production use. The WAX home page is at http://www.ociweb.com/wax/. Java and Ruby versions are available now. The Java version of WAX can be downloaded from Google Code at http://code.google.com/p/waxy/. For information about the Ruby version, click here. Ports for other programming languages will follow.

WAX has the following characteristics:

  • focuses on writing XML, not reading it
  • requires less code than other approaches
  • uses less memory than other approaches
    (because it outputs XML as each method is called rather than
    storing it in a DOM-like structure and outputting it later)
  • doesn't depend on any Java classes other than standard JDK classes
  • is a small library (around 16K)
  • writes all XML node types
  • always outputs well-formed XML or throws an exception unless running in "trust me" mode
  • provides extensive error checking
  • automatically escapes special characters in text and attribute values (unless "unescaped" methods are used)
  • allows most error checking to be turned off for performance
  • knows how to associate DTDs, XML Schemas and XSLT stylesheets with the XML it outputs
  • is well-suited for writing XML request and response messages for REST-based and SOAP-based services

WAX Tutorial

This section provides many examples of using WAX. Each code snippet is followed by the output it produces.

When the no-arg WAX constructor is used, XML is written to standard output. There are also WAX constructors that take a java.io.OutputStream or a java.io.Writer object.

Here's a simple example where only a root element is written:

WAX wax = new WAX();
wax.start("car").close();
<car/>

After a WAX object is closed, a new one must be created in order to write more XML. In the examples that follow, assume that has been done.

Let's write a root element with some text inside:

wax.start("car").text("Prius").end().close();
<car>Prius</car>

The default indentation used is two spaces. The end method terminates the element that is started by the start method. In this case it's not necessary to call end because the close method terminates all unterminated elements.

Let's put the text inside a child element:

wax.start("car").start("model").text("Prius").close();
<car>
<model>Prius</model>
</car>

Let's do the same with the child convenience method: which is equivalent to calling start, text and end.

wax.start("car").child("model", "Prius").close();
<car>
<model>Prius</model>
</car>

Let's put text containing all the special XML characters in a CDATA section:

wax.start("car").start("model").cdata("1<2>3&4'5\";6").close();
<car>
<model>
<![CDATA[1<2>3&4'5"6]]>
</model>
</car>

Let's output the XML without indentation, on a single line:

wax.noIndentsOrLineSeparators();
wax.start("car").child("model", "Prius").close();
<car><model>Prius</model></car>

Let's indent the XML with four spaces instead of the default of two:

wax.setIndent("    "); // can also call setIndent(4)
wax.start("car").child("model", "Prius").close();
<car>
<model>Prius</model>
</car>

Let's add an attribute:

wax.start("car").attr("year", 2008).child("model", "Prius").close();
<car year="2008">
<model>Prius</model>
</car>

Attributes must be specified before any content for their element is specified. For example, calling start, attr and text is valid, but calling start, text and attr is not. If this rule is violated then an IllegalStateException is thrown.

Let's add an XML declaration:

WAX wax = new WAX(Version.V1_0); // Version is an enum
wax.start("car").attr("year", 2008)
.child("model", "Prius").close();
<?xml version="1.0" encoding="UTF-8"?>
<car year="2008">
<model>Prius</model>
</car>

Let's add a comment:

wax.comment("This is a hybrid car.")
.start("car").child("model", "Prius").close();
<!-- This is a hybrid car. -->
<car>
<model>Prius</model>
</car>

Let's add a processing instruction:

wax.processingInstruction("target", "data")
.start("car").attr("year", 2008)
.child("model", "Prius").close();
<?target data?>
<car year="2008">
<model>Prius</model>
</car>

Let's associate an XSLT stylesheet with the XML: The xslt method is a convenience method for adding this commonly used processing instruction.

wax.xslt("car.xslt")
.start("car").attr("year", 2008)
.child("model", "Prius").close();
<?xml-stylesheet type="text/xsl" href="car.xslt"?>
<car year="2008">
<model>Prius</model>
</car>

Let's associate a default namespace with the XML:

wax.start("car").attr("year", 2008)
.defaultNamespace("http://www.ociweb.com/cars")
.child("model", "Prius").close();
<car year="2008"
xmlns="http://www.ociweb.com/cars">
<model>Prius</model>
</car>

Let's associate a non-default namespace with the XML:

String prefix = "c";
wax.start(prefix, "car").attr("year", 2008)
.namespace(prefix, "http://www.ociweb.com/cars")
.child(prefix, "model", "Prius").close();
<c:car year="2008"
xmlns:c="http://www.ociweb.com/cars">
<c:model>Prius</c:model>
</c:car>

Like attributes, namespaces must be specified before any content for their element is specified. If this rule is violated then an IllegalStateException is thrown.

Let's associate an XML Schema with the XML:

wax.start("car").attr("year", 2008)
.defaultNamespace("http://www.ociweb.com/cars", "car.xsd")
.child("model", "Prius").close();
<car year="2008"
xmlns="http://www.ociweb.com/cars"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xsi:schemaLocation="http://www.ociweb.com/cars car.xsd">
<model>Prius</model>
</car>

Let's associate multiple XML Schemas with the XML:

wax.start("car").attr("year", 2008)
.defaultNamespace("http://www.ociweb.com/cars", "car.xsd")
.namespace("m", "http://www.ociweb.com/model", "model.xsd")
.child("m", "model", "Prius").close();
<car year="2008"
xmlns="http://www.ociweb.com/cars"
xmlns:m="http://www.ociweb.com/model"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xsi:schemaLocation="http://www.ociweb.com/cars car.xsd
http://www.ociweb.com/model model.xsd">
<m:model>Prius</m:model>
</car>

Let's associate a DTD with the XML:

wax.dtd("car.dtd")
.start("car").attr("year", 2008)
.child("model", "Prius").close();
<!DOCTYPE car SYSTEM "car.dtd">
<car year="2008">
<model>Prius</model>
</car>

Let's add and use entity definitions:

String url = "http://www.ociweb.com/xml/";
wax.entityDef("oci", "Object Computing, Inc.")
.externalEntityDef("moreData", url + "moreData.xml")
.start("root")
.unescapedText("The author works at &oci; in St. Louis, Missouri.",
true) // avoiding escaping for entity reference
.unescapedText("&moreData;", true)
.close();
<!DOCTYPE root [
<!ENTITY oci "Object Computing, Inc.">
<!ENTITY moreData SYSTEM "http://www.ociweb.com/xml/moreData.xml">
]>
<root>
The author works at &oci; in St. Louis, Missouri.
&moreData;
</root>

A common usage pattern is to pass a WAX object to a method of model objects that use it to write their XML representation. For example, a Car class could have the following method.

public void toXML(WAX wax) {
wax.start("car")
.attr("year", year)
.child("make", make)
.child("model", model)
.end();
}

An example of the XML this would produce follows:

<car year="2008">
<make>Toyota</make>
<model>Prius</model>
</car>

A Person class whose objects hold a reference to an Address object could have the following method.

public void toXML(WAX wax) {
wax.start("person")
.attr("birthdate", birthdate)
.child("name", name);
address.toXML(wax);
wax.end();
}

The Address class could have the following method.

public void toXML(WAX wax) {
wax.start("address")
.child("street", street);
.child("city", city);
.child("state", state);
.child("zip", zip);
.end();
}

An example of the XML this would produce follows:

<person birthdate="4/16/1961">
<name>R. Mark Volkmann</name>
<address>
<street>123 Some Street</street>
<city>Some City</city>
<state>MO</state>
<zip>12345</zip>
</address>
</person>

신고
Posted by Tornado tornado

출처 : http://wheelersoftware.com/articles/spring-cxf-web-services.html



1 | 2 | 3 | 4 | Next »
Software Development

Web Services with Spring 2.5 and Apache CXF 2.0

Quickly create web services in Spring 2.5 using Apache CXF 2.0, a.k.a. XFire 2.0.

In this tutorial I explain how to get a web service up and running using Spring 2.5 and Apache CXF 2.0, which is the combination of Celtix and XFire and is considered XFire 2.0. (I don't know what the Celtix team would say about that, but that's what the XFire site says.) Here I just treat the web service itself; to learn about consuming the web service using Spring and CXF, please see the article Make Web Services Transparent with Spring 2.5 and Apache CXF 2.0.

CXF supports both WSDL-first and Java-first web service development. This article takes the Java-first approach.

Project Setup

The first thing you'll need to do is download CXF from the Apache CXF site. At the time of this writing the project is in incubator status and the latest version is 2.0.4. That's the version I'm using.

You'll also find it useful to know about the section of the CXF user documentation that deals with writing a service with Spring, but currently the docs describe how to integrate with Spring 2.0, and since I want to integrate with Spring 2.5, there are some differences worth highlighting along the way.

Also, the docs describe a "Hello, World" web service that just returns a string, and in this tutorial we want to go a little further than that and actually do a class databinding.

Here are the service-side dependencies you'll need. Inside the distribution there is a file called WHICH_JARS that describes in a little more detail what the JARs are for and which ones you'll really need, if you're interested in that. But the following is essentially the list given in the user docs.

CXF itself

  • cxf-2.0.4-incubator.jar

CXF dependencies

Note that for CXF 2.0.4 the documented dependencies are almost but not quite the same as the JARs that are actually included in the distribution, once again, at the time of this writing (February 2008). Specifically the stax, neethi and XMLSchema JARs are not the ones listed. Here's the corrected list for CXF 2.0.4:

  • commons-logging-1.1.jar
  • geronimo-activation_1.1_spec-1.0-M1.jar (or Sun's Activation jar)
  • geronimo-annotation_1.0_spec-1.1.jar (JSR 250)
  • geronimo-javamail_1.4_spec-1.0-M1.jar (or Sun's JavaMail jar)
  • geronimo-servlet_2.5_spec-1.1-M1.jar (or Sun's Servlet jar)
  • geronimo-stax-api_1.0_spec-1.0.jar
  • geronimo-ws-metadata_2.0_spec-1.1.1.jar (JSR 181)
  • jaxb-api-2.0.jar
  • jaxb-impl-2.0.5.jar
  • jaxws-api-2.0.jar
  • neethi-2.0.2.jar
  • saaj-api-1.3.jar
  • saaj-impl-1.3.jar
  • wsdl4j-1.6.1.jar
  • wstx-asl-3.2.1.jar
  • XmlSchema-1.3.2.jar
  • xml-resolver-1.2.jar

Aegis dependencies

In addition to the above, you will need to add jdom-1.0.jar since Aegis databinding uses it.

Spring dependencies

In this case ignore what's in the CXF documentation, because we're integrating with Spring 2.5 instead of Spring 2.0. I'm going to assume that you have Spring 2.5 already set up on your web services project, including Hibernate or anything else that your web services will need on the implementation side.

Just in case you were wondering, you don't need the Spring MVC module's DispatcherServlet as CXF comes with its own servlet, org.apache.cxf.transport.servlet.CXFServlet.

OK, that should be good for basic project setup. Let's write a simple service.


신고
Posted by Tornado tornado
출처 : http://www.vitarara.org/cms/struts_2_cookbook/post_and_redirect


<action name="createSalesOrderConfirmation" class="sales.CreateSalesOrderAction">
<result name="redirect" type="redirect-action">
<param name="actionName">displaySalesOrder</param>
<param name="namespace">/order/sales</param>
<param name="parse">true</param>
<param name="id">${order.id}</param>
</result>
</action>
신고
Posted by Tornado tornado

Struts2 에서는 아래와 같은 방법으로 사용 가능합니다.

 

src/defaultConfigure.properties format 을 등록.

 

# number format

format.qty={0,number, ,###,###,###}

 

JSP 페이지에서는 다음과 같이 호출합니다.

 

<s:text name="format.qty"><s:param name="value" value="%{10000}"/></s:text>

 

결과는 10,000 과 같이 출력됩니다.

신고
Posted by Tornado tornado
출처 : http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=56&t=006418

자바를 너무 오랫동안 안했나보다... 완전 허무 ...


You should be able to delete ${catalina.home}/work/Catalina/localhost/appName/SESSION.ser where appName is your application (or just delete the whole work directory).

This should enable you to restart.



신고
Posted by Tornado tornado