Web项目中JAVA RMI实现

1. 服务器端程序

  1. 自定义远程接口
    在 Java RMI服务端,远程对象是自定义远程接口实现类的实例, 该自定义远程接口声明每个要远程调用的抽象方法。
    该接口特点:
    a、该接口必须继承java.rmi.Remote接口;
    b、该接口中的每个抽象方法必须抛出RemoteException异常或RemoteException 的父类异常;

    package com.jackmouse.rmi.email.service;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    /**
     * 邮件服务远程接口
     **/
    public interface IEmailService extends Remote {
    
    	/**
         * 发送邮件抽象方法实现
         **/
        boolean send(String from, String password, String title, String content, String to) throws RemoteException;
        
    }
    
  2. 自定义远程接口的实现类
    该实现类特点:

    1. 该实现类必须实现自定义远程接口内的每个远程抽象方法;
    2. 该实现类必须继承java.rmi.UnicastRemoteObject类。UnicastRemoteObject类可以让服务端远程对象与客户端建立一对一的连接;
    3. 由于UnicastRemoteObject类中默认构造方法抛出RemoteException异常,因此该实现类中默认的构造方法必须显示地写出来并且该构造方法必须声明抛出RemoteException异常,别忘了子类构造方法要与参数列表相同的父类构造方法一致,父类无参构造方法抛出了RemoteException异常,那么子类无参构造方法也需要抛出RemoteException异常;
    4. 该实现类也可以含有其它非远程接口定义的抽象方法或非接口方法(即实现类内部自定义的方法,这些方法不能使用@Override进行注释),但客户端不能调用这些新增的方法(别忘了,这些方法并不是自定义远程接口内的抽象方法)。
    package com.jackmouse.rmi.email.service;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    
    import com.jackmouse.local.messages.service.IMessagesService;
    import com.jackmouse.local.messages.service.MessagesService;
    
    /**
     * 邮件服务远程接口实现类
     **/
    public class EmailService extends UnicastRemoteObject implements IEmailService {
    
        private static final long serialVersionUID = 1L;
        
        private IMessagesService messagesService = new MessagesService();
    
        public EmailService() throws RemoteException {
    
        }
    
        /**
         * 发送邮件抽象方法实现
         **/
         //这里做邮件发送测试,邮件服务器地址填自己的邮箱账号的服务器地址
    	public boolean send(String from, String password, String title, String content, String to) throws RemoteException {
           boolean state = false;
        	try {
    			HtmlEmail htmlEmail = new HtmlEmail();
    			//邮件服务器的地址
    			htmlEmail.setHostName("qq.com");
    			//邮件服务器账号和密码
    			htmlEmail.setAuthentication(from, password);
    			//设置发件人:第一个参数为发件人地址;第二个参数为收件人收到邮件时看到的发件人“姓名”
    			htmlEmail.setFrom(from);
    			//设置收件人:第一个参数为收件人邮件地址;第二个参数为收件人收到邮件时看到的收件人“姓名”
    			htmlEmail.addTo(to);
    			//设置邮件内容编码方式
    			htmlEmail.setCharset("UTF-8");
    			//标题
    			htmlEmail.setSubject(title);
    			//邮件内容
    			htmlEmail.setHtmlMsg(content);//发送包含html标签的邮件
    			//发送邮件
    			htmlEmail.send();
    			state = true;
    		} catch (EmailException e) {
    			e.printStackTrace();
    		} finally {
    			return state;
    		}
        }
    }
    
  3. 定义继承ServletContextListener监听器的类EmailServiceListener,并在web.xml配置如下,使在tomcat启动时直接加载该监听器,执行contextInitialized中的代码,启动rmi服务器。

    <listener>
      	<listener-class>com.jackmouse.rmi.email.EmailServiceListener</listener-class>
    </listener>
    
    package com.jackmouse.rmi.email;
    
    import java.net.MalformedURLException;
    import java.rmi.AlreadyBoundException;
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import com.jackmouse.rmi.email.service.EmailService;
    import com.jackmouse.rmi.email.service.IEmailService;
    
    /**
     * 邮件服务监听器
     */
    public class EmailServiceListener implements ServletContextListener{
    
    	public void contextDestroyed(ServletContextEvent arg0) {
    		
    	}
    
    	public void contextInitialized(ServletContextEvent arg0) {
    		try {
    			//需要远程机器访问时,需要设置hostname为远程服务器的公网ip
    			System.setProperty("java.rmi.server.hostname","49.*.*.*");
                int registryPort = 8888;
                IEmailService emailService = new EmailService();
                LocateRegistry.createRegistry(registryPort);
                Naming.bind("rmi://localhost:" + registryPort + "/emailservice",emailService);
                System.out.println("RMI服务器启动成功!");
            } catch (RemoteException e) {
                System.err.println("远程对象创建失败!");
                e.printStackTrace();
            } catch (AlreadyBoundException e) {
                System.err.println("发生重复绑定远程对象异常!");
                e.printStackTrace();
            } catch (MalformedURLException e) {
                System.err.println("绑定的URL不正确!");
                e.printStackTrace();
            }
    	}
    
    }
    

