因为公司的项目中要用到web services,小弟我刚刚接触这个东东,以下是一些学习过程中的心得,和大家分享一下,也希望各位高手能指点指点我~~~呵呵~~~~
一、安装Apache Axis
Apache Axis本身也是一个Web Project,它内建了对SOAP的编码、解析,并为Client提供了一些使用SOAP Service的API,同时,为Web Service的发布提供管理,并对Client提交的处理请求作出响应。对于基于Axis的应用而言,我们可以将注意力完全放在具体Service和Client的设计上,而无需考虑中间的传输过程(对于Client而言,还需要使用一些Axis提供的访问SOAP服务的特定API),这一点是与XML RPC不同的地方。
Apache Axis可以从http://ws.apache.org/axis/下载,当前的最新版本是1.4。
安装Axis的过程很简单:
1、解压Axis到任意目录下;
2、拷贝Axis目录下的webapps/axis目录到%TOMCAT_HOME%/webapps下;
3、为了便于编译和测试程序,添加环境变量:
AXIS_HOME Axis的解压目录
AXIS_LIB %AXIS_HOME%/lib
AXISCLASSPATH %AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery-0.2.jar;%AXIS_LIB%\commons-logging-1.0.4.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar
完成上述工作后,启动Tomcat,并用IE打开:http://localhost:8080/axis/,点击其中的Validation、List两个链接,如果没有报告任何错误,则说明Axis安装成功。
二、举例
以下面的HelloService为例:
package demo.soap;
public class HelloService {
public String sayHello() {
return "Hello World!";
}
}
将该客户端的字节码文件(*.class)放到%TOMCAT_HOME%/webapps/axis/WEB-INF/classes下,当你每次修改服务端代码后,都要重复这个步骤
要发布上面的Service,需编写如下的配置文件:
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
      <service name="UpdateService" provider="java:RPC">
            <parameter name="className" value="com.user.dao.UserDao"/>
            <parameter name="allowedMethods" value="*"/>
      </service>
