저작권 표시

기타 2012. 8. 29. 13:15


company limited by shares = 주식회사
영문을 줄여서 Co.,LTD. 라고 표기합니다.


.(마침표)는 약자임을 나타냅니다.
,(쉼표)는 중요하지 않은 말을 뒤로 붙일 때 사용합니다.


Co., ==> 줄였으니 .(마침표)를 찍고 뒤에 중요하지 않은 말을 뒤에 붙이니 ,(쉼표)를 사용하는 것 입니다.


LTD.는 limited를 줄여서 표기한 것이니 뒤에 .(마침표)를 찍어야 합니다.
(위 질문에 Co 뒤에 ,. 가 아니라 ., 입니다. 위치가 바꼇습니다.)

주식회사인 경우 회사명 뒤에 Co.,Ltd. 를 적어주면 됩니다.
회사명이 "잘난 주식회사"면 영문으로 표기할 때
Jalnan Co.,Ltd.
라고 표기하면 됩니다.

참고로...
Copyright ⓒ ==> 저작권(아이디어 자체보다 아이디어의 표현을 보호)
All rights reserved. ==> 판권 소유(소유자의 허락 없이 사용하는 것을 금지하는 표시)





저작권에 대해 무방식주의인 우리나라에서는 저작권 표시 자체가 큰 의미는 없습니다. 즉 저작권법에 의해 창작될때 저작권이 발생하며 위와 같은 표기를 하지 않더라도 저작권법에 의해 동등하게 보호를 받게 됩니다.

 

제10조(저작권) 저작권은 저작물은 창작한 때부터 발생하며 어떠한 절차나 형식의 이행을 필요로 하지 아니한다.

 

Copyrightⓒ. All Rights Reserved 이 뜻은 모든 권리는 저작권자에게 있다는 의미이며, 성명 등을 추가하여 저작권자를 나타낼 수도 있습니다.  더욱 구체적으로 표기하고자 한다면 Copyrightⓒ. 2010. 홍길동. All Rights Reserved. 이런 식으로 할 수 있습니다.

 

다만 최근에는 다양한 문제로 인하여 사전에 한국저작권위원회를 통해 저작물을 별도로 등록하여 적극적으로 저작권을 보호하고 행사하는 사례가 많아지고 있습니다. 물론 한국저작권위원회에 등록을 하지 않더라도 저작권리는 동등하게 존재하나 등록을 하는 이유는 창작시기와 저작권자 등을 보다 명확하게 할 수 있기 때문입니다.

 

http://www.copyright.or.kr/main/index.do 한국저작권위원회

 

도움이 되셨기를..



출처 - http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=11003&docId=153032571&qb=Y29weXJpZ2h0&enc=utf8&section=kin&rank=1&search_sort=0&spq=1&pid=Rv2Si35Y7udssZ4Kcddssc--112076&sid=UD2U-5CHPVAAAHsOCJ0

http://kin.naver.com/qna/detail.nhn?d1id=6&dirId=60205&docId=120951668&qb=Y29weXJpZ2h0&enc=utf8&section=kin&rank=2&search_sort=0&spq=1&pid=Rv2Si35Y7udssZ4Kcddssc--112076&sid=UD2U-5CHPVAAAHsOCJ0


'기타' 카테고리의 다른 글

SL-C433W 컬러레이저프린터 구매후기  (0) 2018.12.13
How to run Chromium with different UI language on Linux?  (0) 2014.07.12
zip code 란  (0) 2012.03.21
워드에서 티스토리 글 작성  (0) 2012.03.11
여의도맛집 본가참치  (0) 2012.03.08
Posted by linuxism
,


5.HTTP Invoker

HTTP Invoker는 HTTP를 통해 경량의 원격 서비스를 가능하게 하는 Spring에서 제공하는 Remoting 기능이다. 앞서 소개한 RMI와 Hessian/Burlap의 경우 아래와 같은 단점이 있는데 이러한 단점을 보완해주는 기능을 HTTP Invoker가 가지고 있다.

  • RMI 단점: RMI의 경우 자바의 표준 객체 직렬화를 사용하지만 방화벽을 통과하기가 어렵다.

  • Hessian/Burlap의 단점: 방화벽을 쉽게 통과하지만, 자체적인 객체 직렬화 매커니즘을 사용하여 복잡한 형태의 객체 직렬화 시 문제가 발생할 수 있다.

HTTP Invoker는 RMI와 Hessian/Burlap의 단점을 보완해준다. Spring에서 제공하는 Remoting 기능으로 HTTP를 통해 Remoting 기능을 수행하며 자바의 표준 직렬화 매커니즘을 사용한다. 단, Spring에서만 제공하는 Remoting 기술로 클라이언트와 원격 서비스 모두 Spring 어플리케이션 이어야 한다.

다음은 HTTP Invoker 기능을 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다.

5.1.Server Configuration

서버 구현 방식은 일반 서비스 빈 개발 방식과 같으며 HttpInvokerServiceExporter 클래스를 이용하여 손쉽게 일반 Spring Bean으로 작성된 서비스를 HTTP Invoker Service로 노출시킬 수 있다. 이때 모든 public 메소드는 서비스 메소드로 노출된다.

Property NameDescriptionRequiredDefault Value
serviceHTTP Invoker 서비스로 노출시키고 싶은 Spring Bean의 id를 설정한다.YN/A
serviceInterfaceHTTP Invoker 서비스로 노출되는 서비스의 인터페이스 클래스를 패키지정보와 함께 작성한다.YN/A

5.1.1.Samples

