Java
20 April 2011

Spring Remoting — Spring + RMI

Spring Remoting

Spring framework предоставляет обширные возможности по созданию распределенных приложений. Он не только помогает создавать удаленные службы, но и упрощает доступ к ним. На данный момент в с помощью фреймворка можно организовывать удаленный доступ с помощью большого количества технологий — Caucho’s Hessian и Burlap, собственная реализация удаленного доступа через HTTP, RMI и т.д. Под катом краткий обзор возможностей фреймворка Spring для создания распределенных приложений с помощью RMI.



Spring Remoting



Вернемся к примеру, начатому в прошлой статье.

Был рассмотрен интерфейс Action, представляющий математическую операцию и две его реализации ActionAdd и ActionMultiply:

public interface Action {
    long performAction(long op1, long op2);
    String getName();
}

public class ActionAdd implements Action {
    @Override
    public long performAction(long op1, long op2) {
        return op1 + op2;    
    }

    @Override
    public String getName() {
        return " + ";
    }
}

public class ActionMultiply implements Action {
    @Override
    public long performAction(long op1, long op2) {
        return op1 * op2;
    }

    @Override
    public String getName() {
        return " * ";
    }
}


И интерфейс ICalculator с реализацией Calculator:

public interface ICalculator {
    public void setAction(Action act);
    public String calc(String[] args);
}

public class Calculator implements ICalculator {
    private Action action;

    @Override
    public void setAction(Action action) {
        this.action = action;
    }

    @Override
    public String calc(String[] args) {
        long op1 = Long.parseLong(args[0]);
        long op2 = Long.parseLong(args[1]);
        return op1 + action.getName() + op2 + " = " + action.performAction(op1, op2);
    }
}


Объекты помещались в IoC контейнер spring:

<beans>
    <bean id="multiply" class="springtest.operations.ActionMultiply" />
    <bean id="add" class="springtest.operations.ActionAdd" />
    
    <bean id="calculator" class="springtest.calculator.Calculator">
        <property name="action" ref="add" />
    </bean>
</beans>


И из контейнера извлекался уже созданный объект:

ICalculator calc = (ICalculator) factory.getBean("сalculator");
System.out.print(calc.calc(new String[] {"30", "60"}));


Распределение.



Теперь принято решение наше приложение сделать распределенным – один компьютер не справляется с большой вычислительной нагрузкой. Java предоставляет для таких случаев RMI — Remote Method Invocation, программный интерфейс вызова удаленных методов, с помощью которого не так сложно это сделать. Но используя Spring Remoting все получается более чем просто.

Для создания RMI сервера все, что нам нужно, это объявить в контейнере специальный bean – RMI Service:

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
    <property name="serviceName" value="Calculator"/>
    <property name="service" ref="calculator"/>
    <property name="serviceInterface" value="springtest.calculator.ICalculator"/>
    <property name="registryPort" value="1199"/>
</bean>


Стартуем сервер нашего распределенного приложения:

public class ActionServer {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("xml-beans.xml");
    }
}


Считывая XML файл, Spring сам сделает все необходимое. Запускаем.

Mar 24, 2011 5:14:24 PM org.springframework.remoting.rmi.RmiServiceExporter getRegistry
INFO: Looking for RMI registry at port '1199'
Mar 24, 2011 5:14:24 PM org.springframework.remoting.rmi.RmiServiceExporter sourcepare
INFO: Binding service 'Calculator' to RMI registry: RegistryImpl_Stub[UnicastRef [liveRef: 
      [endpoint:[127.0.1.1:1199](remote),objID:[0:0:0, 0]]]]


Сервер готов.

Теперь нужно сделать клиента. Создадим класс ClientCalculator, представляющий собой обертку для калькулятора:

public class ClientCalculator {
    private ICalculator calculator;

    public void setCalculator(ICalculator calculator) {
        this.calculator = calculator;
    }

    public ICalculator getCalculator() {
        return calculator;
    }
}


Теперь для клиентского приложения создаем свой IoC XML контейнер:

<beans>
    <bean id="clientCalculator" class="springrmi.client.ClientCalculator">
        <property name="calculator" ref="remoteCalculator"/>
    </bean>
    
    <bean id="remoteCalculator" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
        <property name="serviceUrl" value="rmi://localhost:1199/Calculator"/>
        <property name="serviceInterface" value="springtest.calculator.ICalculator"/>
    </bean>
</beans>


Для создания и использования удаленных объектов используется RmiProxeFactoryBean, который возвращает необходимый интерфейс. И передает его только что созданной обертке clientCalculator.

Создаем класс клиента и проверяем:

public class Client {
    public static void main(String[] args) {
        ApplicationContext factory = new ClassPathXmlApplicationContext("springrmi/client/client-beans.xml");
        ClientCalculator calc = (ClientCalculator) factory.getBean("clientCalculator");
        System.out.print(calc.getCalculator().calc(new String[] {"30", "60"}));
    }
}


30 + 60 = 90


Все, готово. Мы получили распределенное приложение.

Исходник:
http://narod.ru/disk/8319633001/springrmi.tar.gz.html

Используемые источники:
http://static.springsource.org/spring/docs/2.0.x/reference/remoting.html

Кроме RMI, в Spring Remoting так же есть поддержка и других сервисов. Для дальнейшего чтения рекомендую обратиться к указанной выше ссылке.

+24
13.1k 49
Comments 5