엊그제 인가 작성한 spring rmi 포스트에 이어서..
친구가 얘기한 http invoker도 한번 해보았다..
이쪽은 이상하게 웹에 예제가 많지 않더라... 음.. 왜 그러지..
일단, http invoker는 stream을 사용하여 객체를 주고 받는 형식으로 되어 있는 듯 하다.
httpclient.. 예전에 풍대리님께서 가르쳐주신 그러한 비슷한 방법을 사용하는 듯..
일단 해보는 것이 목적이기 때문에..
작성을 해보았다.
service 제공 측. (server)
public interface HttpInvokerSearchService {
Log logger = LogFactory.getLog(HttpInvokerSearchService.class);
HashMap<String,String> search(String keyword);
}
public class HttpInvokerSearchServiceImpl implements HttpInvokerSearchService {
Log logger = LogFactory.getLog(HttpInvokerSearchServiceImpl.class);
@Override
public HashMap<String,String> search(String keyword) {
logger.warn("call service keyword : " + keyword);
HashMap<String,String> resultMap = new HashMap<String,String>();
resultMap.put("result", keyword);
return resultMap;
}
}
직렬화를 구현 할 필요가 없다.
http invoker를 사용하게 위해서는 서비스를 제공하는 측에 dispatcherservlet을 하나 더 생성 한다.
물론 기존의 dispatcher servlet에 합쳐도 작동은 한다.
<!-- http invoker -->
<servlet>
<servlet-name>httpinvoker</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/actions/httpinvoker*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/http/*</url-pattern>
</servlet-mapping>
<!--// http invoker -->
이렇게 dispatcherservlet을 하나더 생성하고, 해당 경로에 httpinvoker-config.xml 이라는 파일을 작성한다.
<!-- Http Invoker -->
<bean id="httpInvokerService"
class="gseshop.u2search.service.HttpInvokerSearchServiceImpl">
</bean>
<bean name="/HttpSearchService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="httpInvokerService" />
<property name="serviceInterface" value="gseshop.u2search.service.HttpInvokerSearchService" />
</bean>
<!-- // Http Invoker -->
디폴트로 org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping를 사용하게 될 것이다.
만약에 기존의 dispatcherserlvet에 추가 하고 싶다면 web.xml에
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/http/*</url-pattern>
</servlet-mapping>
<!--// http invoker -->
이렇게 추가하고, action-config.xml에 위(httpinvoker-config.xml 의) 설정을 해주면된다. 이 경우에 uri가 bean name="/HttpSearchService" 로 mapping 이 될 수 있도록 BeanNameUrlHandlerMapping를 사용하여 mapping 해주어야 한다.
이미 사용하고 있는 HandlerMapping이 있다면
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="order" value="2" />
</bean>
이렇게 설정해 주자.
이렇게 해주면 서버측에서 해야 할 작업은 끝났다.
이 서버측 서비스 호출은 http://local:port/app-name/http/HttpSearchService 로 호출되게 된다.
Client측.
서비스를 요청하는 측에 대한 작업을 해보자..
일단 위에서 작성한 인터페이스(HttpInvokerSearchService.java)를 가지고 있어야 한다. (Spring RMI와 같은 이유로..)
원격 서비스를 call하는 client측 은 아래와 같다.
public class HttpInvokerSearchServiceClient {
Log logger = LogFactory.getLog(HttpInvokerSearchServiceClient.class);
private HttpInvokerSearchService serverService;
@Autowired
public void setServerService(HttpInvokerSearchService serverService) {
this.serverService = serverService;
}
public HashMap<String,String> doSomething(String keyword) {
HashMap<String,String> resultMap = serverService.search(keyword);
logger.info("RESULT : " + resultMap);
return resultMap;
}
}
위에서 Autowired로 set 해주고 있는 클래스가 서버측에서 제공된 인터페이스이다.
이를 위한 설정은 아래와 같다.
<!-- spring http invoker client -->
<bean id="searchServiceHttpInvokerProxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8889/http/HttpSearchService"/>
<property name="serviceInterface" value="gseshop.u2si.service.HttpInvokerSearchService"/>
</bean>
<bean id="httpInvokerSearchServiceClient" class="gseshop.u2si.service.HttpInvokerSearchServiceClient" >
<property name="serverService" ref="searchServiceHttpInvokerProxy" />
</bean>
<!--// spring http invoker client -->
httpInvokerSearchServiceClient가 가지고 있는 HttpInvokerSearchService객체를 injection 하기 위한 설정이다. 위 설정을 통해서 HttpInvokerSearchService 클래스를 통하여 원격에 있는 메서드를 호출 할 수 있게 된다.
간단한 테스트 클래스를 만들어보면..
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:config/applicationContext.xml",
"classpath:actions/action-config.xml",
"classpath:services/serviceContext-sample.xml" })
public class HttpInvokeSearchServiceClientTest {
Log logger = LogFactory.getLog(HttpInvokeSearchServiceClientTest.class);
@Autowired
private HttpInvokerSearchServiceClient httpInvokerSearchServiceClient;
@Test
public void testService() {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HashMap<String, String> resultMap = httpInvokerSearchServiceClient.doSomething("TEST NIKE");
logger.info("Test Result : " + resultMap);
assertEquals(resultMap.get("result"),"TEST NIKE");
}
}
이렇게 해서 위에서 설정한 httpInvokerSearchServiceClient를 injection하여 원격 메서드를 호출해 볼 수 있다.
일단 클라이언트측에서 해야 할 일이 많지 않고..
rmi보다 가벼운거 같다. 하지만 어디서 본거 같은데...
양측이 모두 spring을 사용하고 있어야지만 사용 할 수 있다고 한다.