다음은 HTTP Invoker 서버 구현 속성 설정에 대한 예제이다. 서비스는 일반 Spring Bean 개발과 동일하며 HttpInvokerServiceExporter Bean에서 property 설정 정보를 참조하여 HTTP Invoker 서비스로 노출시키고 있다.

  • Configuration

    다음은 HTTP Invoker 서비스를 지원하는 HttpInvokerServiceExporter의 속성을 정의한 context-remoting.xml 의 일부이다.

    <bean id="remotingProductService" 
            class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="service" ref="productService"/>
        <property name="serviceInterface" 
                value="anyframe.sample.remoting.sales.service.ProductService" />
    </bean>

    여기서 HttpInvokerServiceExporter 빈은 Spring MVC의 컨트롤러로 작성되어 있으므로 Spring MVC의 DispatcherServlet을 web.xml 파일에 설정해야 한다. HTTP로 서비스를 제공하기 위해서 웹 어플리케이션으로 서비스를 배포하여 제공하고 있다. 다음은 서버 사이드 웹 어플리케이션의 web.xml 의 일부이다.

    <web-app id="WebApp_ID" version="2.4"
        xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <display-name>sample-web</display-name>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath:/spring/context-*.xml
            </param-value>
        </context-param>
        
        ...중략...
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener
            </listener-class>
        </listener>
        
        <servlet>
            <servlet-name>action</servlet-name>
            <servlet-class>
                org.springframework.web.servlet.DispatcherServlet
            </servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:/springmvc/*-servlet.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>action</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
        
        <!-- remoting-configuration-START -->  
        <servlet>
            <servlet-name>remoting</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:/springmvc/remoting-servlet.xml</param-value>
            </init-param>
        </servlet>    
        
        <servlet-mapping>
            <servlet-name>remoting</servlet-name>
            <url-pattern>/remoting/*</url-pattern>
        </servlet-mapping>    
        <!-- remoting-configuration-END -->
        ...중략...
    </web-app>

    여기서 Spring MVC의 URL Mapping 기능을 사용하여 HTTP 기반의 HTTP Invoker 컨트롤러를 호출할 수 있도록 한다. 다음은 서버 사이드 웹 어플리케이션의 remoting-servlet.xml 의 일부이다. * 패턴의 모든 URL에 대한 요청이 DispatcherServlet으로 전달된 후 urlMapping 정보에 의해 remotingProductService가 호출되어 HTTP Invoker 서비스가 제공된다.

    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/ProductService">remotingProductService</prop>
            </props>
        </property>
    </bean>

5.2.Client Configuration

클라이언트는 Spring에서 제공하는 org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean 클래스를 사용하여 HTTP Invoker Service에 접근할 수 있다.

Property NameDescriptionRequiredDefault Value
serviceUrlHTTP Invoker 서비스 접근 URL 정보이다. "http://" + 서버ip + ":" + port 번호 + "/" + 서비스 명 (ex.http://localhost:9002/ProductService)YN/A
serviceInterfaceHTTP Invoker 서비스로 노출되는 서비스의 인터페이스 클래스를 패키지정보와 함께 작성한다.YN/A

5.2.1.Samples

다음은 HTTP Invoker 클라이언트 속성 설정에 대한 예제이다. 클라이언트는 HttpInvokerProxyFactoryBean에서 property 설정 정보를 참조하여 HTTP Invoker 서비스에 접근하고 있다.

  • Configuration

    다음은 HTTP Invoker 서비스에 접근하는 HttpInvokerProxyFactoryBean의 속성을 정의한 context-remoting.xml 의 일부이다.

    <bean id="productServiceClient"
        class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <property name="serviceUrl"
            value="http://localhost:8080/anyframe.sample.remoting/remoting/ProductService" />
        <property name="serviceInterface"
            value="anyframe.sample.remoting.sales.service.ProductService" />
    </bean>

    Hessian/Burlap 서비스에 접근하는 클라이언트와 마찬가지로 serviceInterface Property에는 서비스가 구현하는 인터페이스 클래스를 설정하고. serviceUrl Property에는 서비스 URL을 작성하는데 HTTP Invoker라는 이름에서도 알 수 있듯이 HTTP 기반으로 제공되므로 HTTP URL을 작성하도록 한다. HTTP 방식으로 원격 서비스를 호출할 때 HTTP 클라이언트를 선택할 수 있다. 기본적으로 HttpInvokerProxyFactoryBean은 J2SE HTTP 클라이언트를 사용하지만, httpInvokerRequestExecutor 프라퍼티를 셋팅하여 Apache Commons HttpClient를 사용할 수도 있다.

    <!-- Add HTTP Invoker Client -->
    <bean id="productServiceClient" 
            class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <property name="serviceUrl" value="http://localhost:8080/ProductService" />
        <property name="serviceInterface" 
                value="anyframe.sample.remoting.sales.ProductService"/>
        <property name="httpInvokerRequestExecutor" ref="httpClient"/>    
    </bean>
    
    <bean id="httpClient" 
          class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"> 
        <property name="httpClient"> 
            <bean class="org.apache.commons.httpclient.HttpClient"> 
                <property name="connectionTimeout" value="2000"/> 
            </bean> 
        </property> 
    </bean>

  • Test Case

    다음은 앞서 정의한 속성 설정 파일들을 기반으로 하여 HTTP Invoker 서비스에 접근하는 예제인 ProductController.java 코드의 일부이다.

    public class HttpInvokerSpringSupportTest extends RemotingSpringTestCase {
    
    @Controller
    public class ProductController {
        @Resource(name = "productServiceClient")
        private ProductService productService;
    
        /**
         * get a product detail.
         * 
         * @param request
         * @param response
         * @return
         * @throws Exception
         */
        @RequestMapping("/remotingGetProduct.do")
        public ModelAndView get(HttpServletRequest request) throws Exception {
    
            String prodNo = request.getParameter("prodNo");
    
            if (!StringUtils.isBlank(prodNo)) {
                Product gettedProduct = (Product) productService.get(prodNo);
    
                gettedProduct.setImageFile("/upload/"
                        + gettedProduct.getImageFile());
                request.setAttribute("product", gettedProduct);
            }
    
            return new ModelAndView(
                    "/WEB-INF/jsp/remoting/sales/product/viewProduct.jsp");
        }
    
        /**
         * display product list
         * 
         * @param request
         * @param response
         * @return
         * @throws Exception
         */
        @RequestMapping("/remotingListProduct.do")
        public ModelAndView list(HttpServletRequest request,
                ProductSearchVO searchVO) throws Exception {
    
            String pageParam = (new ParamEncoder("productList")
                    .encodeParameterName(TableTagParameters.PARAMETER_PAGE));
            String pageParamValue = request.getParameter(pageParam);
            int pageIndex = StringUtil.isNotEmpty(pageParamValue) ? (Integer
                    .parseInt(pageParamValue)) : 1;
            searchVO.setPageIndex(pageIndex);
    
            Page resultPage = productService.getPagingList(searchVO);
    
            request.setAttribute("search", searchVO);
            request.setAttribute("productList", resultPage.getList());
            request.setAttribute("size", resultPage.getTotalCount());
            request.setAttribute("pagesize", resultPage.getPagesize());
            request.setAttribute("pageunit", resultPage.getPageunit());
    
            return new ModelAndView(
                    "/WEB-INF/jsp/remoting/sales/product/listProduct.jsp");
        }
    }