</deployment>
将上述内容保存为%TOMCAT_HOME%\webapps\axis\WEB-INF\deploy.txt,并在其所在目录下执行:
java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.txt
生成server-config.wsdd文件,打开该文件看一下,可以看到UpdateService的相关信息已被添加到该文件,此外,还包括一些默认的配置信息以及AdminService、Version两个基础服务。
以下是UpdateService的Client程序的相关代码:
package demo.soap;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
public class HelloClient {
public static void main(String [] args) throws Exception {
String endpoint = "http://localhost:" + "8080" + "/axis/services/UpdateService"; // Attention: A little difference
Service service = new Service();
Call call = (Call)service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setOperationName("sayHello");
String res = (String)call.invoke(new Object[] {});
System.out.println(res);
}
}
与前面的EchoClient的区别仅在于访问点稍有不同。
发布后如何删除对应的Service呢?要删除上面发布的UpdateService服务,只需在%TOMCAT_HOME%\webapps\axis\WEB-INF目录下添加如下的undeploy.txt描述文件,其内容如下:
<undeployment xmlns="http://xml.apache.org/axis/wsdd/">
<service name="UpdateService"/>
</undeployment>
然后执行:
java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient undeploy.txt
以更新server-config.wsdd文件。
刷新一下页面:
http://localhost:8080/axis/servlet/AxisServlet
将看到前面已发布的对应的Service已被删除。
如果以后还要发布新的Service,你可以选择直接更新上面产生的server-config.wsdd文件,或者重复上面的步骤。以上就是一个简单的通过AXIS SOAP来远程调用其他WEB应用中的方法的示例.
但是以上被调用的远程方法,只适用于无返回值或者是基本数据类型的返回值,而当我们要调用自定义类型的值的时候,需要做一些修改.比如,在我调用的远程方法中,我要返回一个集合类型的值,该集合类型中包含的是一个标准的JAVABEAN。具体方法如下:
服务端:
public Vector Select(String sql) {
// TODO Auto-generated method stub
Vector userlist = new Vector();
//得到数据库连接
con = jfu.getConnection();
if (con == null) {
return null;
}
try {
stm = con.createStatement();
stm.executeUpdate("use test");
rs = stm.executeQuery(sql);
System.out.println("执行SQL:===" + sql);
while (rs.next()) {
UserInFo user = (UserInFo) ObjectFactory
.getObjectInstance("userinfo");
user.setUsername(rs.getString("user_ID"));
user.setCardID(rs.getString("card_id"));
user.setGamepoint(rs.getString("game_point"));
userlist.add(user);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (con != null) {
try {
rs.close();
rs = null;
stm.close();
stm = null;
con.close();
con = null;
System.out.println("数据库已关闭......");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}
return userlist;
}public class UserInFo implements java.io.Serializable { private String cardID;
private String username;
private String gamepoint;

public String getCardID() {
return cardID;
}
public void setCardID(String cardID) {
this.cardID = cardID;
}
public String getGamepoint() {
return gamepoint;
}
public void setGamepoint(String gamepoint) {
this.gamepoint = gamepoint;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
将该客户端的字节码文件(*.class)放到%TOMCAT_HOME%/webapps/axis/WEB-INF/classes下,当你每次修改服务端代码后,都要重复这个步骤修改server-config.wsdd文件,声明你自定义类型的输入和输出参数的类型
<service name="UpdateService" provider="java:RPC">
  <parameter name="allowedMethods" value="*"/>
  <parameter name="className" value="com.user.dao.UserDao"/>
  <beanMapping qname="myNS:UserInFo" xmlns:myNS="UpdateService" languageSpecificType="java:com.user.vo.UserInFo"/>
 </service>
beanMapping节点定义了UserInFo对象的序列化和反序列化使用Axis自带的针对JavaBean的序列化和反序列化器来实现。
其中,xmlns定义命名空间为UpdateService,和服务同名,qname定义为命名空间myNS中的UserInFo,与被序列化的类名相同,这种命名方式可使处理的对象一目了然。当然也可命名为其他名字。客户端:
public Vector InvokeService(String userid) throws Exception {
String endpoint = "http://localhost:" + "8080"
+ "/axis/services/UpdateService"; Service service = new Service(); Call call = (Call) service.createCall(); call.setTargetEndpointAddress(new java.net.URL(endpoint)); QName qn = new QName("UpdateService", "UserInFo");
        
                // 在Call对象中注册自定义类型
call.registerTypeMapping(UserInFo.class, qn, new org.apache.axis.encoding.ser.BeanSerializerFactory(UserInFo.class,
qn), new org.apache.axis.encoding.ser.BeanDeserializerFactory(
UserInFo.class, qn)); // 设置输入参数类型
call.addParameter("p1", XMLType.XSD_STRING, ParameterMode.IN);
// 设置返回值类型
call.setReturnType(XMLType.XSD_ANYTYPE); String sql = null;
if(userid.equals("all")){
sql = "select * from user";
}else{
sql = "select * from user where user_ID='" + userid+ "'";
}

Vector msg = (Vector) call.invoke("Select",new Object[] {sql});
return msg; }
在客户端,首先为UserInFo定义一个QName对象,构造函数中的第一个参数值要和wsdd中beanMapping节点的xmlns:myNS属性值相同,第二个参数值要和beanMapping的qname属性值相同。然后在Call对象中注册自定义类型所用的序列化和反序列化器。通过以下语句来实现:
call.registerTypeMapping(UserInFo.class, qn,
                      new org.apache.axis.encoding.ser.BeanSerializerFactory(UserInFo.class, qn),        
                      new org.apache.axis.encoding.ser.BeanDeserializerFactory(UserInFo.class, qn));以上就是自定义类型方法的调用。

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【tony840101】截止到2008-07-31 01:05:24的历史汇总数据(不包括此帖):
    发帖的总数量:1                        发帖的总分数:20                       每贴平均分数:20                       
    回帖的总数量:1                        得分贴总数量:0                        回帖的得分率:0%                       
    结贴的总数量:0                        结贴的总分数:0                        
    无满意结贴数:0                        无满意结贴分:0                        
    未结的帖子数:1                        未结的总分数:20                       
    结贴的百分比:0.00  %               结分的百分比:0.00  %                  
    无满意结贴率:---------------------无满意结分率:---------------------
    如何结贴请参考这里:http://topic.csdn.net/u/20080501/09/ef7ba1b3-6466-49f6-9d92-36fe6d471dd1.html

    取消马甲机器人,请点这里:http://www.java2000.net/mycsdn/robotStop.jsp?usern=tony840101