java框架简介4----Spring+Hessian 远程过程调用

Spring+Hessian简介:

Hessian能够完成RMI就是远程过程调用,实际上Hessian自己就可以完成这个功能,但是我的目的是将与Spring相关的框架与Spring结合起来,一起完成任务,所有不单独拿出一个章节来讲Hessian。不够,使用方式都是相通的。

 

这次需要完成的任务是这样的,假设在远程有一个作业需要执行,我们写一个客户端,并将这个客户端安装到远程主机上,然后再本机上远程调用客户端的服务,让客户端执行远程主机的作业任务。

 

从上面的分析可知,我们需要完成两个服务,一个是远程执行主机的服务,一个是本地的调用服务。整个程序的结构如下:

远程执行主机服务:

需要用到的jar包:

 

本地执行主机目录:

 

需要的jar包:

 

 

第一步:编写远程主机服务:

要在远程主机上执行作业必然需要对需要执行的作业进行描述,这里对作业的描述如下:

package com.guan.springHessianClientTest.logicModel;

 

import java.io.File;

import java.io.Serializable;

 

public class Job implements Serializable{

    /**

     * 注意作业必须要实现Serializable接口,很明显,作业作为参数在两个主机间传递,必然要进行串行化。Hessian是以二进制的形式进行传输的。

     */

    private static final long serialVersionUID = 1L;

    private String executable;//可执行文件的名字

    private File directory;//执行目录

    private String stdOutFile;//标准输出文档

    private String stdErrFile;//标准错误输出文档

    private String[] args;//程序执行参数

   

 

    public File getDirectory() {

       return directory;

    }

 

    public void setDirectory(File directory) {

       this.directory = directory;

    }

 

    public String getExecutable() {

       return executable;

    }

 

    public void setExecutable(String executable) {

       this.executable = executable;

    }

 

    public String[] getArgs() {

       return args;

    }

 

    public void setArgs(String[] args) {

       this.args = args;

    }

 

    public String getStdOutFile() {

       return stdOutFile;

    }

 

    public void setStdOutFile(String stdOutFile) {

       this.stdOutFile = stdOutFile;

    }

 

    public String getStdErrFile() {

       return stdErrFile;

    }

 

    public void setStdErrFile(String stdErrFile) {

       this.stdErrFile = stdErrFile;

    }

}

上面这个类是个实体类,不多说,大家都明白。

然后实现一个ServiceDao就是服务接口,对应Hessian来说,这个接口是必须的,因为Hessian建立的远程调用,在远程不能过直接对服务的实现调用,而是对服务的接口进行调用,后面还会分析其原因。

package com.guan.springHessianClientTest.ServiceDao;

 

import java.io.IOException;

 

import com.guan.springHessianClientTest.logicModel.Job;

 

public interface ExecuteServiceDao {

    public void submintJob(Job job) throws IOException;

}

 

这个接口很简单,就是提交作业到远程执行。

 

下面给出上面接口的实现:

package com.guan.springHessianClientTest.ServiceImpl;

 

import java.io.BufferedInputStream;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

 

import com.guan.springHessianClientTest.ServiceDao.ExecuteServiceDao;

import com.guan.springHessianClientTest.logicModel.Job;

 

public class ExecuteServiceDaoImpl implements ExecuteServiceDao{

 

    public void submintJob(Job job) throws IOException {

       Runtime runtime = Runtime.getRuntime();//执行时环境

       Process process = runtime.exec(job.getExecutable(),job.getArgs(),job.getDirectory());

       //开启一个进程来执行提交过来的程序

       BufferedInputStream in = new BufferedInputStream(process.getInputStream());//获得可执行程序的标准输出

       BufferedReader br = new BufferedReader(new InputStreamReader(in));//创建一个reader读取标准输出

      

       BufferedInputStream err = new BufferedInputStream(process.getErrorStream());/*获得可执行程序标准错误输出*/

       BufferedReader berr = new BufferedReader(new InputStreamReader(err));

      

       PrintStream myout = new PrintStream(new FileOutputStream(new File(job.getStdOutFile()))); /*打开标准输出文件*/

       PrintStream myerr = new PrintStream(new FileOutputStream(new File(job.getStdErrFile())));/*打开标准错误输出文件*/

 

       String s;

       while ((s = br.readLine()) != null)

           myout.println(s);/*读取,然后输出到文件*/

       while ((s = berr.readLine()) != null)

           myerr.println(s);

    }

   

}

 

在执行程序的过程中,服务先开启一个进程来执行这个程序,然后将执行的结果输出到文件中。

 

接下来,需要配置远程调用的接口,首先要在web.xml中配置Spring的过滤器,这个可以参考我前面的Spring+Hibernate那篇文章。

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5"

    xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <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>

</web-app>

 