출처 - http://dev.anyframejava.org/docs/anyframe/plugin/remoting/4.5.2/reference/html/ch05.html



Posted by linuxism
,


Chapter 17. Spring을 사용한 원격(Remoting)및 웹서비스

17.1. 소개

원격 지원을 위한 Spring통합 클래스는 다양한 기술을 사용한다. 원격 지원은 당신의 (Spring) POJO에 의해 구현되는 원격-가능 서비스의 개발을 쉽게 한다. 현재 Spring은 4가지 원격 기술을 지원한다.

  • 원격 메소드 호출 (RMI). RmiProxyFactoryBeanRmiServiceExporter의 사용을 통해 Spring은 전통적인 RMI(java.rmi.Remote 인터페이스와 java.rmi.RemoteException을 가지는)와 RMI 호출자(어떠한 자바 인터페이스를 가진)를 통한 투명한 원격 모두 지원합니다.

  • Spring의 HTTP 호출자. Spring은 어떤 자바 인터페이스(RMI 호출자와 같은)를 지원하는 HTTP를 통한 자바 직렬화를 허용하는 특별한 원격 전략을 제공한다. 관련 지원 클래스는 HttpInvokerProxyFactoryBeanHttpInvokerServiceExporter이다.

  • Hessian. HessianProxyFactoryBeanHessianServiceExporter를 사용하여 Caucho에 의해 제공되는 가벼운 바이너리 HTTP기반 프로토콜을 사용하는 당신의 서비스를 투명하게 드러낼수 있다.

  • Burlap. Burlap은 Hessian을 위한 Caucho의 XML기반의 대안이다. Spring은 BurlapProxyFactoryBeanBurlapServiceExporter 같은 지원 클래스를 제공한다.

  • JAX RPC. Spring은 JAX-RPC를 통한 웹서비스를 위한 원격 지원을 제공한다.

  • JMS (TODO).

Spring의 원격 기능에 대해 언급하는 동안 우리는 다음의 도메인 모델과 관련 서비스를 사용할것이다.

// Account domain object
public class Account implements Serializable{
  private String name;

  public String getName();
  public void setName(String name) {
    this.name = name;
  }
}
			

// Account service
public interface AccountService {

  public void insertAccount(Account acc);
  
  public List getAccounts(String name);
}
			

// Remote Account service
public interface RemoteAccountService extends Remote {

  public void insertAccount(Account acc) throws RemoteException;
  
  public List getAccounts(String name) throws RemoteException;
}
			

// ... and corresponding implement doing nothing at the moment
public class AccountServiceImpl implements AccountService {

  public void insertAccount(Account acc) {
    // do something
  }
  
  public List getAccounts(String name) {
    // do something
  }
}
			

우리는 RMI를 사용하여 원격 클라이언트에 서비스를 드러내길 시작하고 RMI를 사용한 장애에 대해 조금 이야기할것이다. 우리는 Hessian을 위한 예제를 보여줄 것이다.

17.2. RMI를 사용한 서비스 드러내기

RMI를 위한 Spring의 지원을 사용하여, 당신은 RMI내부구조를 통해 당신의 서비스를 투명하게 드러낼수 있다. 이 셋업 후 당신은 보안 컨텍스트 위임이나 원격 트랜잭션 위임을 위한 표준적인 지원이 없다는 사실을 제외하고 기본적으로 remote EJB와 유사한 설정을 가진다. Spring은 RMI호출자를 사용할때 추가적인 호출 컨텍스트와 같은 것을 위한 고리(hooks)를 제공한다. 그래서 당신은 예를 들어 보안 프레임워크나 사용자정의 보안 증명에 붙일수 있다.

