本篇博文遠程接口及其實現類代碼不再放上來,參考博文Web項目中JAVA RMI實現中的代碼
一、服務器端代碼
- 建立遠程接口,該接口不用再像JAVA RMI中繼承Romote類了。
- 建立遠程接口的實現類,該類不用再像JAVA RMI中繼承java.rmi.UnicastRemoteObject類,構造方法也不需要創建。
- 配置spring配置文件application.xml文件如下:
<!--遠程接口實現類--> <bean id="emailService" class="com.jackmouse.rmi.email.service.EmailService"/> <bean id="serviceExporter" class="org.springframework.remoting.rmi.RmiServiceExporter"> <!--服務名--> <property name="service" ref="emailService"></property> <!--serviceName屬性用來在RMI註冊表中註冊一個服務--> <property name="serviceName" value="email"></property> <property name="serviceInterface" value="com.jackmouse.rmi.email.service.IEmailService"/> <property name="registryPort" value="8888"></property> </bean>
- web.xml中配置DispatcherServlet並設置contextConfigLocation值爲application.xml
- 發佈項目
二、客戶端代碼
- 創建與服務器端相同的遠程接口
- 配置spring配置文件application.xml文件如下:
<bean id="emailService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> // <property name="serviceUrl" value="rmi://127.0.0.1:8888/email"/> <property name="serviceInterface" value="com.jackmouse.rmi.email.service.IEmailService"/> <!-- 預查找遠程對象 默認爲true --> <property name="lookupStubOnStartup" value="false"/> <!-- 是否刷新遠程調用緩存的stub --> <property name="refreshStubOnConnectFailure" value="true"></property> </bean>
- 測試類
package packageofrmi; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import com.jackmouse.rmi.email.service.IEmailService; /** * 客戶端測試 */ public class TestClient { public static void main(String[] args) { String title = "rmi測試";//郵件主題 String password = "XXX";//發件人密碼 String to = "[email protected]";//收件人郵箱賬號 String from = "[email protected]";//發件人郵箱賬號 String content="123";//郵件內容 ApplicationContext ctx =new ClassPathXmlApplicationContext("application.xml"); IEmailService emailService = (IEmailService)ctx.getBean("email"); System.out.println(emailService.send(from,password,title,content,to)); } }
三、注意點
當rmi服務器在遠程服務器時,如果遠程服務器有多個網卡,就需要指定某個ip。
服務器端需要像JAVA RMI中創建ServletContextListener監聽器的子類EmailServiceListener並在contextInitialized方法中寫入如下代碼
System.setProperty("java.rmi.server.hostname","49.*.*.*");
但是在spring中可以通過配置MethodInvokingFactoryBean進行靜態注入來配置某些系統配置,所以在application.xml中加入如下配置即可代替以上代碼的作用
<!--靜態注入服務器的hostname-->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" value="#{@systemProperties}" />
<property name="targetMethod" value="putAll" />
<property name="arguments">
<props>
<prop key="java.rmi.server.hostname" >遠程服務器的公網ip</prop>
</props>
</property>
</bean>
#{@systemProperties}等效於java.lang.System.getProperties()方法返回的Properties對象。
這個配置的通俗理解:在bean的生命週期的初始化階段,通過SpEL表達式,引用systemProperties的bean,通過MethodInvokingFactoryBean調用引用bean的putAll方法,將所配置的屬性(moaLogPath、moaPort…等),注入到System的Properties中。