通过这个配置,很容易看到,凡是以/remoting开始的请求,都会被传递给Spring来处理。

下面要配置Spring

Remoting-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:aop="http://www.springframework.org/schema/aop"

      

       xsi:schemaLocation="http://www.springframework.org/schema/beans

           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

           http://www.springframework.org/schema/aop

           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

           http://www.springframework.org/schema/tx

           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

           http://www.springframework.org/schema/context

           http://www.springframework.org/schema/context/spring-context-2.5.xsd">     

        <bean id="excuteServiceDaoImpl" class="com.guan.springHessianClientTest.ServiceImpl.ExecuteServiceDaoImpl"/>

        <bean name="/executeManagerService" class="org.springframework.remoting.caucho.HessianServiceExporter">

               <property name="service" ref="excuteServiceDaoImpl"/>

               <property name="serviceInterface" value="com.guan.springHessianClientTest.ServiceDao.ExecuteServiceDao"/>

       </bean>

</beans>

首先创建了一个ExecuteServiceDaoImpl的实现,然后创建了一个远程调用的服务,这个服务中注入了ExecuteServiceDaoImpl的实现。并且说明了接口是ExecuteServiceDao。在远程需要获得这个远程调用的服务(/executeManagerService,注意呀,这个名字前有个/),然后使用接口来完成服务的访问。

 

第二部分 服务端本地调用的编写:

本地调用只写了个测试程序,需要直接从执行服务端拷贝modeldao。然后需要写一个Spring的配置文件,bean.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:aop="http://www.springframework.org/schema/aop"

      

       xsi:schemaLocation="http://www.springframework.org/schema/beans

           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

           http://www.springframework.org/schema/aop

           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

           http://www.springframework.org/schema/tx

           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

           http://www.springframework.org/schema/context

           http://www.springframework.org/schema/context/spring-context-2.5.xsd">

                    

       <bean id="myServiceClient" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">

       <property name="serviceUrl">

          <value>http://localhost:8080/SpringHessianClientTest/remoting/executeManagerService</value>

       </property>

       <property name="serviceInterface">

           <value>com.guan.springHessianClientTest.ServiceDao.ExecuteServiceDao</value>

       </property>

       </bean>

</beans>

先创建一个Servicebean,并指明这个Serviceurl是刚才我们配置那个服务的url,注意我是本机测试,所以使用localHost,并且我的tomcat配置的是8080端口,如果执行服务放在远程主机上,那么要将localHost更换成其ip地址。然后指明要使用的接口是什么。

 

注意在提交端,并没有拷贝服务的实现,只是拷贝了服务的接口。

最后的测试部分代码如下:

package com.guan.springHessianClientTest.RomoteService;

 

import java.io.File;

import java.io.IOException;

 

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import com.guan.springHessianClientTest.ServiceDao.ExecuteServiceDao;

import com.guan.springHessianClientTest.logicModel.Job;

 

public class RMIServiceTest {

    @Test

    public void remoteTest() throws IOException

    {

        ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");//分析Spring配置文档

        ExecuteServiceDao studentService = (ExecuteServiceDao) appContext.getBean("myServiceClient");//获取配置的bean

        Job job = new Job();//新创建一个job,并进行配置

        job.setExecutable("F://programs//vs6.0//redirectionTest//Debug//redirectionTest.exe");

        job.setDirectory(new File("F://programs//NFSWorkSpace"));

        job.setStdErrFile("F://test.err");

        job.setStdOutFile("F://test.out");

        studentService.submintJob(job);//直接调用完成执行

    }

}

 

从上面的例子我们可以看出,整个执行过程就像在本机执行一样,是不是很方便呀!!

测试的程序redirectionTest是用c++写的,代码如下:

#include <iostream>

 

using std::cin;

using std::cout;

using std::endl;

using std::cerr;

 

void main()

{

         cout<<"hello world!!"<<endl;

         cout<<"您好!!!"<<endl;

         cout<<"good good "<<endl;

         cerr<<"err message"<<endl;

         cout<<"after err message"<<endl;

         cerr<<"second errmessage"<<endl;

}

 

最后结果是:在F盘生成两个文件

Test.err

err message

second errmessage

 

Test.out

hello world!!

您好!!!

good good

after err message

 

实际上这已经是个小的网格的概念,作业调度系统在远程调度作业到执行主机去执行作业。

 

远程过程调用就像您在本地调用方法一样轻松的完成您的任务,这是一个好方法。

 

如果您在提交端不想使用Spring,可以用下面的方法,似乎更简练些:

      

        String url = " http://localhost:8080/SpringHessianClientTest/remoting/executeManagerService ";

        HessianProxyFactory factory = new HessianProxyFactory();

        ExecuteServiceDao executeServiceDao= (ExecuteServiceDao) factory.create(ExecuteServiceDao.class, url);

      

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值