17.2.1. RmiServiceExporter를 사용하여 서비스 내보내기

RmiServiceExporter를 사용하여, 우리는 RMI객체처럼 AccountService객체의 인터페이스를 드러낼수 있다. 인터페이스는 RmiProxyFactoryBean을 사용하거나 전통적인 RMI서비스의 경우 일반적인 RMI를 통해 접근될수 있다. RmiServiceExporter는 RMI호출자를 통해 RMI가 아닌 서비스의 발생을 명시적으로 지원한다.

우리는 먼저 Spring BeanFactory내 우리의 서비스를 셋업한다.

<bean id="accountService" class="example.AccountServiceImpl">
    <!-- any additional properties, maybe a DAO? -->
</bean>
				

그리고 나서 우리는 RmiServiceExporter를 사용하여 우리의 서비스를 드러낼것이다.

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
	<!-- does not necessarily have to be the same name as the bean to be exported -->
	<property name="serviceName"><value>AccountService</value></property>
	<property name="service"><ref bean="accountService"/></property>
	<property name="serviceInterface"><value>example.AccountService</value></property>
	<!-- defaults to 1099 -->
	<property name="registryPort"><value>1199</value></property>
</bean>
				

당신이 볼수 있는 것처럼, 우리는 RMI등록(registry)을 위한 포트를 오버라이딩한다. 종종, 당신의 애플리케이션 서버는 RMI등록을 유지하고 그것을 방해하지 않는것이 현명하다. 게다가 서비스 이름은 서비스를 바인드 하기 위해 사용된다. 서비스는 rmi://HOST:1199/AccountService에 비인드될것이고 우리는 클라이언트측에서 서비스로 링크하기 위해 이 URL을 사용할것이다.

노트 : 우리는 하나의 프라퍼티를 남겨두었다. 이를테면 servicePort이고 디폴트로에 의해 0이된다. 이것은 서비스와 통신하기 위해 사용될 익명 포트를 의미한다. 당신은 다른 포트를 명시할수 있다.

17.2.2. 클라이언트에서 서비스 링크하기

우리의 클라이언트는 계좌(accounts)를 관리하기 위한 AccountService을 사용하는 간단한 객체이다.

public class SimpleObject {
  private AccountService accountService;
  public void setAccountService(AccountService accountService) {
    this.accountService = accountService;
  }
}
				

클라이언트에서 서비스에 링크하기 위해, 우리는 간단한 객체와 서비스 링크 설정을 포함하는 분리된 bean factory를 생성할 것이다.

<bean class="example.SimpleObject">
	<property name="accountService"><ref bean="accountService"/></property>
</bean>

<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
	<property name="serviceUrl"><value>rmi://HOST:1199/AccountService</value></property>
	<property name="serviceInterface"><value>example.AccountService</value></property>
</bean>
				

그것은 우리가 클라이언트에서 원격 계좌(account)서비스를 지원하기 위해 해야 할 필요가 있는 모든것이다. Spring은 호출자를 투명하게 생성하고 RmiServiceExporter를 통해 계좌 서비스를 원격적으로 가능하게 한다. 클라이언트에서 우리는 RmiProxyFactoryBean를 사용하여 이것을 링크한다.

17.3. HTTP를 통해 서비스를 원격으로 호출하기 위한 Hessian 이나 Burlap을 사용하기.

Hessian은 바이너리 HTTP-기반 원격 프로토콜을 제공한다. 이것은 Caucho에 의해 생성되었고 Hessian자체에 대한 좀더 상세한 정보는 http://www.caucho.com에서 찾을수 있다.

17.3.1. Hessian을 위해 DispatcherServlet을 묶기.

Hessian은 HTTP를 통해 통신하고 사용자정의 서블릿을 사용해서도 그렇게 한다. Spring의 DispatcherServlet 원리를 사용하여, 당신의 서비스를 드러내는 서블릿을 쉽게 묶을수 있다. 먼저 우리는 애플리케이션내 새로운 서블릿을 생성해야만 한다. (이것은 web.xml으로 부터 인용한다.)

<servlet>
	<servlet-name>remoting</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>remoting</servlet-name>
	<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
				

당신은 아마도 Spring의 DispatcherServlet 원리에 익숙하고 만약 그렇다면 당신은 WEB-INF 디렉토리내 (당신의 서블릿 이름 뒤) remoting-servlet.xml라는 이름의 애플리케이션 컨텍스트를 생성할것이다. 애플리케이션 컨텍스트는 다음 부분에서 사용될것이다.

17.3.2. HessianServiceExporter를 사용하여 bean을 드러내기

remoting-servlet.xml 라고 불리는 새롭게 생성된 애플리케이션 컨텍스트내에서 우리는 당신의 서비스를 내보내는 HessianServiceExporter를 생성할것이다.

<bean id="accountService" class="example.AccountServiceImpl">
    <!-- any additional properties, maybe a DAO? -->
</bean>

<bean name="/AccountService" class="org.springframework.remoting.caucho.HessianServiceExporter">
    <property name="service"><ref bean="accountService"/></property>
    <property name="serviceInterface">
        <value>example.AccountService</value>
    </property>
</bean>
				

