• RMI简单实例与Spring集成RMI


         rmi远程方法调用,用于服务器端和客户端之间的会话通信。

          本文以两种方式实现rmi,一种为单独的rmi实例 一种为spring中集成rmi    记录学习的脚步

        1.rmi与jpa的融合

    /*
     * 自己编写rmi的话 只需三步 前两步针对服务器端 第三步针对客户端
     * 1.让远程服务实现类继承UnicastRemoteObject  并让远程服务接口继承Remote
     * 2.使用LocateRegistry.createRegistry注册RMI的服务端口 Naming.rebind绑定远程服务对象
     * 3.客户端通过Naming.lookup查找远程服务对象
     * 
     */

    远程服务接口类 IStusDAO.java 继承Remote类

    package com.undergrowth.rmi;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    import java.sql.Timestamp;
    import java.util.List;
    
    import com.undergrowth.bean.Stus;
    
    /**
     * Interface for StusDAO.
     * 
     * @author MyEclipse Persistence Tools
     */
    
    public interface IStusDAO extends Remote{
    	/**
    	 * Perform an initial save of a previously unsaved Stus entity. All
    	 * subsequent persist actions of this entity should use the #update()
    	 * method. This operation must be performed within the a database
    	 * transaction context for the entity's data to be permanently saved to the
    	 * persistence store, i.e., database. This method uses the
    	 * {@link javax.persistence.EntityManager#persist(Object)
    	 * EntityManager#persist} operation.
    	 * 
    	 * <pre>
    	 * EntityManagerHelper.beginTransaction();
    	 * IStusDAO.save(entity);
    	 * EntityManagerHelper.commit();
    	 * </pre>
    	 * 
    	 * @param entity
    	 *            Stus entity to persist
    	 * @throws RuntimeException
    	 *             when the operation fails
    	 */
    	public void save(Stus entity) throws RemoteException;
    
    	/**
    	 * Delete a persistent Stus entity. This operation must be performed within
    	 * the a database transaction context for the entity's data to be
    	 * permanently deleted from the persistence store, i.e., database. This
    	 * method uses the {@link javax.persistence.EntityManager#remove(Object)
    	 * EntityManager#delete} operation.
    	 * 
    	 * <pre>
    	 * EntityManagerHelper.beginTransaction();
    	 * IStusDAO.delete(entity);
    	 * EntityManagerHelper.commit();
    	 * entity = null;
    	 * </pre>
    	 * 
    	 * @param entity
    	 *            Stus entity to delete
    	 * @throws RuntimeException
    	 *             when the operation fails
    	 */
    	public void delete(Stus entity) throws RemoteException;
    
    	/**
    	 * Persist a previously saved Stus entity and return it or a copy of it to
    	 * the sender. A copy of the Stus entity parameter is returned when the JPA
    	 * persistence mechanism has not previously been tracking the updated
    	 * entity. This operation must be performed within the a database
    	 * transaction context for the entity's data to be permanently saved to the
    	 * persistence store, i.e., database. This method uses the
    	 * {@link javax.persistence.EntityManager#merge(Object) EntityManager#merge}
    	 * operation.
    	 * 
    	 * <pre>
    	 * EntityManagerHelper.beginTransaction();
    	 * entity = IStusDAO.update(entity);
    	 * EntityManagerHelper.commit();
    	 * </pre>
    	 * 
    	 * @param entity
    	 *            Stus entity to update
    	 * @return Stus the persisted Stus entity instance, may not be the same
    	 * @throws RuntimeException
    	 *             if the operation fails
    	 */
    	public Stus update(Stus entity) throws RemoteException;
    
    	public Stus findById(String id) throws RemoteException;
    
    	/**
    	 * Find all Stus entities with a specific property value.
    	 * 
    	 * @param propertyName
    	 *            the name of the Stus property to query
    	 * @param value
    	 *            the property value to match
    	 * @param rowStartIdxAndCount
    	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
    	 *            row index in the query result-set to begin collecting the
    	 *            results. rowStartIdxAndCount[1] specifies the the maximum
    	 *            count of results to return.
    	 * @return List<Stus> found by query
    	 */
    	public List<Stus> findByProperty(String propertyName, Object value,
    			int... rowStartIdxAndCount) throws RemoteException;
    
    	public List<Stus> findByStuName(Object stuName, int... rowStartIdxAndCount) throws RemoteException;
    
    	public List<Stus> findByStuAge(Object stuAge, int... rowStartIdxAndCount) throws RemoteException;
    
    	/**
    	 * Find all Stus entities.
    	 * 
    	 * @param rowStartIdxAndCount
    	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
    	 *            row index in the query result-set to begin collecting the
    	 *            results. rowStartIdxAndCount[1] specifies the the maximum
    	 *            count of results to return.
    	 * @return List<Stus> all Stus entities
    	 */
    	public List<Stus> findAll(int... rowStartIdxAndCount) throws RemoteException;
    }

    远程服务实现类 StusDAO.java 继承UnicastRemoteObject

    package com.undergrowth.rmi;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    import java.sql.Timestamp;
    import java.util.List;
    import java.util.logging.Level;
    import javax.persistence.EntityManager;
    import javax.persistence.Query;
    
    import com.undergrowth.bean.EntityManagerHelper;
    import com.undergrowth.bean.Stus;
    
    /**
     * A data access object (DAO) providing persistence and search support for Stus
     * entities. Transaction control of the save(), update() and delete() operations
     * must be handled externally by senders of these methods or must be manually
     * added to each of these methods for data to be persisted to the JPA datastore.
     * 
     * @see com.undergrowth.bean.Stus
     * @author MyEclipse Persistence Tools
     */
    public class StusDAO extends UnicastRemoteObject implements IStusDAO {
    	
    	public StusDAO() throws RemoteException {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    
    	// property constants
    	public static final String STU_NAME = "stuName";
    	public static final String STU_AGE = "stuAge";
    
    	private EntityManager getEntityManager() {
    		return EntityManagerHelper.getEntityManager();
    	}
    
    	/**
    	 * Perform an initial save of a previously unsaved Stus entity. All
    	 * subsequent persist actions of this entity should use the #update()
    	 * method. This operation must be performed within the a database
    	 * transaction context for the entity's data to be permanently saved to the
    	 * persistence store, i.e., database. This method uses the
    	 * {@link javax.persistence.EntityManager#persist(Object)
    	 * EntityManager#persist} operation.
    	 * 
    	 * <pre>
    	 * EntityManagerHelper.beginTransaction();
    	 * StusDAO.save(entity);
    	 * EntityManagerHelper.commit();
    	 * </pre>
    	 * 
    	 * @param entity
    	 *            Stus entity to persist
    	 * @throws RuntimeException
    	 *             when the operation fails
    	 */
    	public void save(Stus entity) throws RemoteException{
    		EntityManagerHelper.log("saving Stus instance", Level.INFO, null);
    		try {
    			getEntityManager().persist(entity);
    			EntityManagerHelper.log("save successful", Level.INFO, null);
    		} catch (RuntimeException re) {
    			EntityManagerHelper.log("save failed", Level.SEVERE, re);
    			throw re;
    		}
    	}
    
    	/**
    	 * Delete a persistent Stus entity. This operation must be performed within
    	 * the a database transaction context for the entity's data to be
    	 * permanently deleted from the persistence store, i.e., database. This
    	 * method uses the {@link javax.persistence.EntityManager#remove(Object)
    	 * EntityManager#delete} operation.
    	 * 
    	 * <pre>
    	 * EntityManagerHelper.beginTransaction();
    	 * StusDAO.delete(entity);
    	 * EntityManagerHelper.commit();
    	 * entity = null;
    	 * </pre>
    	 * 
    	 * @param entity
    	 *            Stus entity to delete
    	 * @throws RuntimeException
    	 *             when the operation fails
    	 */
    	public void delete(Stus entity) throws RemoteException{
    		EntityManagerHelper.log("deleting Stus instance", Level.INFO, null);
    		try {
    			entity = getEntityManager().getReference(Stus.class,
    					entity.getStuId());
    			getEntityManager().remove(entity);
    			EntityManagerHelper.log("delete successful", Level.INFO, null);
    		} catch (RuntimeException re) {
    			EntityManagerHelper.log("delete failed", Level.SEVERE, re);
    			throw re;
    		}
    	}
    
    	/**
    	 * Persist a previously saved Stus entity and return it or a copy of it to
    	 * the sender. A copy of the Stus entity parameter is returned when the JPA
    	 * persistence mechanism has not previously been tracking the updated
    	 * entity. This operation must be performed within the a database
    	 * transaction context for the entity's data to be permanently saved to the
    	 * persistence store, i.e., database. This method uses the
    	 * {@link javax.persistence.EntityManager#merge(Object) EntityManager#merge}
    	 * operation.
    	 * 
    	 * <pre>
    	 * EntityManagerHelper.beginTransaction();
    	 * entity = StusDAO.update(entity);
    	 * EntityManagerHelper.commit();
    	 * </pre>
    	 * 
    	 * @param entity
    	 *            Stus entity to update
    	 * @return Stus the persisted Stus entity instance, may not be the same
    	 * @throws RuntimeException
    	 *             if the operation fails
    	 */
    	public Stus update(Stus entity) throws RemoteException{
    		EntityManagerHelper.log("updating Stus instance", Level.INFO, null);
    		try {
    			Stus result = getEntityManager().merge(entity);
    			EntityManagerHelper.log("update successful", Level.INFO, null);
    			return result;
    		} catch (RuntimeException re) {
    			EntityManagerHelper.log("update failed", Level.SEVERE, re);
    			throw re;
    		}
    	}
    
    	public Stus findById(String id) throws RemoteException{
    		EntityManagerHelper.log("finding Stus instance with id: " + id,
    				Level.INFO, null);
    		try {
    			Stus instance = getEntityManager().find(Stus.class, id);
    			return instance;
    		} catch (RuntimeException re) {
    			EntityManagerHelper.log("find failed", Level.SEVERE, re);
    			throw re;
    		}
    	}
    
    	/**
    	 * Find all Stus entities with a specific property value.
    	 * 
    	 * @param propertyName
    	 *            the name of the Stus property to query
    	 * @param value
    	 *            the property value to match
    	 * @param rowStartIdxAndCount
    	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
    	 *            row index in the query result-set to begin collecting the
    	 *            results. rowStartIdxAndCount[1] specifies the the maximum
    	 *            number of results to return.
    	 * @return List<Stus> found by query
    	 */
    	@SuppressWarnings("unchecked")
    	public List<Stus> findByProperty(String propertyName, final Object value,
    			final int... rowStartIdxAndCount) throws RemoteException{
    		EntityManagerHelper.log("finding Stus instance with property: "
    				+ propertyName + ", value: " + value, Level.INFO, null);
    		try {
    			final String queryString = "select model from Stus model where model."
    					+ propertyName + "= :propertyValue";
    			Query query = getEntityManager().createQuery(queryString);
    			query.setParameter("propertyValue", value);
    			if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
    				int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
    				if (rowStartIdx > 0) {
    					query.setFirstResult(rowStartIdx);
    				}
    
    				if (rowStartIdxAndCount.length > 1) {
    					int rowCount = Math.max(0, rowStartIdxAndCount[1]);
    					if (rowCount > 0) {
    						query.setMaxResults(rowCount);
    					}
    				}
    			}
    			return query.getResultList();
    		} catch (RuntimeException re) {
    			EntityManagerHelper.log("find by property name failed",
    					Level.SEVERE, re);
    			throw re;
    		}
    	}
    
    	public List<Stus> findByStuName(Object stuName, int... rowStartIdxAndCount) throws RemoteException{
    		return findByProperty(STU_NAME, stuName, rowStartIdxAndCount);
    	}
    
    	public List<Stus> findByStuAge(Object stuAge, int... rowStartIdxAndCount) throws RemoteException{
    		return findByProperty(STU_AGE, stuAge, rowStartIdxAndCount);
    	}
    
    	/**
    	 * Find all Stus entities.
    	 * 
    	 * @param rowStartIdxAndCount
    	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
    	 *            row index in the query result-set to begin collecting the
    	 *            results. rowStartIdxAndCount[1] specifies the the maximum
    	 *            count of results to return.
    	 * @return List<Stus> all Stus entities
    	 */
    	@SuppressWarnings("unchecked")
    	public List<Stus> findAll(final int... rowStartIdxAndCount) throws RemoteException{
    		EntityManagerHelper.log("finding all Stus instances", Level.INFO, null);
    		try {
    			final String queryString = "select model from Stus model";
    			Query query = getEntityManager().createQuery(queryString);
    			if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
    				int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
    				if (rowStartIdx > 0) {
    					query.setFirstResult(rowStartIdx);
    				}
    
    				if (rowStartIdxAndCount.length > 1) {
    					int rowCount = Math.max(0, rowStartIdxAndCount[1]);
    					if (rowCount > 0) {
    						query.setMaxResults(rowCount);
    					}
    				}
    			}
    			return query.getResultList();
    		} catch (RuntimeException re) {
    			EntityManagerHelper.log("find all failed", Level.SEVERE, re);
    			throw re;
    		}
    	}
    
    }

    注册远程服务对象 RmiServer.java

    package com.undergrowth.junit;
    
    import java.rmi.Naming;
    import java.rmi.registry.LocateRegistry;
    
    import com.undergrowth.rmi.IStusDAO;
    import com.undergrowth.rmi.StusDAO;
    
    /*
     * 自己编写rmi的话 只需三步 前两步针对服务器端 第三步针对客户端
     * 1.让远程服务实现类继承UnicastRemoteObject  并让远程服务接口继承Remote
     * 2.使用LocateRegistry.createRegistry注册RMI的服务端口 Naming.rebind绑定远程服务对象
     * 3.客户端通过Naming.lookup查找远程服务对象
     * 
     */
    
    public class RmiServer {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		try {
    			IStusDAO istusDAO=new StusDAO();
    			//System.setProperty("java.rmi.server.hostname", "192.168.38.172");
    			//创建访问rmi的远程端口
    			//启动rmiregister程序
    			//Runtime.getRuntime().exec("rmiregistry 4567");
    			LocateRegistry.createRegistry(4567);
    			//注册远程服务对象
    			Naming.rebind("rmi://192.168.38.172:4567/IStusDAO", istusDAO);
    			System.out.println("注册远程服务对象成功");
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    }
    

    在cmd下查看rmi绑定的端口



    客户端测试 RmiClient.java

    package com.undergrowth.junit;
    
    import java.rmi.Naming;
    import java.sql.Timestamp;
    import java.util.Calendar;
    import java.util.List;
    import java.util.UUID;
    
    import com.undergrowth.bean.Stus;
    import com.undergrowth.rmi.IStusDAO;
    
    public class RmiClient {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		try {
    			IStusDAO iStusDAO=(IStusDAO) Naming.lookup("rmi://192.168.38.172:4567/IStusDAO");
    			List<Stus> listStus=iStusDAO.findAll();
    			for (Stus stus : listStus) {
    				System.out.println(stus);
    			}
    			
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    }
    

    客户端输出

    Stus [stuId=014ED6D01D9B4C6E882E3624032FA9CD, stuName=sz, stuAge=21.0, stuBirthday=2014-04-19 15:07:33.0]
    Stus [stuId=946E460A4FA14D8496EF601E754FD314, stuName=gz, stuAge=20.0, stuBirthday=2014-04-19 15:07:33.0]

    2.spring集成rmi和jpa

    /*
     * spring支持的rmi很简单  
     * 不用服务接口继承Remote
     * 不用服务实现类继承UnicastRemoteObject
     * 也不用我们自己注册rmi的远程服务实现类
     * 
     * 服务器端 你需要做的仅仅是 写好你需要提供远程服务的实现类
     * 然后将其交给RmiServiceExporter类 RmiServiceExporter会将实现类发布为RMI服务
     * 
     * 客户端 也很简单
     * 只需要使用RmiProxyFactoryBean从服务器端的URL从获取服务对象  并进行封装给你定义的id
     * 然后从spring容器中获取RmiProxyFactoryBean封装的id即可
     * 
     * 此测试代码中 服务器和客户端都在一个项目中 也可换成多个项目 在不同的电脑中
     * 只需要在服务器的RmiServiceExporter中加入 p:registryHost="ip地址" 即可
     * 客户端将localhost换成ip地址即可
     */


    spring的配置文件 如下

    <?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:p="http://www.springframework.org/schema/p"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
    	xmlns:tx="http://www.springframework.org/schema/tx">
    
        <!-- spring 的jpa的事务管理  -->
    	<bean id="entityManagerFactory"
    		class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    		<property name="persistenceUnitName" value="SpringRmiAndJpa" />
    	</bean>
    	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    		<property name="entityManagerFactory" ref="entityManagerFactory" />
    	</bean>
    	<tx:annotation-driven transaction-manager="transactionManager" />
    	<bean
    		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
    	</bean>
    	<bean
    		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">
    	</bean>
    	
    	<bean id="IStusDAO" class="com.undergrowth.bean.StusDAO"></bean>
    	
    	<!-- 使用RmiServiceExporter将IStusDAO的对象导出为RMI服务对象 -->
    	<bean class="org.springframework.remoting.rmi.RmiServiceExporter" 
    	p:service-ref="IStusDAO"
    	p:serviceName="IStusDAO"
    	p:registryPort="1199"
    	p:serviceInterface="com.undergrowth.bean.IStusDAO"
    	/>
    	
    	<!-- 使用RmiProxyFactoryBean从远程服务处获取服务的对象 并将其封装成stusDao对象 -->
    	<bean id="stusDao" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"
    		p:serviceUrl="rmi://localhost:1199/IStusDAO"
    		p:serviceInterface="com.undergrowth.bean.IStusDAO"
    	/>
    	
    </beans>

    服务接口实现类 StusDAO.java

    package com.undergrowth.bean;
    
    import java.sql.Timestamp;
    import java.util.List;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.persistence.Query;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.stereotype.Repository;
    import org.springframework.transaction.annotation.Transactional;
    
    /**
     * A data access object (DAO) providing persistence and search support for Stus
     * entities. Transaction control of the save(), update() and delete() operations
     * can directly support Spring container-managed transactions or they can be
     * augmented to handle user-managed Spring transactions. Each of these methods
     * provides additional information for how to configure it for the desired type
     * of transaction control.
     * 
     * @see com.undergrowth.bean.Stus
     * @author MyEclipse Persistence Tools
     */
    @Transactional
    @Repository
    public class StusDAO implements IStusDAO {
    	private static final Log logger = LogFactory.getLog(StusDAO.class);
    	// property constants
    	public static final String STU_NAME = "stuName";
    	public static final String STU_AGE = "stuAge";
    
    	private EntityManager entityManager;
    
    	@PersistenceContext
    	public void setEntityManager(EntityManager entityManager) {
    		this.entityManager = entityManager;
    	}
    
    	private EntityManager getEntityManager() {
    		return entityManager;
    	}
    
    	/**
    	 * Perform an initial save of a previously unsaved Stus entity. All
    	 * subsequent persist actions of this entity should use the #update()
    	 * method. This operation must be performed within the a database
    	 * transaction context for the entity's data to be permanently saved to the
    	 * persistence store, i.e., database. This method uses the
    	 * {@link javax.persistence.EntityManager#persist(Object)
    	 * EntityManager#persist} operation.
    	 * <p>
    	 * User-managed Spring transaction example:
    	 * 
    	 * <pre>
    	 * TransactionStatus txn = txManager
    	 * 		.getTransaction(new DefaultTransactionDefinition());
    	 * StusDAO.save(entity);
    	 * txManager.commit(txn);
    	 * </pre>
    	 * 
    	 * @see <a href =
    	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
    	 *      container-managed transaction examples</a>
    	 * @param entity
    	 *            Stus entity to persist
    	 * @throws RuntimeException
    	 *             when the operation fails
    	 */
    	public void save(Stus entity) {
    		logger.info("saving Stus instance");
    		try {
    			getEntityManager().persist(entity);
    			logger.info("save successful");
    		} catch (RuntimeException re) {
    			logger.error("save failed", re);
    			throw re;
    		}
    	}
    
    	/**
    	 * Delete a persistent Stus entity. This operation must be performed within
    	 * the a database transaction context for the entity's data to be
    	 * permanently deleted from the persistence store, i.e., database. This
    	 * method uses the {@link javax.persistence.EntityManager#remove(Object)
    	 * EntityManager#delete} operation.
    	 * <p>
    	 * User-managed Spring transaction example:
    	 * 
    	 * <pre>
    	 * TransactionStatus txn = txManager
    	 * 		.getTransaction(new DefaultTransactionDefinition());
    	 * StusDAO.delete(entity);
    	 * txManager.commit(txn);
    	 * entity = null;
    	 * </pre>
    	 * 
    	 * @see <a href =
    	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
    	 *      container-managed transaction examples</a>
    	 * @param entity
    	 *            Stus entity to delete
    	 * @throws RuntimeException
    	 *             when the operation fails
    	 */
    	public void delete(Stus entity) {
    		logger.info("deleting Stus instance");
    		try {
    			entity = getEntityManager().getReference(Stus.class,
    					entity.getStuId());
    			getEntityManager().remove(entity);
    			logger.info("delete successful");
    		} catch (RuntimeException re) {
    			logger.error("delete failed", re);
    			throw re;
    		}
    	}
    
    	/**
    	 * Persist a previously saved Stus entity and return it or a copy of it to
    	 * the sender. A copy of the Stus entity parameter is returned when the JPA
    	 * persistence mechanism has not previously been tracking the updated
    	 * entity. This operation must be performed within the a database
    	 * transaction context for the entity's data to be permanently saved to the
    	 * persistence store, i.e., database. This method uses the
    	 * {@link javax.persistence.EntityManager#merge(Object) EntityManager#merge}
    	 * operation.
    	 * <p>
    	 * User-managed Spring transaction example:
    	 * 
    	 * <pre>
    	 * TransactionStatus txn = txManager
    	 * 		.getTransaction(new DefaultTransactionDefinition());
    	 * entity = StusDAO.update(entity);
    	 * txManager.commit(txn);
    	 * </pre>
    	 * 
    	 * @see <a href =
    	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
    	 *      container-managed transaction examples</a>
    	 * @param entity
    	 *            Stus entity to update
    	 * @return Stus the persisted Stus entity instance, may not be the same
    	 * @throws RuntimeException
    	 *             if the operation fails
    	 */
    	public Stus update(Stus entity) {
    		logger.info("updating Stus instance");
    		try {
    			Stus result = getEntityManager().merge(entity);
    			logger.info("update successful");
    			return result;
    		} catch (RuntimeException re) {
    			logger.error("update failed", re);
    			throw re;
    		}
    	}
    
    	public Stus findById(String id) {
    		logger.info("finding Stus instance with id: " + id);
    		try {
    			Stus instance = getEntityManager().find(Stus.class, id);
    			return instance;
    		} catch (RuntimeException re) {
    			logger.error("find failed", re);
    			throw re;
    		}
    	}
    
    	/**
    	 * Find all Stus entities with a specific property value.
    	 * 
    	 * @param propertyName
    	 *            the name of the Stus property to query
    	 * @param value
    	 *            the property value to match
    	 * @param rowStartIdxAndCount
    	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
    	 *            row index in the query result-set to begin collecting the
    	 *            results. rowStartIdxAndCount[1] specifies the the maximum
    	 *            number of results to return.
    	 * @return List<Stus> found by query
    	 */
    	@SuppressWarnings("unchecked")
    	public List<Stus> findByProperty(String propertyName, final Object value,
    			final int... rowStartIdxAndCount) {
    		logger.info("finding Stus instance with property: " + propertyName
    				+ ", value: " + value);
    		try {
    			final String queryString = "select model from Stus model where model."
    					+ propertyName + "= :propertyValue";
    			Query query = getEntityManager().createQuery(queryString);
    			query.setParameter("propertyValue", value);
    			if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
    				int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
    				if (rowStartIdx > 0) {
    					query.setFirstResult(rowStartIdx);
    				}
    
    				if (rowStartIdxAndCount.length > 1) {
    					int rowCount = Math.max(0, rowStartIdxAndCount[1]);
    					if (rowCount > 0) {
    						query.setMaxResults(rowCount);
    					}
    				}
    			}
    			return query.getResultList();
    		} catch (RuntimeException re) {
    			logger.error("find by property name failed", re);
    			throw re;
    		}
    	}
    
    	public List<Stus> findByStuName(Object stuName, int... rowStartIdxAndCount) {
    		return findByProperty(STU_NAME, stuName, rowStartIdxAndCount);
    	}
    
    	public List<Stus> findByStuAge(Object stuAge, int... rowStartIdxAndCount) {
    		return findByProperty(STU_AGE, stuAge, rowStartIdxAndCount);
    	}
    
    	/**
    	 * Find all Stus entities.
    	 * 
    	 * @param rowStartIdxAndCount
    	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
    	 *            row index in the query result-set to begin collecting the
    	 *            results. rowStartIdxAndCount[1] specifies the the maximum
    	 *            count of results to return.
    	 * @return List<Stus> all Stus entities
    	 */
    	@SuppressWarnings("unchecked")
    	public List<Stus> findAll(final int... rowStartIdxAndCount) {
    		logger.info("finding all Stus instances");
    		try {
    			final String queryString = "select model from Stus model";
    			Query query = getEntityManager().createQuery(queryString);
    			if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
    				int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
    				if (rowStartIdx > 0) {
    					query.setFirstResult(rowStartIdx);
    				}
    
    				if (rowStartIdxAndCount.length > 1) {
    					int rowCount = Math.max(0, rowStartIdxAndCount[1]);
    					if (rowCount > 0) {
    						query.setMaxResults(rowCount);
    					}
    				}
    			}
    			return query.getResultList();
    		} catch (RuntimeException re) {
    			logger.error("find all failed", re);
    			throw re;
    		}
    	}
    
    	public static IStusDAO getFromApplicationContext(ApplicationContext ctx) {
    		return (IStusDAO) ctx.getBean("StusDAO");
    	}
    }

    上面的 @Transactional 用于spring的jpa的事务管理  


    服务接口 IStusDAO.java

    package com.undergrowth.bean;
    
    import java.sql.Timestamp;
    import java.util.List;
    
    /**
     * Interface for StusDAO.
     * 
     * @author MyEclipse Persistence Tools
     */
    
    public interface IStusDAO {
    	/**
    	 * Perform an initial save of a previously unsaved Stus entity. All
    	 * subsequent persist actions of this entity should use the #update()
    	 * method. This operation must be performed within the a database
    	 * transaction context for the entity's data to be permanently saved to the
    	 * persistence store, i.e., database. This method uses the
    	 * {@link javax.persistence.EntityManager#persist(Object)
    	 * EntityManager#persist} operation.
    	 * <p>
    	 * User-managed Spring transaction example:
    	 * 
    	 * <pre>
    	 * TransactionStatus txn = txManager
    	 * 		.getTransaction(new DefaultTransactionDefinition());
    	 * IStusDAO.save(entity);
    	 * txManager.commit(txn);
    	 * </pre>
    	 * 
    	 * @see <a href =
    	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
    	 *      container-managed transaction examples</a>
    	 * @param entity
    	 *            Stus entity to persist
    	 * @throws RuntimeException
    	 *             when the operation fails
    	 */
    	public void save(Stus entity);
    
    	/**
    	 * Delete a persistent Stus entity. This operation must be performed within
    	 * the a database transaction context for the entity's data to be
    	 * permanently deleted from the persistence store, i.e., database. This
    	 * method uses the {@link javax.persistence.EntityManager#remove(Object)
    	 * EntityManager#delete} operation.
    	 * <p>
    	 * User-managed Spring transaction example:
    	 * 
    	 * <pre>
    	 * TransactionStatus txn = txManager
    	 * 		.getTransaction(new DefaultTransactionDefinition());
    	 * IStusDAO.delete(entity);
    	 * txManager.commit(txn);
    	 * entity = null;
    	 * </pre>
    	 * 
    	 * @see <a href =
    	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
    	 *      container-managed transaction examples</a>
    	 * @param entity
    	 *            Stus entity to delete
    	 * @throws RuntimeException
    	 *             when the operation fails
    	 */
    	public void delete(Stus entity);
    
    	/**
    	 * Persist a previously saved Stus entity and return it or a copy of it to
    	 * the sender. A copy of the Stus entity parameter is returned when the JPA
    	 * persistence mechanism has not previously been tracking the updated
    	 * entity. This operation must be performed within the a database
    	 * transaction context for the entity's data to be permanently saved to the
    	 * persistence store, i.e., database. This method uses the
    	 * {@link javax.persistence.EntityManager#merge(Object) EntityManager#merge}
    	 * operation.
    	 * <p>
    	 * User-managed Spring transaction example:
    	 * 
    	 * <pre>
    	 * TransactionStatus txn = txManager
    	 * 		.getTransaction(new DefaultTransactionDefinition());
    	 * entity = IStusDAO.update(entity);
    	 * txManager.commit(txn);
    	 * </pre>
    	 * 
    	 * @see <a href =
    	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
    	 *      container-managed transaction examples</a>
    	 * @param entity
    	 *            Stus entity to update
    	 * @return Stus the persisted Stus entity instance, may not be the same
    	 * @throws RuntimeException
    	 *             if the operation fails
    	 */
    	public Stus update(Stus entity);
    
    	public Stus findById(String id);
    
    	/**
    	 * Find all Stus entities with a specific property value.
    	 * 
    	 * @param propertyName
    	 *            the name of the Stus property to query
    	 * @param value
    	 *            the property value to match
    	 * @param rowStartIdxAndCount
    	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
    	 *            row index in the query result-set to begin collecting the
    	 *            results. rowStartIdxAndCount[1] specifies the the maximum
    	 *            count of results to return.
    	 * @return List<Stus> found by query
    	 */
    	public List<Stus> findByProperty(String propertyName, Object value,
    			int... rowStartIdxAndCount);
    
    	public List<Stus> findByStuName(Object stuName, int... rowStartIdxAndCount);
    
    	public List<Stus> findByStuAge(Object stuAge, int... rowStartIdxAndCount);
    
    	/**
    	 * Find all Stus entities.
    	 * 
    	 * @param rowStartIdxAndCount
    	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
    	 *            row index in the query result-set to begin collecting the
    	 *            results. rowStartIdxAndCount[1] specifies the the maximum
    	 *            count of results to return.
    	 * @return List<Stus> all Stus entities
    	 */
    	public List<Stus> findAll(int... rowStartIdxAndCount);
    }

    客户端实现 SpringRmiClient.java

    package com.undergrowth.junit;
    
    import static org.junit.Assert.*;
    
    import java.sql.Timestamp;
    import java.util.Calendar;
    import java.util.List;
    import java.util.UUID;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.undergrowth.bean.IStusDAO;
    import com.undergrowth.bean.Stus;
    
    /*
     * spring支持的rmi很简单  
     * 不用服务接口继承Remote
     * 不用服务实现类继承UnicastRemoteObject
     * 也不用我们自己注册rmi的远程服务实现类
     * 
     * 服务器端 你需要做的仅仅是 写好你需要提供远程服务的实现类
     * 然后将其交给RmiServiceExporter类 RmiServiceExporter会将实现类发布为RMI服务
     * 
     * 客户端 也很简单
     * 只需要使用RmiProxyFactoryBean从服务器端的URL从获取服务对象  并进行封装给你定义的id
     * 然后从spring容器中获取RmiProxyFactoryBean封装的id即可
     * 
     * 此测试代码中 服务器和客户端都在一个项目中 也可换成多个项目 在不同的电脑中
     * 只需要在服务器的RmiServiceExporter中加入 p:registryHost="ip地址" 即可
     * 客户端将localhost换成ip地址即可
     */
    public class SpringRmiClient {
    
    	@Test
    	public void testRmiClient() {
    		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
    		//获取封装的远程服务对象
    		IStusDAO iStusDAO=(IStusDAO) ac.getBean("stusDao");
    		//调用远程服务对象的方法 返回列表结果
    		List<Stus> list=iStusDAO.findAll();
    		for (Stus stus : list) {
    			System.out.println(stus);
    		}
    		//添加
    		Stus stus=new Stus(UUID.randomUUID().toString(), "spring rmi客户端", 78.9, new Timestamp(Calendar.getInstance().getTimeInMillis()));
    		iStusDAO.save(stus);
    		
    		list=iStusDAO.findAll();
    		for (Stus stus2 : list) {
    			System.out.println(stus2);
    		}
    		
    		
    		//如果不加下面的while语句  那么 执行完此测试方法后 在cmd中 就看不到rmi的绑定端口信息 
    		//因为spring在测试完成后 会清理相关的rmi信息
    		//while(true){}
    	}
    
    }
    

    控制台输出

    log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    [EL Info]: 2014-05-03 12:44:50.747--ServerSession(17038506)--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b
    [EL Info]: connection: 2014-05-03 12:44:51.655--ServerSession(17038506)--file:/D:/learnsoftware/java/AndroidDevelop/myeclipse_2013_code/SpringRmiAndJpa/bin/_SpringRmiAndJpa login successful
    Stus [stuId=014ED6D01D9B4C6E882E3624032FA9CD, stuName=sz, stuAge=21.0, stuBirthday=2014-04-19 15:07:33.0]
    Stus [stuId=946E460A4FA14D8496EF601E754FD314, stuName=gz, stuAge=20.0, stuBirthday=2014-04-19 15:07:33.0]
    Stus [stuId=014ED6D01D9B4C6E882E3624032FA9CD, stuName=sz, stuAge=21.0, stuBirthday=2014-04-19 15:07:33.0]
    Stus [stuId=946E460A4FA14D8496EF601E754FD314, stuName=gz, stuAge=20.0, stuBirthday=2014-04-19 15:07:33.0]
    Stus [stuId=96d4f969-6d0a-4f6d-940f-e97b73080314, stuName=spring rmi客户端, stuAge=78.9, stuBirthday=2014-05-03 12:44:52.591]



    对比以上两种方式 会发现spring的rmi比自己写的rmi要简单、方便的多 不过前提是你对spring要有一定的了解


    其实使用自定义的rmi方式时 遇到了很多我称之为诡异的现象 也记录一下吧

    其实当我写好远程服务接口和远程服务实现类时 我尝试着使用junit类进行测试 如下 

    package com.undergrowth.junit;
    
    import static org.junit.Assert.*;
    
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    import java.util.List;
    
    import org.junit.Test;
    
    import com.undergrowth.bean.Stus;
    import com.undergrowth.rmi.IStusDAO;
    import com.undergrowth.rmi.StusDAO;
    
    public class RmiJunit {
    
    	@Test
    	public void testServer() {
    		
    		try {
    			IStusDAO istusDAO=new StusDAO();
    			//System.setProperty("java.rmi.server.hostname", "192.168.38.172");
    			//创建访问rmi的远程端口
    			//启动rmiregister程序
    			//Runtime.getRuntime().exec("rmiregistry 4567");
    			LocateRegistry.createRegistry(4567);
    			//注册远程服务对象
    			Naming.rebind("rmi://192.168.38.172:4567/IStusDAO", istusDAO);
    			System.out.println("注册远程服务对象成功");
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    	
    	@Test
    	public void testClient() {
    		
    		try {
    			IStusDAO iStusDAO=(IStusDAO) Naming.lookup("rmi://192.168.38.172:4567/IStusDAO");
    			/*List<Stus> listStus=iStusDAO.findAll();
    			for (Stus stus : listStus) {
    				System.out.println(stus);
    			}*/
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    	
    	@Test
    	public void testCon(){
    		IStusDAO iStusDAO;
    		try {
    			iStusDAO = new StusDAO();
    			List<Stus> listStus=iStusDAO.findAll();
    			for (Stus stus : listStus) {
    				System.out.println(stus);
    			}
    		} catch (RemoteException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    }
    


    先运行testServer没有问题  控制台打印出 

    注册远程服务对象成功
    
    即表示服务器端注册rmi服务是没有问题的 看起来是这样 是么?

    其实不是 接着看 然后运行testClient 发现报错了 

    java.rmi.ConnectException: Connection refused to host: 192.168.38.172; nested exception is: 
    	java.net.ConnectException: Connection refused: connect
    	at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601)
    	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
    	at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
    	at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
    	at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    	at java.rmi.Naming.lookup(Naming.java:84)
    	at com.undergrowth.junit.RmiJunit.testClient(RmiJunit.java:42)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:597)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    Caused by: java.net.ConnectException: Connection refused: connect
    	at java.net.PlainSocketImpl.socketConnect(Native Method)
    	at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
    	at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
    	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
    	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
    	at java.net.Socket.connect(Socket.java:529)
    	at java.net.Socket.connect(Socket.java:478)
    	at java.net.Socket.<init>(Socket.java:375)
    	at java.net.Socket.<init>(Socket.java:189)
    	at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:22)
    	at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:128)
    	at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
    	... 29 more
    

    上网一搜 好多 经典的错误 但是我都排查了 说ip错误的 不是  说服务器和客户端的rmi的url要一致 也不是  

    很明显  是客户端无法连接上服务器的rmi端口 于是 


    发现cmd下面居然没有 4567的端口监听

    这让我好郁闷 接着寻寻觅觅 还是没找到原因  将testServer和testClient换成两个main函数后  发现就正常了  好吧 我发现我找到原因了 

    在testServer里面加上一句 如下

    @Test
    	public void testServer() {
    		
    		try {
    			IStusDAO istusDAO=new StusDAO();
    			//System.setProperty("java.rmi.server.hostname", "192.168.38.172");
    			//创建访问rmi的远程端口
    			//启动rmiregister程序
    			//Runtime.getRuntime().exec("rmiregistry 4567");
    			LocateRegistry.createRegistry(4567);
    			//注册远程服务对象
    			Naming.rebind("rmi://192.168.38.172:4567/IStusDAO", istusDAO);
    			System.out.println("注册远程服务对象成功");
    			while(true){}
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}

    因为在与testServer运行完后 如果没有加while(true){} 这句的话  注册的rmi这个进程就关掉了  进程都关了 rmi的端口监听也就不存在了 客户端还怎么连的上呢 郁闷死了 不过 好歹解决了


    当然 如果使用  

    Runtime.getRuntime().exec("rmiregistry 4567");
    的话 则会在后台创建一个rmiregistry的进程 这样 rmi的服务就不依赖于当前的进程了  但是  在Naming.rebind的时候 则会报错 如下

    @Test
    	public void testServer() {
    		
    		try {
    			IStusDAO istusDAO=new StusDAO();
    			//System.setProperty("java.rmi.server.hostname", "192.168.38.172");
    			//创建访问rmi的远程端口
    			//启动rmiregister程序
    			Runtime.getRuntime().exec("rmiregistry 5678");
    			//LocateRegistry.createRegistry(5678);
    			//注册远程服务对象
    			Naming.rebind("rmi://192.168.38.172:5678/IStusDAO", istusDAO);
    			System.out.println("注册远程服务对象成功");
    			//while(true){}
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}

    错误

    java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    	java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    	java.lang.ClassNotFoundException: com.undergrowth.rmi.IStusDAO
    	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:400)
    	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
    	at sun.rmi.transport.Transport$1.run(Transport.java:159)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    	at java.lang.Thread.run(Thread.java:662)
    	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
    	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
    	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:359)
    	at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
    	at java.rmi.Naming.rebind(Naming.java:160)
    	at com.undergrowth.junit.RmiJunit.testServer(RmiJunit.java:29)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:597)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    	java.lang.ClassNotFoundException: com.undergrowth.rmi.IStusDAO
    	at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
    	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:390)
    	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
    	at sun.rmi.transport.Transport$1.run(Transport.java:159)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    	at java.lang.Thread.run(Thread.java:662)
    Caused by: java.lang.ClassNotFoundException: com.undergrowth.rmi.IStusDAO
    	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    	at java.lang.Class.forName0(Native Method)
    	at java.lang.Class.forName(Class.java:249)
    	at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:709)
    	at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:653)
    	at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:590)
    	at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628)
    	at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
    	at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:238)
    	at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1528)
    	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1490)
    	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1729)
    	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1326)
    	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
    	... 12 more
    

    原因在于  使用rmiregistry的进程的时候  在注册istusDAO对象的时候  使用的是相对路径查找istusDAO的类 而rmiregistry进程根本不知道istusDAO的类在哪里 

    有解决办法 即 进入到istusDAO的所在目录 在运行测试方法 即可

  • 相关阅读:
    python中函数的定义,调用,全局变量,局部变量,函数的嵌套使用初级篇
    逐行解释和整体解释的理解
    python中函数参数的详解,可变参数,关键字参数等
    python中is和==的区别
    python中的模块,以及包的导入的总结
    Python当中的a += a 与 a = a + a 的区别,可变类型与不可变类型的数据类型,引用传参
    学习Java的第七天
    学习Java的第八天
    学习java的第六天
    学习java第二天
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275575.html
Copyright © 2020-2023  润新知