=> 장점은, 클라이언트 코드가 RMI 서비스를 처리한다는 것을 아예 몰라도 되며, 단지 주입된 Serivce 객체만을 받을 뿐
RMI는 원격 서비스 통신으로는 훌륭하지만 여러 단점이 있다.
방화벽을 넘어 작업하는 환경에서는 한계가 있음(대체로 임의 포트를 사용)...
인트라넷은 상관없지만, 인터넷상에서는 문제가 된다(터널링 작업이 까다로움)
RMI는 자바기반이기 때문에, 클라이언트 서비스 둘 다 자바로 작성해야함(자바의 직렬화를 사용하므로, 양쪽의 객체타입이 동일해야함)
===> 이러한 단점을 해결하기 위해 Hessian과 Burlap 을 이용한다.
3. Hessian과 Burlap을 이용한 리모트 서비스 노출
Hessian, Burlap은 Http를 통해, 가벼운 원격서비스를 가능케 한다. 웹서비스 단순화를 목표로 함
Hessian : RMI와 유사하게, 클라이언트와 서비스간에, 바이너리 메시지를 이용해 통신함 - PHP, Python, C++등 자바 외의 언어에 이식됨
Burlap : XML기반 리모팅 기술, XML을 파싱 가능한 언어라면, 자동적으로 이식 가능하다. 메시지 구조가 매우 간단
-> 두가지 기술은 대부분 동일함. 바이너리메시지와, XML의 차이이다.
3.1 Hessian과 Burlap을 이용한 빈 기능 노출
Hessian 서비스 익스포트
스프링에서 Hessian 서비를 익스포트하는 것은, RMI와 비슷함. HessianServiceExporter를 사용하면 됨 => 서비스에 대해서는 RmiServiceExporter와 동일한 기능 ==> 그러나, 방식은 약간 다르다
HessianServiceExporter는 Hessian의 요청을 받아, POJO의 메소드 호출로 변환하는 스프링 MVC 컨트롤러
@Bean
public HessianServiceExporter hessianExportedSpitterService(SpitterService service) {
HessianServiceExporter exporter = new HessianServiceExporter();
exporter.setService(service); // * RmiSerivceExporter와 마찬가지로, 서비스로 구현하는 빈에 대한 레퍼런스가 연결
exporter.setServiceInterface(SpitterService.class);
return exporter;
}
* 레지스트리를 갖지 않으므로, serviceName 프로퍼티는 필요가 없음
Hessian 컨트롤러 구성하기
RMI와 Hessian의 주된 차이점은, Hessian이 HTTP기반이기에, HessianServiceExporter가 스프링 MVC로 구현된다는 점.. 따라서 두가지의 설정이 필요하다.
* DispatcherServlet 설정 -> Hessian 서비스를 URL을 적젌한 서비스 빈으로 디스패치하도록 URL 핸들러 설정
/* WebApplicationInitalizer 사용 시 */
ServletRegistration.Dynamic dispatcher = container.addServlet(
"appServlet", new DispatcherServlet(dispatcherServletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
dispatcher.addMapping("*.service"); // Hessian서비스를 처리하기 위해 *.service URL패턴 서블릿 매핑 추가
/* AbstractDispatcherServletInitializer 또는 AbstractAnnotationConfigDispatcherServletInitializer 사용 시 */
@Override
protected String[] getServletMappings() {
return new String[] { "/", "*.service" }; // URL패턴 서블릿 매핑 추가
}
==> Spittle.service에 관한 매핑은 궁극적으로 hessianSpittleService빈(SpittleServiceImpl의 프록시)에 의해 처리
@Bean
public HandlerMapping hessianMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
Properties mappings = new Properties();
mappings.setProperty("/spitter.service",
"hessianExportedSpitterService");
mapping.setMappings(mappings);
return mapping;
}
* 해당 SimpleUrlHandlerMaping이 실제 URL매핑을 처리하게 된다.
Burlap 서비스 익스포트
BurlapServiceExporter는 XML을 처리하는 것 빼고는 Hessian과 모든 측면에서 동일
@Bean
public BurlapServiceExporter burlapExportedSpitterService(SpitterService service) {
BurlapServiceExporter exporter = new BurlapServiceExporter();
exporter.setService(service);
exporter.setServiceInterface(SpitterService.class);
return exporter;
}
* 유일한 차이점은, 빈의 메소드와, exporter 클래스 ===> 컨트롤러 설정은 동일하다(생략)
3.2 Hessian/Burlap 서비스에 액세스하기
RmiProxyFactoryBean처럼 프록시를 이용하여, Spitter 서비스를 소비하는 클라이언트 코드가 Hessian/Burlap인지 모르게 할 수 있다.
HessianProxyFactoryBean / BurlapProxyFactoryBean 사용
/* Hessian */
@Bean
public HessianProxyFactoryBean spitterService() {
HessianProxyFactoryBean proxy = new HessianProxyFactoryBean();
proxy.setServiceUrl("http://localhost:8080/Spitter/spitter.service");
proxy.setServiceInterface(SpitterService.class);
return proxy;
}
/* Burlap */
@Bean
public BurlapProxyFactoryBean spitterService() {
BurlapProxyFactoryBean proxy = new BurlapProxyFactoryBean();
proxy.setServiceUrl("http://localhost:8080/Spitter/spitter.service");
proxy.setServiceInterface(SpitterService.class);
return proxy;
}
* Hessian/Burlap은 Http를 기반으로 하므로, 방화벽 문제를 겪지 않음
* 하지만 복잡한 데이터모델의 경우, 직렬화 모델이 충분치 않을 수 있음(RMI가 우위)
==> RMI(자바의 직렬화 사용)와 Hessian/Burlap(방화벽 문제 없음)의 장점을 섞은 스프링의 HTTP호출자가 존재
4. 스프링의 HttpInvoker 사용하기
방화벽을 가로질러 사용 + 독자적인 객체 직렬화 매커니즘 => 스프링 Http 호출자(invoker) => HttpInvoker
4.1 빈을 HTTP 서비스로 익스포트
* HttpInvokerServiceExporter를 이용
@Bean
public HttpInvokerServiceExporter httpExportedSpitterService(SpitterService service) {
HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
exporter.setService(service);
exporter.setServiceInterface(SpitterService.class);
return exporter;
}
* 동작 자체도, HessianServiceExporter와 유사하다(스프링 MVC 컨트롤러)