지금 우리는 클라이언트에서 서비스를 링크할 준비가 되어있다. 명시된 핸들러 맵핑은 없고 서비스를 향한 요청 URL을 맵핑한다. 그래서 BeanNameUrlHandlerMapping은 사용될것이다. 나아가 서비스는 bean이름(http://HOST:8080/remoting/AccountService)을 통해 표시되는 URL에 내보내어질것이다.

17.3.3. 클라이언트의 서비스로 링크하기

HessianProxyFactoryBean을 사용하여 우리는 클라이언트에서 서비스로 링크할수 있다. 같은 원리는 RMI예제처럼 적용한다. 우리는 분리된 bean factory나 애플리케이션 컨텍스트를 생성하고 SimpleObject가 계좌를 관리하기 위해 AccountService를 사용하는 다음 bean을 따른다.

<bean class="example.SimpleObject">
    <property name="accountService"><ref bean="accountService"/></property>
</bean>

<bean id="accountService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
	<property name="serviceUrl"><value>http://remotehost:8080/AccountService</value></property>
	<property name="ServiceInterface"><value>example.AccountService</value></property>
</bean>
				

That's all there is to it.

17.3.4. Burlap 사용하기

우리는 Hessian의 XML기반의 대응물인 Burlap을 여기서 상세하게 언급하지 않을것이다. Hessian처럼 정확하게 같은 방법으로 설정되고 셋업된 후 변형물은 위에서 설명된다. Hessian 이라는 단어를 Burlap으로 교체하고 당신은 모든것을 셋팅한다.

17.3.5. Hessian 이나 Burlap을 통해 드러나는 서비스를 위한 HTTP 기본 인증 적용하기

Hessian 과 Burlap 장점중 하나는 두가지 프로토콜이 모두 HTTP-기반이기 때문에 우리가 HTTP 기본 인증을 쉽게 적용할수 있다는 것이다. 당신의 일반적인 HTTP서버의 보안 기법은 web.xml 보안 기능을 사용하여 쉽게 적용될수 있다. 대개 당신은 여기서 사용자별 보안 증명을 사용하지 않지만 공유된 증명은 Hessian/BurlapProxyFactoryBean 레벨(JDBC 데이터소스와 유사한)에서 정의된다.

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
	<property name="interceptors">
		<list>
			<ref bean="authorizationInterceptor"/>
		</list>
	</property>
</bean>

<bean id="authorizationInterceptor" 
	class="org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor">
	<property name="authorizedRoles">
		<list>
			<value>administrator</value>
			<value>operator</value>
		</list>
	</property>	
</bean>
				

이것은 우리가 BeanNameUrlHandlerMapping을 명시적으로 언급하고 오직 관리자만을 허용하는 인터셉터를 셋팅하며 이 애플리케이션 컨텍스트내에서 언급된 bean을 호출하는 작업을 수행하는 예제이다.

노트 : 물론, 이 예제는 보안 내부구조의 유연한 종류를 보여주지 않는다. 보안이 관련된 만큼 좀더 많은 옵션을 위해서 Spring을 위한 Acegi 보안 시스템을 보라. 그것은 http://acegisecurity.sourceforge.net에서 찾을수 있다.

17.4. HTTP호출자를 사용하여 서비스를 드러내기

그들 자체의 얼마 안되는 직렬화 기법을 사용하는 가벼운 프로토콜인 Burlap 과 Hessian이 상반돤것처럼 Spring HTTP호출자는 HTTP를 통해 서비스를 드러내기 위한 표준적인 자바 직렬화 기법을 사용한다. 이것은 당신의 인자와 반환 타입이 Hessian 과 Burlap이 사용하는 직렬화 기법을 사용하여 직렬화될수 없는 복합(complex)타입이라면 커다란 장점을 가진다. (원격 기술을 선택할때 좀더 많은 숙고사항을 위해서 다음 부분을 참조하라.)

Spring은 HTTP호출을 수행하거나 Commons HttpClient를 위해 J2SE에 의해 제공되는 표준적인 기능을 사용한다. 만약 당신이 좀더 향상되었거나 사용하기 쉬운 기능이 필요하다면 후자를 사용하라. 좀더 많은 정보를 위해서는 jakarta.apache.org/commons/httpclient을 참조하라.

17.4.1. 서비스 객체를 드러내기

Hessian 이나 Burlap을 사용하는 방법과 매우 유사한 서비스 객체를 위한 HTTP 호출자 내부구조를 셋업하라. Hessian지원이 HessianServiceExporter를 제공하는 것처럼 Spring Http호출자 지원은 org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter라고 불리는 것을 제공한다. (위에서 언급된) AccountService을 드러내기 위해 다음 설정이 대체될 필요가 있다.

    <bean name="/AccountService" class="org.sprfr.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="service"><ref bean="accountService"/></property>
        <property name="serviceInterface">
            <value>example.AccountService</value>
        </property>
	</bean>

17.4.2. 클라이언트에서 서비스 링크하기

다시 클라이언트로부터 서비스를 링크하는것은 Hessian 이나 Burlap을 사용할때 이것을 하는 방법과 매우 유사하다. 프록시를 사용하여 Spring은 내보내어진 서비스를 위한 URL을 위해 당신의 호출을 HTTP POST요청으로 번역할수 있을것이다.

	
	<bean id="httpInvokerProxy" class="org.sprfr.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
		<property name="serviceUrl">
			<value>http://remotehost:8080/AccountService</value>
		</property>
		<property name="serviceInterface">
			<value>example.AccountService</value>
		</property>
	</bean>

전에 언급된것처럼, 당신은 사용하고자 하는 HTTP클라이언트를 선택할수 있다. 디폴트에 의하면 HttpInvokerProxy가 J2SE HTTP기능을 사용한다. 하지만 당신은 httpInvokerRequestExecutor 프라퍼티를 셋팅하여 Commons HttpClient를 사용할수 있다.

<property name="httpInvokerRequestExecutor">
	<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
</property>

17.5. 웹 서비스

Spring은 다음을 위한 지원을 가진다.

  • JAX-RPC를 사용하여 서비스를 드러내기
  • 웹 서비스에 접근하기

위의 지원 목록 다음으로, 당신은 XFire xfire.codehaus.org를 사용하여 웹 서비스를 드러낼수 있다. XFire는 Codehaus에서 현재 개발중인 가벼운 SOAP라이브러리이다.

17.5.1. JAX-RPC를 사용하여 서비스를 드러내기

Spring은 JAX-RPC 서블릿 endpoint구현물(ServletEndpointSupport) 을 위한 편리한 base클래스이다. 우리의 AccountService를 드러내기 위해 우리는 Spring의 ServletEndpointSupport클래스를 확장하고 여기서 언제나 비지니스 레이어로 호출을 위임하는 비지니스 로직을 구현한다.

/**
 * JAX-RPC compliant RemoteAccountService implementation that simply delegates
 * to the AccountService implementation in the root web application context.
 *
 * This wrapper class is necessary because JAX-RPC requires working with
 * RMI interfaces. If an existing service needs to be exported, a wrapper that
 * extends ServletEndpointSupport for simple application context access is
 * the simplest JAX-RPC compliant way.
 *
 * This is the class registered with the server-side JAX-RPC implementation.
 * In the case of Axis, this happens in "server-config.wsdd" respectively via
 * deployment calls. The Web Service tool manages the life-cycle of instances
 * of this class: A Spring application context can just be accessed here.
 */
public class AccountServiceEndpoint extends ServletEndpointSupport implements RemoteAccountService {
    
    private AccountService biz;
	
    protected void onInit() {
        this.biz = (AccountService) getWebApplicationContext().getBean("accountService");
    }

    public void insertAccount(Account acc) throws RemoteException {
        biz.insertAccount(acc);
    }
  
    public Account[] getAccounts(String name) throws RemoteException {
        return biz.getAccounts(name);
    }
  
}	

우리의 AccountServletEndpoint는 Spring의 기능에 접근하기 위해 허용하는 Spring컨텍스트처럼 같은 웹 애플리케이션내에서 수행할 필요가 있다. Axis의 경우, AxisServlet정의를 web.xml로 복사하고 "server-config.wsdd" 내 endpoint를 셋업한다.(또는 배치툴을 사용한다.) Axis를 사용한 웹 서비스처럼 드러나는 OrderService가 있는 샘플 애플리케이션 JPetStore를 보라.

17.5.2. 웹 서비스에 접근하기

Spring은 웹 서비스 프록시인 LocalJaxRpcServiceFactoryBeanJaxRpcPortProxyFactoryBean을 생성하기 위한 두가지 factory bean을 가진다. 전자는 JAX-RPC서비스 클래스만을 반환할수 있다. 후자는 우리의 비지니스 서비스 인터페이스를 구현하는 프록시를 반환할수 있는 완전한 버전이다. 이 예제에서 우리는 이전 단락내 나오는 AccountService Endpoint를 위한 프록시를 생성하기 위해 나중에 사용된다. 당신은 Spring이 조금의 코딩을 요구하는 웹 서비스를 위한 대단한 지원을 가진다는 것을 볼것이다. 대부분의 마법은 대개 Spring설정 파일내에서 이루어진다.

    <bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
        <property name="serviceInterface">
            <value>example.RemoteAccountService</value>
        </property>
        <property name="wsdlDocumentUrl">
            <value>http://localhost:8080/account/services/accountService?WSDL</value>
        </property>
        <property name="namespaceUri">
            <value>http://localhost:8080/account/services/accountService</value>
        </property>
        <property name="serviceName">
            <value>AccountService</value>
        </property>
        <property name="portName">
            <value>AccountPort</value>
        </property>
    </bean>

serviceInterface는 클라이언트가 사용할 원격 비지니스 인터페이스이다. wsdlDocumentUrl은 WSDL파일을 위한 URL이다. Spring은 JAX-RPC서비스를 생성하기 위해 시작시 이것이 필요하다. namespaceUri는 .wsdl파일내 targetNamespace에 대응한다. serviceName은 .wsdl파일내 서비스 이름에 대응한다. portName은 .wsdl파일내 포트명에 대응한다.

웹 서비스에 접근하는 것은 우리가 RemoteAccountService인터페이스처럼 이것을 드러내는 bean factory를 가지는것처럼 매우 쉽다. 우리는 Spring내 이것을 묶을수 있다.

    <bean id="client" class="example.AccountClientImpl">
        ...
        <property name="service">
            <ref bean="accountWebService"/>
        </property>
    </bean>

그리고 클라이언트 코드로 부터 우리는 이것이 RemoteException을 던지는것을 제외하고 일반 클래스인것처럼 웹 서비스에 접근할수 있다.

public class AccountClientImpl {

    private RemoteAccountService service;
    
    public void setService(RemoteAccountService service) {
        this.service = service;
    }
    
    public void foo() {
       try {
           service.insertAccount(...);
        } catch (RemoteException e) {
           // ouch
           ...
        }
     }
     
}

우리는 Spring이 관련된 체크되지 않은 RemoteAccessException으로의 자동변환을 지원하기 때문에 체크된 RemoteException을 제거할수 있다. 이것은 우리가 비-RMI인터페이스 또한 제공하는것을 요구한다. 우리의 설정은 다음과 같다.

    <bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
        <property name="serviceInterface">
            <value>example.AccountService</value>
        </property>
        <property name="portInterface">
            <value>example.RemoteAccountService</value>
        </property>
        ...
    </bean>

serviceInterface는 비-RMI 인터페이스를 위해 변경된다. 우리의 RMI 인터페이스는 portInterface 프라퍼티를 사용하여 정의된다. 우리의 클라이언트 코드는 java.rmi.RemoteException을 피할수 있다.

public class AccountClientImpl {

    private AccountService service;
    
    public void setService(AccountService service) {
        this.service = service;
    }
    
    public void foo() {
        service.insertAccount(...);
     }
     
}

17.5.3. Register Bean 맵핑

Account와 같은 정보를 넘어 복합 객체를 이동시키기 위해 우리는 클라이언트 측에서 bean맵핑을 등록해야만 한다.

Note

서버측에서 Axis를 사용하여 등록된 bean맵핑은 server-config.wsdd에서 언제나 수행된다.

우리는 클라이언트 측에서 bean맵핑을 등록하기 위해 Axis를 사용할것이다. 이것을 하기 위해 우리는 Spring Bean factory의 하위클래스를 만들 필요가 있고 프로그램에 따라 bean맵핑을 등록한다.

public class AxisPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {

	protected void postProcessJaxRpcService(Service service) {
		TypeMappingRegistry registry = service.getTypeMappingRegistry();
		TypeMapping mapping = registry.createTypeMapping();
		registerBeanMapping(mapping, Account.class, "Account");
		registry.register("http://schemas.xmlsoap.org/soap/encoding/", mapping);
	}

	protected void registerBeanMapping(TypeMapping mapping, Class type, String name) {
		QName qName = new QName("http://localhost:8080/account/services/accountService", name);
		mapping.register(type, qName,
		    new BeanSerializerFactory(type, qName),
		    new BeanDeserializerFactory(type, qName));
	}

}

17.5.4. 자체적인 핸들러 등록하기

이 장에서 우리는 SOAP메시지를 정보를 통해 보내기 전에 코드를 사용자정의 할수 있는 웹 서비스 프록시를 위한 javax.rpc.xml.handler.Handler를 등록할 것이다. javax.rpc.xml.handler.Handler는 콜백 인터페이스이다. jaxrpc.jar내 제공되는 편리한 base클래스인 javax.rpc.xml.handler.GenericHandler가 있다.

public class AccountHandler extends GenericHandler {

    public QName[] getHeaders() {
        return null;
    }

    public boolean handleRequest(MessageContext context) {
        SOAPMessageContext smc = (SOAPMessageContext) context;
        SOAPMessage msg = smc.getMessage();

        try {
            SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
            SOAPHeader header = envelope.getHeader();
            ...
		
        } catch (SOAPException e) {
            throw new JAXRPCException(e);
        }

        return true;
    }

}

우리의 AccountHandler를 JAX-RPC 서비스에 등록하는 것이 필요하다. 그래서 메시지가 정보를 통해 전달되기 전에 handleRequest을 호출할것이다. Spring은 이 시점에 핸들러를 등록하기 위한 선언적인 지원을 가지지 않는다. 그래서 우리는 프로그램마다 다른 접근법을 사용해야만 한다. 어쨌든 Spring은 우리가 이 bean factory를 확장하고 postProcessJaxRpcService 메소드를 오버라이드 할수 있는 것처럼 이것을 쉽게 만든다.

public class AccountHandlerJaxRpcPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {

    protected void postProcessJaxRpcService(Service service) {
        QName port = new QName(this.getNamespaceUri(), this.getPortName());
        List list = service.getHandlerRegistry().getHandlerChain(port);
        list.add(new HandlerInfo(AccountHandler.class, null, null));

        logger.info("Registered JAX-RPC Handler [" + AccountHandler.class.getName() + "] on port " + port);
    }

}

그리고 마지막으로 우리는 factory bean을 사용하기 위해 Spring설정을 변경하는 것을 기억해야만 한다.

    <bean id="accountWebService" class="example.AccountHandlerJaxRpcPortProxyFactoryBean">
        ...
    </bean>    

17.5.5. XFire를 사용하여 웹 서비스를 드러내기

XFire는 Codehaus에서 호스팅되는 가벼운 SOAP라이브러리이다. 현 시점(2005년 3월)에, XFire는 여전히 개발중이다. 비록 Spring지원이 안정적이라고 하더라도 대부분의 기능은 나중에 추가될것이다. XFire를 드러내는 것은 당신이 WebApplicationContext에 추가할 RemoteExporter-스타일의 bean으로 조합된 XFire를 가진 XFire 컨텍스트를 사용하는 것이다.

당신이 서비스를 드러내는 것을 허용하는 모든 메소드처럼 당신은 드러낼 서비스를 포함하는 관련된 WebApplicationContext를 가진 DispatcherServlet을 생성해야 한다.

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

당신은 XFire설정을 링크해야만 한다. 이것은 ContextLoaderListener(또는 서블릿)가 가지는 contextConfigLocations 컨텍스트 파라미터에 컨텍스트 파일을 추가하는것이다. 설정 파일은 XFire jar파일내 위치하고 물론 애플리케이션의 클래스패스에 위치할수도 있다.

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
    classpath:org/codehaus/xfire/spring/xfire.xml
  </param-value>
</context-param>

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

당신이 서블릿 맵핑(위에서 선언된 XFire서블릿을 위한 /* 맵핑)을 추가한 후에 당신은 오직 XFire를 사용하는 서비스를 드러내기 위한 추가적인 bean을 추가해야만 한다. 예를 들어 당신은 xfire-servlet.xml을 다음에 추가하라.

<beans>
  <bean name="/Echo" class="org.codehaus.xfire.spring.XFireExporter">
    <property name="service">
      <ref bean="echo"/>
    </property>
    <property name="serviceInterface">
      <value>org.codehaus.xfire.spring.Echo</value>
    </property>
    <property name="serviceBuilder">
      <ref bean="xfire.serviceBuilder"/>
    </property>
    <!-- the XFire bean is wired up in the xfire.xml file you've linked in earlier
    <property name="xfire">
      <ref bean="xfire"/>
    </property>
  </bean>

  <bean id="echo" class="org.codehaus.xfire.spring.EchoImpl"/>
</beans>

XFire는 나머지를 다룬다. 이것은 당신의 서비스 인터페이스를 분석하고 이것으로 부터 WSDL을 생성한다. 이 문서의 일부는 XFire사이트로부터 가져왔다. XFire와 Spring통합에 대한 좀더 상세한 정보는 docs.codehaus.org/display/XFIRE/Spring를 보라.

17.6. 자동-탐지(Auto-detection)는 원격 인터페이스를 위해 구현되지 않는다.

구현된 인터페이스의 자동-탐지가 원격 인터페이스에는 발생하지 않는 가장 중요한 이유는 원격 호출자를 위해 너무 많은 문이 열리는 것을 피하는 것이다. 대상 객체는 호출자에게 드러내는 것을 원하지 않는 InitializingBean 이나 DisposableBean처럼 내부 콜백 인터페이스를 구현해야만 한다.

대상에 의해 구현된 모든 인터페이스를 가진 프록시를 제공하는 것은 로컬의 경우 언제나 문제가 되지 않는다. 하지만 원격 서비스를 내보낼때 당신은 원격 사용의 경향이 있는 특정 작업을 가진 특정 서비스 인터페이스를 보여야만 한다. 내부 콜백 인터페이스외에도 대상은 원격 노출의 경향이 있는 것중 하나를 가진 다중 비지니스 인터페이스를 구현해야만 한다. 이러한 이유로 우리는 명시되는 서비스 인터페이스를 요구한다.

이것은 설정의 편리함과 내부 메소드의 뜻하지 않는 노출의 위험사이의 거래이다. 서비스 인터페이스를 명시하는 것은 많은 노력이 필요하지 않고 당신을 특정 메소드의 제어된 노출에 관련된 안전적인 쪽에 두게된다.

17.7. 기술을 선택할때 고려사항.

여기에 표시된 각각 그리고 모든 기술은 결점을 가진다. 당신이 기술을 선택할때 당신이 드러내는 서비스와 당신이 정보를 통해 보낼 객체중 필요한 것을 주의깊게 검토해야만 한다.

RMI를 사용할때, 당신이 RMI 소통을 관통(tunneling)하지 않는 한 HTTP프로토콜을 통해 객체에 접근하는 것은 불가능하다. RMI는 정보를 통해 직렬화가 필요한 복합 데이터 모델을 사용할때 중요한 완전한 객체 직렬화를 지원하는 상당히 무거운 프로토콜이다. 어쨌든 RMI-JRMP는 자바 클라이언트에 묶인다. 이것은 자바-대-자바 원격 솔루션이다.

Spring의 HTTP호출자는 만약 당신이 HTTP-기반 원격이 필요하지만 자바 직렬화에 의존한다면 좋은 선택이다. 이것은 수송기처럼 HTTP를 사용하는 RMI호출자를 가진 기본 내부구조를 공유한다. HTTP호출자는 자바-대-자바 원격에 제한을 가지지 않을뿐 아니라 클라이언트측과 서버측 모두 제한을 가하지 않는다. (후자는 비-RMI인터페이스를 위해 Spring의 RMI호출자에 적용한다.)

Hessian 그리고/또는 Burlap은 명시적으로 비-자바 클라이언트를 허용하기 때문에 이종 환경내에서 작동할때 명백한 값을 제공한다. 어쨌든 비-자바 지원은 여전히 제한된다. 알려진 문제는 늦게 초기화하는 collection으로 조합된 Hibernate객체의 직렬화를 포함한다. 만약 당신이 그러한 데이타 모델을 가진다면 Hessian대신에 RMI나 HTTP호출자를 사용하는 것을 검토하라.

JMS는 서비스의 클러스터(clusters)를 제공하기 위해 유용할수 있고 로드 밸런싱, 발견(discovery) 그리고 자동 대체(failover)를 다루기 위해 JMS 브로커(broker)를 허용한다. 디폴트에 의해 자바 직렬화는 JMS원격을 사용하지만 JMS제공자가 서버가 다른 기술로 구현되는것을 허용하는 XStream과 같은 포맷팅을 묶기 위한 다른 기법을 사용할수 있을때 사용된다.

EJB는 표준적인 권한(role)-기반 인증과 인증, 그리고 원격 트랜잭션 위임을 지원하는 면에서 RMI를 능가하는 장점을 가진다. 이것은 비록 핵심 Spring에 의해 제공되지는 않지만 보안 컨텍스트 위임을 지원하는 RMI호출자나 HTTP호출자를 얻는것은 가능하다. 써드 파티나 사용자정의 솔루션내 플러그인하기 위한 선호하는 고리(hooks)가 있다. 


출처 - http://blog.naver.com/PostView.nhn?blogId=mullets214&logNo=100102493964






Posted by linuxism
,