2. 客户端程序

  1. 定义与服务器端一样的远程接口,包名也要相同,但不用再继承Remote,方法也不用抛出RemoteException
    package com.jackmouse.rmi.email.service;
    
    /**
     * 发送邮件服务远程接口
     **/
    public interface IEmailService{
    
        /**
         * 发送邮件抽象方法
         **/
    	boolean send(String from, String password, String title, String content, String to);
    }
    
  2. 进行测试
    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 = "XXXX@qq.com";//收件人邮箱账号
            String from = "XXXX@qq.com";//发件人邮箱账号
            String content="123";//邮件内容
    
            try {
                //依据服务名称通过Naming类的lookup方法获取RMI服务端特定的远程对象引用 ,为调用该对象中实现的接口中的方法奠定基础,其中lookup方法的参数标准格式为“rmi://host:registryPort/serviceName”,也可以“//host:registryPort/serviceName”。
            	IEmailService emailService = (IEmailService)Naming.lookup("rmi://127.0.0.1:8888/emailservice");
                System.out.println(emailService.send(from, password, title, content, to));
                System.out.println("发送成功");
            } catch (NotBoundException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
    
    运行后输出true即测试成功

3. 注意点

  1. 服务器端的远程接口要继承java.rmi.Remote接口,方法要抛出RemoteException或其父类异常
  2. 服务器端的远程接口实现类必须继承java.rmi.UnicastRemoteObject类。由于UnicastRemoteObject类中默认构造方法抛出RemoteException异常,因此该实现类中默认的构造方法必须显示地写出来并且该构造方法必须声明抛出RemoteException异常。
  3. 服务器端的ServletContextListener监听器的子类EmailServiceListener中有这么一句代码:
    System.setProperty("java.rmi.server.hostname","49.*.*.*");
    
    当做本地rmi测试时,不需要这行代码。
    当把rmi服务器的web项目放到远程服务器上时,需要设置hostname为远程服务器的公网ip。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
请移步:http://download.csdn.net/source/2881508 版本:1.0.0.1 完全兼容 前一个版本 升级时同时更新 RMVIEWP.CAB、rmview1.0.0.1.jar(删除前一个版本的jar包,名称为:RMVIEW.JAR) 使用方法不变,无缝升级。 更新日志: 1. 修正部分用户使用用到插件的分割符号,致使插件不能正常使用,本版间使用xml格式,不会和用户使用的符号有冲突。 2. 重新构件了ocx,jar两个地方的源码,使结构更加清晰。 注意事项: 1. 这个版本的功能和前一个版本的功能是一样的,如果运行得可以就可以不用更新 声明: 任何个人或组织可以自由使用,可以任意修改、复制、发布,但要保留本人的声明以遵重本人的劳动成果,并且不能用于任何商业目的。 本人提供的是免费报表,不与商家争长短,但希望对你有用: 使用方法: 范例使用的是access数据库,首先在odbc 注册ReportDemo.mdb 数据源,名字随你喜好, 然后修改classes文件下的 db.properties 的连接。 然后把项目放在tomcat下运行既可: 起作用的关键文件:RMVIEWP.CAB 文件,客户端插件 Lib下的两个包:rmview1.0.0.1.jar,commons-logging.jar 使用接口: package common.rmview; /* * 设计的第一步,首先定义字段的类型, * 然后通过AddRow将结果加入缓存 * */ import common.rmview.surperInterface.IDataSet; import common.rmview.until.Types; public interface IRMDataSet extends IDataSet { public void addField(String fieldName, Types.filedType type, int fieldLength, Boolean isNull);//1:将段类型加入 public void addField(String fieldName, Types type, int fieldLength);//1:将段类型加入,isNull 默认为 false public void AddRow(IRMDataRecord rmd);//2:在 IRMDataRecord实现类赋值完成一条记录后使用一次,循环加入. } package common.rmview; import common.rmview.surperInterface.IDataRecord; /* * 使用时的第二步 * 通过这个接口设置结果集 */ public interface IRMDataRecord extends IDataRecord { public void SetValue(String fieldName,Object objValue); } package common.rmview; /* * 第三步: * 前面IDataSet,IRMDataRecord实现类完成后,通过此接口的实现类向html也面输出ie到ie以方便ocx的取值使用 */ public interface IRMEngine { final int rmf=1; final int rls=2; public void SetReportFile(String urlandFileName,int fileFormat);//1:设置报表路径及文件名称 public void AddClientDataSet(String dataSourceName,IRMDataSet rmd);//2:设置数据源名称以ocx使用,并把IRMDataSet实现的结果加入 public String CreateViewer();//3:生成在html页面的编码 } 具体的使用方法请参照 index.jsp 报表的使用方法请自己参照官方的文档 RMDesigner.exe 是个设计器(非本人开发,所有权属于其所在的组织),也可以使用delphi 的RM报表来设计 RM报表的设计请另行学习。 新建QQ群:29672297 有疑问请发邮件到 lujianfu123@yahoo.com.cn 下期计划:进行对 fastReport的封装。不过也要看呼声如何再决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值