写一篇巨杂的流水记录下对j2ee的某些技术的浏览。
webservice是为跨平台设计的通信语言,不过HelloWorld而言,C#要做得比java要好很多很多!
第一方面:C#提供WebService,C#或Java调用。
C#新建WebService的步骤如下:
- 新建Asp.net Web工程。
- 添加文件=>webservice,输入文件名。
- 右键文件=>在浏览器中预览就可以看到webservice,点击invoke可以调用它。
- Winlin.asmx的代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; namespace MyWebService { /// <summary> /// Summary description for Winlin /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class Winlin : System.Web.Services.WebService { [WebMethod] public string HelloWorld() { return "C# WebService: Hello World!"; } } }
C#使用WebService也灰常简单:
- 添加Service引用
- 填入刚刚预览的地址:http://localhost:59851/Winlin.asmx?WSDL
- 输入引用的命名空间(将该webservice装入该命名空间,例如csharp)
- 直接调用类就可以了:
using System; namespace WebServiceClient { class Program { static void Main(string[] args) { csharp.WinlinSoapClient client = new csharp.WinlinSoapClient(); Console.WriteLine(client.HelloWorld()); } } }
而Java搞清楚了其实也很简单,不过对于初学者就得翻很多资料,找很多例子,IDE并不能搞好这个事情。
Java调用C#生成的webservice的方法如下:
- 新建Java工程。例如MyWSClient。
- 运行cmd.exe,进入工程目录,例如:
cd d:\tvie\lab\java\wsClient\src
- 生成调用webService的stub:
wsimport -p org.tempuri -keep http://localhost:59851/Winlin.asmx?WSDL
- 注:不要引用jboss的jar,否则会报错:
java.lang.ClassNotFoundException: com.sun.xml.messaging.saaj.soap.AttachmentPartImpl
- 可以看到生成了一堆的文件。
- 调用:
import org.tempuri.*; public class CSharpWSInvoke { public static void main(String[] args){ Winlin winlin = new Winlin(); WinlinSoap soap = winlin.getWinlinSoap(); System.out.println(soap.helloWorld()); } }
第二方面:Java直接提供WebService,C#或Java调用。
Java直接提供WebService的方法如下:
- 新建Java工程,例如MyWSClient。
- 必须新建packet,不能使用默认的packet。例如cn.winlin。
- 新建Class,内容如下:
package cn.winlin; import javax.jws.WebMethod; import javax.jws.WebService; import javax.xml.ws.Endpoint; @WebService public class Hello { @WebMethod public String hello(String name){ return "Hello, "+name; } public static void main(String[] args){ Hello hello = new Hello(); Endpoint.publish("http://localhost:8081/hello", hello); System.out.println("webservice published!"); } }
- 然后打开cmd.exe,进入目录:
cd D:\tvie\lab\java\wsServer\src
- 生成webservice:
apt -d build cn\winlin\Hello.java
- 启动webservice:
cd build java cn.winlin.Hello
- 可以看到service启动成功:
http://localhost:8081/hello?wsdl
调用方法同上。
Java的调用方法:
- 新建工程,例如MyWSClient。
- 打开cmd.exe,进入目录:
cd d:\tvie\lab\java\wsClient\src wsimport -p cn.winlin -keep http://localhost:8081/hello?wsdl
- 然后新建Java类调用:
import cn.winlin.*; public class JavaWSInvoke { public static void main(String[] args){ HelloService service = new HelloService(); Hello hello = service.getHelloPort(); System.out.println(hello.hello("winlin")); } }
第三方面:Java使用EJB SLSB提供webservice
EJB的Stateless Session Bean能以简单方式提供webservice。方法如下:
- 新建EJB工程。
- 添加无状态Session Bean。提供remote接口。
- Remote接口定义如下:
package com.winlin; import javax.ejb.Remote; @Remote public interface MyWebServiceRemote { }
- 在实现类中添加标记即可:
package com.winlin; import javax.ejb.Stateless; import javax.jws.WebMethod; import javax.jws.WebService; @Stateless @WebService public class MyWeb implements MyWebServiceRemote { public MyWeb() { } @WebMethod public String sayHello() { return "WebService: it's me!"; } @WebMethod public String sayName(String name) { System.out.println("WS: sayName(\""+name+"\")invoked!"); return "WebService: it's me "+name; } }
- 直接发布到容器,例如jboss。
- 调用方法同上。
以java调用为例,方法如下:
- 生成stub,调用wsimport命令,同上。
- 调用:
import com.winlin.*; public class MyWebInvoker { public static void main(String[] args) { MyWebService web = new MyWebService(); MyWeb me = web.getMyWebPort(); System.out.println(me.sayHello()); } }
- 添加webservice引用后,调用如下:
using System; namespace WebServiceClient { class Program { static void Main(string[] args) { ejb.MyWebClient ejbclient = new ejb.MyWebClient(); ejb.sayHelloResponse ejbres = ejbclient.sayHello(new ejb.sayHello()); Console.WriteLine(ejbres.@return); } } }
JBOSS 5使用jdk1.6时会有ws不兼容的情况。
若SLSB暴露webservice报错:
java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage
则执行如下命令:
cp client/jbossws-native-jaxrpc.jar lib/endorsed/
cp client/jbossws-native-jaxws.jar lib/endorsed/
cp client/jbossws-native-jaxws-ext.jar lib/endorsed/
cp client/jbossws-native-saaj.jar lib/endorsed/
第五方面:JBoss的启动参数和WebService的地址
webservice生成的地址默认是127.0.0.1,可以在jboss启动时指定为本机ip:
./run.sh -b 10.12.12.101
第六方面:使用Mysql数据库,对外提供WebService调用
- 拷贝mysql-ds.xml到deploy,里面包含数据库的数据源。内容如下:
<?xml version="1.0" encoding="UTF-8"?> <datasources> <local-tx-datasource> <jndi-name>MySqlDS_EJB</jndi-name> <connection-url>jdbc:mysql://localhost:3306/mysql_ejb</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>tvie</user-name> <password>tvie</password> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources>
-
将mysql的jar库拷贝到:jboss5\server\default\lib 并重启jboss服务器。
mysql-connector-java-5.1.0-bin.jar
http://downloads.mysql.com/archives/mysql-connector-java-5.1/mysql-connector-java-5.1.0.zip
http://downloads.mysql.com/archives/mysql-connector-java-5.1/mysql-connector-java-5.1.0.tar.gz - 创建数据库,进入mysql后执行如下sq语句:
drop DATABASE IF EXISTS `mysql_ejb`; create DATABASE mysql_ejb; use mysql_ejb; DROP TABLE IF EXISTS `Project`; CREATE TABLE `Project` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'the id of project', `source` varchar(2000) DEFAULT NULL COMMENT 'the friendly project name', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
- 在ejbModule\META-INF目录,新建文件persistence.xml,内容如下(红色字体和mysql-ds.xml中保持一致):
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="mysql_ejb"> <jta-data-source>java:/MySqlDS_EJB</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="none" /> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" /> </properties> </persistence-unit> </persistence>
- 新建数据实体EntityBean,映射到表:
package com.winlin.db; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "Project") @SuppressWarnings("serial") public class Project implements Serializable { private Integer id; private String source; @Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getId(){ return this.id; } public void setId(Integer id){ this.id = id; } public String getSource(){ return this.source; } public void setSource(String source){ this.source = source; } }
- 新建SLSB的Remote接口:
package com.winlin.db; import javax.ejb.Remote; @Remote public interface ProjectBeanRemote { }
- SLSB的实现(对外提供webservice):
package com.winlin.db; import java.util.List; import javax.ejb.Stateless; import javax.jws.WebMethod; import javax.jws.WebService; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; @Stateless @WebService public class ProjectBean implements ProjectBeanRemote { @PersistenceContext(unitName="mysql_ejb") protected EntityManager em; public ProjectBean() { } @WebMethod public void insertProject(Project p){ em.persist(p); } @WebMethod @SuppressWarnings("unchecked") public List<Project> getProjectList(){ Query query = em.createQuery("select p from Project p order by p.id asc"); List<Project> p = (List<Project>) query.getResultList(); return p; } @WebMethod public void updateSource(String source, int id){ Project p = em.find(Project.class, id); p.setSource(source); } }
- 发布EJB。
- 导入webservice:
wsimport -p com.winlin.db -keep http://database:8080/com.winlin.database/ProjectBean?WSDL
- 调用webservice:
import java.util.Date; import java.util.List; import com.winlin.db.Project; import com.winlin.db.ProjectBean; import com.winlin.db.ProjectBeanService; public class EJBDbClient { public static void main(String[] args) { Date start = new Date(); System.out.println(start.toString()); ProjectBeanService server = new ProjectBeanService(); ProjectBean bean = server.getProjectBeanPort(); Project p = new Project(); p.setSource("test."+bean.getProjectList().size()+".flv"); bean.insertProject(p); List<Project> list = bean.getProjectList(); System.out.println("we get a list contains:" + list.size() + " elements."); for(int i=0;i<list.size();i++){ System.out.println("id="+list.get(i).getId()+",url="+list.get(i).getSource()); } Date end = new Date(); System.out.println(end.toString()); System.out.println("total:" + ((end.getTime() - start.getTime()) / 100 / 10.0) + "s"); } }
第七方面:使用Eclipse调试EJB
如下方法可以在Eclipse中调试EJB生成的webservices
- Windows => Show View => Servers
- 右键 => New => Server
- 选择JBoss5.0 Server,默认参数选择完成
- 右键新建的Server => Open可以打开详细配置
- Open launch configuration 可以打开详细的运行参数配置。
其中,Arguments设置VM arguments需要添加参数:-Djava.endorsed.dirs=C:\jboss5\lib\endorsed。即设为:
否则webservice运行会报错(JBoss5.0+Jdk1.6)。-Dprogram.name=run.bat -Xms128m -Xmx512m -XX:MaxPermSize=256m -Djava.endorsed.dirs=C:\jboss5\lib\endorsed
- 启动调试即可。
第八方面:EJB使用Hibernate
Jboss支持hibernate,所以直接编写hibernate的程序就可以运行在Jboss上了。
方法如下:
- 在mysql中新建数据库:
drop DATABASE IF EXISTS `mysql_ejb`; create DATABASE mysql_ejb; use mysql_ejb; DROP TABLE IF EXISTS `Project`; CREATE TABLE `Project` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'the id of project', `source` varchar(2000) DEFAULT NULL COMMENT 'the friendly project name', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
- 注:不用新建mysql-ds.xml数据源。
- 新建ejb项目,在ejbModule(相当于src)下添加hibernate.cfg.xml,内容如下:
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <property name="connection.url"> jdbc:mysql://localhost:3306/mysql_ejb </property> <property name="connection.username">winlin</property> <property name="connection.password">mypassword</property> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="myeclipse.connection.profile">MySQL</property> <mapping resource="com/winlin/Project.hbm.xml" /> </session-factory> </hibernate-configuration>
- 为表Project新建类:
package com.winlin; public class Project { private int id; private String source; public int getId(){ return this.id; } public void setId(int id){ this.id = id; } public String getSource(){ return this.source; } public void setSource(String source){ this.source = source; } }
- 在同目录下新建映射文件:Project.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.winlin.Project" table="project" catalog="mysql_ejb"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="assigned" /> </id> <property name="source" type="java.lang.String"> <column name="source" length="2000" /> </property> </class> </hibernate-mapping>
- 添加SLSB无状态SessionBean:ProjectBean,提供webservice,实现Remote接口:
package com.winlin; import java.util.List; import javax.ejb.Stateless; import javax.jws.WebMethod; import javax.jws.WebService; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; @WebService @Stateless public class ProjectBean implements ProjectBeanRemote { private static final SessionFactory factory = build_factory(); private static SessionFactory build_factory(){ try{ return new Configuration().configure().buildSessionFactory(); } catch(Exception ex){ System.out.println("[error] initialize factory failed: " + ex.getMessage()); throw new ExceptionInInitializerError(ex); } } public ProjectBean() { } @WebMethod public void insert_project(String source){ Session session = factory.openSession(); Transaction tx = session.beginTransaction(); Project p = new Project(); p.setSource(source); session.save(p); tx.commit(); session.close(); } @SuppressWarnings({ "unchecked", "rawtypes" }) @WebMethod public List<Project> get_projects(){ Session session = factory.openSession(); Query query = session.createQuery("from Project as project order by id desc"); query.setFirstResult(3); query.setMaxResults(10); List list = query.list(); return list; } }
- 调用方法。
先导入ws:
然后client调用:wsimport -p com.winlin -keep http://127.0.0.1:8080/hibernate.db/ProjectBean?wsdl
import java.util.Date; import java.util.List; import com.winlin.Project; import com.winlin.ProjectBean; import com.winlin.ProjectBeanService; public class HibernateDbClient { public static void main(String[] args) { Date start = new Date(); System.out.println(start.toString()); ProjectBeanService service = new ProjectBeanService(); ProjectBean bean = service.getProjectBeanPort(); if(args.length <= 0){ bean.insertProject("hello.hibernate.flv"); } else{ bean.insertProject(args[0]); } List<Project> list = bean.getProjects(); for(int i=0 ;i < list.size(); i++){ System.out.println(list.get(i).getSource()); } Date end = new Date(); System.out.println(end.toString()); System.out.println("total:" + ((end.getTime() - start.getTime()) / 100 / 10.0) + "s"); } }
第九方面:使用JAR
将接口定义在一个jar,供其他的project调用,方法如下:
- 新建java工程,定义接口IMan如下:
public interface IMan { public String getName(); public void bookFood(); }
- 生成jar文件,执行如下命令:
cd D:\tvie\lab\java\coms.shared\src jar cvf ../com.winlin.shared.jar *.class
- 新建调用java工程,定义类如下:
public class Client implements IMan { public static void main(String[] args) { Client c = new Client(); c.bookFood(); } public String getName(){ return "Client"; } public void bookFood(){ System.out.println(this.getName() + ": Client book food!"); } }
- 编译程序:
cd d:\tvie\lab\java\coms.client\src javac -classpath ..\..\coms.shared\com.winlin.shared.jar Client.java
- 执行程序:
java -classpath .;..\..\coms.shared\com.winlin.shared.jar Client
- 结果如下:
Client: Client book food!
第十方面:命令行编译和执行
在Windows下编译和Linux下编译有所不同。例如,若某程序引用了Jboss的库(EJB,JNI,JMS等),则编译和执行方法如下:
在Windows下编译和执行:
- 直接编译:
cd D:\tvie\lab\java\jms.receiver\src javac -cp .;c:\jboss5\client\* QueueReceiver.java
- 可以是-cp或者-classpath。
注意-cp后面必须是文件,可以用通配符(并且不能带扩展名),以下命令均为错误:
javac QueueReceiver.java #没有带指定Jboss的库 javac -cp . QueueReceiver.java #没有指定Jboss的引用库 javac -cp .:c:\jboss5\client\* QueueReceiver.java #分隔符必须是分号。 javac -cp .;c:\jboss5\client\*.jar QueueReceiver.java #通配符不能带扩展名。
- 直接执行:
java -cp .;c:\jboss5\client\* QueueReceiver
Linux下编译和执行:
- 直接编译:
/home/tvie/java javac -cp .:/usr/local/jboss/client/* QueueReceiver.java
- 分隔符必须是冒号,其他和windows一致,一下命令为错误:
javac QueueReceiver.java #没有指定Jboss的库 javac . QueueReceiver.java #没有指定Jboss的库 javac -cp .;/usr/local/jboss/client/* QueueReceiver.java #使用的是分号,而不是冒号 javac -cp .:/usr/local/jboss/client/*.jar QueueReceiver.java #通配符后面不能使用扩展名
- 直接执行:
java -cp .:/usr/local/jboss/client/* QueueReceiver
使用环境变量。可以使用环境变量,这样可以不带-cp就可以编译和执行。方法如下:
- Windows设置环境变量(设置环境变量后关闭cmd.exe重新打开cmd.exe):
右键我的电脑 => 属性 => 高级 => 在“系统变量” 双击“CLASSPATH” 设置内容如下:
.;c:\jboss5\client\*
- Linux下执行如下命令:
sudo vi /etc/profile #在结尾添加如下一行: export CLASSPATH=.:/usr/local/jboss/client/* #退出vi后,执行如下命令: source /etc/profile
- 编译和执行(linux和windows都一样):
javac QueueReceiver.java java QueueReceiver
- 要注意分隔符和-cp只能是文件(通配符也是)。
第十方面:关于JMS和EJB-MDB
JMS是消息框架,定义了消息框架,EJB-MDB是JMS的消息消费者(Consumer/Receiver),其实可以自己定义Producer和Receiver/Consumer。
定义消息队列,拷贝到/usr/local/jboss/server/default/deploy/winlin-service.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<server>
<mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=winlin">
<attribute name="JNDIName">queue/winlin</attribute>
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
</server>
定义消息生产者(Producer)不断生产消息:
import java.util.Date;
import java.util.Properties;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.naming.Context;
import javax.naming.InitialContext;
public class QueueSender
{
public static void main(String[] args) throws Exception{
String msg = "Hello, this is server!";
if(args.length > 0){
msg = args[0];
}
for(int i=0; ;i ++){
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
props.setProperty(Context.PROVIDER_URL, "localhost:1099");
props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
InitialContext context = new InitialContext(props);
QueueConnectionFactory factory = (QueueConnectionFactory)context.lookup("ConnectionFactory");
QueueConnection conn = factory.createQueueConnection();
QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
Destination queue = (Queue)context.lookup("queue/winlin");
MessageProducer producer = session.createProducer(queue);
String formatted_msg = "msg#"+i+", "+msg;
producer.send(session.createTextMessage(formatted_msg));
session.close();
conn.close();
System.out.println("Message sended("+new Date().toString()+"): " + formatted_msg);
}
}
}
定义消息消费者(Receiver):
import java.util.Date;
import java.util.Properties;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
class MyMessageListener implements MessageListener
{
private QueueSession session;
private QueueConnection conn;
public void onMessage(Message msg){
try{
//Thread.sleep(100);
System.out.println(new Date().toString() + ":" + ((TextMessage)msg).getText());
}catch(Exception e){
e.printStackTrace();
}
}
public void start() throws Exception{
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
props.setProperty(Context.PROVIDER_URL, "localhost:1099");
props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
InitialContext context = new InitialContext(props);
QueueConnectionFactory factory = (QueueConnectionFactory)context.lookup("ConnectionFactory");
QueueConnection conn = factory.createQueueConnection();
QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
Queue queue = (Queue)context.lookup("queue/winlin");
javax.jms.QueueReceiver receiver = session.createReceiver(queue);
receiver.setMessageListener(this);
this.session = session;
this.conn = conn;
conn.start();
}
public void stop() throws Exception{
session.close();
conn.close();
}
}
public class QueueReceiver
{
public static void main(String[] args) throws Exception {
MyMessageListener msg = new MyMessageListener();
msg.start();
System.out.println("Listener started!");
Thread.sleep(20*1000);
msg.stop();
System.out.println("Receiver exited!");
}
}
编译和执行:
#编译
javac -cp .:/usr/local/jboss/client/* QueueReceiver.java
javac -cp .:/usr/local/jboss/client/* QueueSender.java
#执行,可以在不同的机器
java -cp .:/usr/local/jboss/client/* QueueReceiver
java -cp .:/usr/local/jboss/client/* QueueSender
第十一方面:关于RMI
远程调用,RMI是EJB的基础,JMS是消息机制,也可以作为调用的方式。
JMS若需要消息处理的结果,就会很麻烦。例如Producer发送一条消息到队列A,Receiver从队列A接受到消息后再发一条消息到队列B。首先需要两个队列,其次若Producer有多个,就有麻烦了。
例如ProducerA和ProducerB都发送了消息到队列A,Receiver接受消息处理后将结果发到队列B,ProducerA和ProducerB都能收到消息,可是无法确定能收到特定的消息。
可以用topic接口,可并不使用这个场景(会接受到自己不需要的消息),所以消息作为调用还是有局限性。topic在广播给Receiver,例如更新状态时,每个Receiver都需要这个消息,是符合应用场景的。
RMI是同步调用(webservice同步调用作为异构平台的应用,ARMI据说是异步具体还再看),使用方法如下:
实现RMIServer:
import java.rmi.Naming;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
interface IServer extends Remote
{
public String hello() throws RemoteException;
}
class Server extends UnicastRemoteObject implements IServer
{
public Server() throws RemoteException{
}
public String hello() throws RemoteException{
return "#" + Thread.currentThread().getId() + ": hello, RMI world!";
}
}
public class RMIServer
{
public static void main(String[] args) throws Exception {
IServer server = new Server();
LocateRegistry.createRegistry(9099);
String url = "rmi://localhost:9099/RMIServer";
Naming.bind(url, server);
Thread.sleep(10000);
System.exit(0);
}
}
实现RMIClient:
import java.rmi.Naming;
public class RMIClient
{
public static void main(String[] args) throws Exception {
for(;;){
String url = "rmi://localhost:9099/RMIServer";
IServer server = (IServer)Naming.lookup(url);
System.out.println("RMIServer: " + server.hello());
}
}
}
第十二方面 java7的内存问题
使用wsimport导入webservice后调用,若使用java6调用没有问题,若使用java7调用(7.0.10.8)内存会一直增长直到吃光。
最后一方面:没有了。
靠人品了~