挠痒痒的专栏

彪悍的人生不需要解释

用户操作
[即时聊天] [发私信] [加为好友]
挠痒痒ID:chnic
1430次访问,排名2万外,好友3人,关注者7人。
彪悍的人生不需要解释
chnic的文章
原创 8 篇
翻译 0 篇
转载 0 篇
评论 4 篇
挠痒痒的公告
写Blog主要为了沉淀一下自己的所学。这里的博文都是从我的另一博客copy来的。http://chnic.javaeye.com
最近评论
yong_shang808808:D:\jboss-4.2.1.GA\server\default\deploy\axisfile.war\WEB-INF>java org.apache.ax
is.client.AdminClient deploy.wsdd
Processing file deploy.wsdd
Exception: AxisFault
faultCode……
chnic:不好意思,源代码blog上面都有的。
你可以自己copy. 我基本上是在一份源代码上做的所有东西。
wsdd 还有一些相关文件早就改的面目全非了。
你照着我的步骤一步一步来 不会出错的。
singlesword2007:写的不错!深入而且易懂,期待下一篇!
allisgone:可以发一个完整的例子给我吗?发到邮箱里,谢了
文章分类
收藏
    相册
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 利用AXIS开发Webservice(四) —— 如何抛出自定义异常收藏

    新一篇: 利用AXIS开发Webservice(五) —— 如何传递文件 | 旧一篇: 用JDK+记事本来完成一个无状态SessionBean

    今天进入AXIS之四,如何抛出一个你的自定义异常。本来想连传文件一起介绍的。后来感觉一篇blog里太多的内容也不太好,看起来太辛苦,还是慢慢来,废话不多进入正题。

    上一篇介绍了如果在Server和Client端传递一个自己的对象。有些人也许会问传递异常行不行?答案是可以。只不过传递异常的配置要稍微复杂一些。空口无凭,我还是用点代码来说明。今天的例子稍微复杂点,用一下数据库(MySQL)。首先创建表和输入测试数据。

    create table users(id integer primary key, name varchar(20not null);
     
    insert into users values(1'Lincoln'),(2'Michael'),(4'Mahone'),(6'Sara');

    一个user表,4条记录。等会我们client段会发送一个SOAP request给server段,之后server段返回客户要的数据,如果没有则抛出一个自定义异常。表建立完成之后来编写JavaBean。

    package com.chnic.bean;

    public class UserBean implements java.io.Serializable{

        
    private static final long serialVersionUID = 1L;
        
    private int id;
        
    private String name;
        
        
    public UserBean(){
            
        }

        
    public int getId() {
            
    return id;
        }

        
    public void setId(int id) {
            
    this.id = id;
        }

        
    public String getName() {
            
    return name;
        }

        
    public void setName(String name) {
            
    this.name = name;
        }

    }


    Bean有两个属性,Id和Name。client会根据ID来取要的Name。编写完Bean之后我们来编写Customer Exception的代码。

    package com.chnic.exception;

    import java.rmi.RemoteException;

    public class NoSuchUserException extends RemoteException {

        
    private String errorMessage = "No such user: ";
        
    private int id;
        
    private static final long serialVersionUID = 1L;

        
    public NoSuchUserException() {
        }


        
    public void printErrorMessage(){
            System.out.println(errorMessage 
    + id);
        }


        
    public int getId() {
            
    return id;
        }


        
    public void setId(int id) {
            
    this.id = id;
        }

    }

    NoSuchUserException这个类会记录在数据库没有相应数据的ID的值,然后返回给Client。值得注意的是,因为这个是个远程异常。所 以要继承RemoteException这个类。两个要transfer的Bean完成之后。我们来编写Service Ojbect的代码。

    package com.chnic.webservice;

    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;

    import com.chnic.bean.UserBean;
    import com.chnic.exception.NoSuchUserException;
    import java.sql.DriverManager;

    public class CheckUserInfo {
        
    private String url = "jdbc:mysql://localhost:3306/test";
        
    private String user = "root";
        
    private String password = "root";
        
        
        
    public CheckUserInfo(){    
            
        }

        
        
    public Connection getConn(){
            
    try {
                Class.forName(
    "com.mysql.jdbc.Driver");
                
    return DriverManager.getConnection(url, user, password);
            }
     catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
     catch (SQLException e) {
                e.printStackTrace();
            }

            
    return null;
        }

        
        
    public UserBean checkUser(int id) throws NoSuchUserException{
            Connection conn 
    = null;
            
    try {
                conn 
    = this.getConn();
                PreparedStatement statement 
    = 
                    conn.prepareStatement(
    "select * from users where id = ?");
                statement.setInt(
    1, id);
                ResultSet rs 
    = statement.executeQuery();
                
    boolean flag = false;
                UserBean user 
    = null;
                 
                
    while(rs.next()){
                    flag 
    = true;
                    user 
    = new UserBean();
                    user.setId(id);
                    user.setName(rs.getString(
    2));
                }

                rs.close();
                
    if(flag)
                    
    return user;
                
    else{
                    NoSuchUserException userException 
    = new NoSuchUserException();
                    userException.setId(id);
                    
                    
    throw userException;
                }

            }
     catch (SQLException e) {
                e.printStackTrace();
            }
    finally{
                
    this.closeConn(conn);
            }

            
    return null;
        }

        
        
    public void closeConn(Connection conn){    
            
    try {
                conn.close();
            }
     catch (SQLException e) {
                e.printStackTrace();
            }

        }

    }

    因为是Demo代码,代码写的比较粗糙,反正就是为了个演示。大家能看出来效果就好了。代码很简单,接收到一个id,然后在数据库里做匹配。如果找到匹配的了返回那个userbean,如果没找到就throw一个Exception出去。在这里多嘴一句。传递的Bean赋值的时候一定要用setXXX方法,不能用构造函数传递,否则传递过去之后属性值会丢失。 你编写的那个Bean一定要严格遵循JavaBean规范。 

    之后我们来看WSDD发布文件。比起之前我们看到的WSDD文件,这次的稍微有点点复杂。

    <deployment xmlns="http://xml.apache.org/axis/wsdd/" 
        xmlns:java
    ="http://xml.apache.org/axis/wsdd/providers/java">
        
        
    <service name="AxisExceptionTest" provider="java:RPC">
               
    <namespace>http://faults.samples</namespace>
            
    <parameter name="className" value="com.chnic.webservice.CheckUserInfo"/>
            
    <parameter name="allowedMethods" value="checkUser"/>
            
    <parameter name="scope" value="Session"/>
            
            
    <operation name="checkUser" 
                       qname
    ="operNS:checkUser" 
                       xmlns:operNS
    ="getSingleUser" 
                       returnQName
    ="getUserReturn" 
                       returnType
    ="rtns:User" 
                       xmlns:rtns
    ="http://faults.samples" >
                       
                   
    <parameter name="id" type="tns:int" 
                       xmlns:tns
    ="http://www.w3.org/2001/XMLSchema"/>             
                   
    <fault name="NoSuchEmployeeFault" 
                          qname
    ="fns:fault" 
                          xmlns:fns
    ="http://faults.samples" 
                          class
    ="samples.faults.NoSuchEmployeeFault" 
                          type
    ="tns:NoSuchUserFault" 
                          xmlns:tns
    ="http://faults.samples"/>
            
    </operation>
            
                       
            
    <typeMapping qname="myns:NoSuchUserFault" 
                xmlns:myns
    ="urn:CustomerFault"
                type
    ="java:com.chnic.exception.NoSuchUserException"
                serializer
    ="org.apache.axis.encoding.ser.BeanSerializerFactory"
                deserializer
    ="org.apache.axis.encoding.ser.BeanDeserializerFactory"
                encodingStyle
    ="http://schemas.xmlsoap.org/soap/encoding/"/>
            
            
    <typeMapping qname="myns:User"
                  xmlns:myns
    ="urn:CustomerBean"
                   type
    ="java:com.chnic.bean.UserBean"
                   serializer
    ="org.apache.axis.encoding.ser.BeanSerializerFactory"
                   deserializer
    ="org.apache.axis.encoding.ser.BeanDeserializerFactory"
                   encodingStyle
    ="http://schemas.xmlsoap.org/soap/encoding/"/>
        
    </service>
    </deployment>

    首先不同的是多了个命名空间也就是namespace节点,等会测试代码中会看到用途。除了namespace之外还有operation这个节点和里面的parameter和fault子节点。先来介绍operation这个节点的属性。

    name:操作名称或者方法名称,这个值会和你server发布的相关方法名匹配,所以要和方法名相同。

    qname:针对这个operation的限定名。

    xmlns:针对这个qname的命名空间也就是namespace。(不明白的可以看上一篇博文)

    returnQName:这个元素节点所对应的方法返回出来对象的Qname。

    returnType:返回类型,注意和下面的typemapping的qname比较。

    parameter 节点是这个operation指代的方法的参数,fault节点代表要这个方法要抛出的异常。异常也需要被mapping。下面的typemapping 做的也是这样的事情。这两个元素的节点的属性和operation都是类似,对以一下大概就知道什么意思了。在这里也不多解释了。现在来看测试代码。

    package com.chnic.test;

    import java.rmi.RemoteException;

    import javax.xml.namespace.QName;
    import javax.xml.rpc.Call;
    import javax.xml.rpc.Service;
    import javax.xml.rpc.ServiceException;
    import javax.xml.rpc.ServiceFactory;
    import javax.xml.rpc.encoding.TypeMapping;
    import javax.xml.rpc.encoding.TypeMappingRegistry;

    import org.apache.axis.encoding.ser.BeanDeserializerFactory;
    import org.apache.axis.encoding.ser.BeanSerializerFactory;

    import com.chnic.bean.UserBean;
    import com.chnic.exception.NoSuchUserException;


    public class TestException {

        
    public static void main(String[] args){
            String uri 
    = "http://faults.samples";
            String serviceName 
    = "EmployeeInfoService";
            ServiceFactory serviceFactory;
            String url 
    = "http://localhost:8080/axis/services/AxisExceptionTest";
            
    try {
                serviceFactory 
    = ServiceFactory.newInstance();
                QName serQ 
    = new QName(uri, serviceName);
                Service service 
    = serviceFactory.createService(serQ);
                
                TypeMappingRegistry registry 
    = service.getTypeMappingRegistry();
                TypeMapping map 
    = registry.getDefaultTypeMapping();
                            
                QName employeeQName 
    = new QName("urn:CustomerBean""User");
                map.register(UserBean.
    class, employeeQName, 
                    
    new BeanSerializerFactory(UserBean.class, employeeQName), 
                    
    new BeanDeserializerFactory(UserBean.class, employeeQName));

                QName faultQName 
    = new QName("urn:CustomerFault""NoSuchUserFault");
                map.register(NoSuchUserException.
    class, faultQName, 
                    
    new BeanSerializerFactory(NoSuchUserException.class, faultQName), 
                    
    new BeanDeserializerFactory(NoSuchUserException.class, faultQName));
                        
                Call call 
    = service.createCall();
                call.setTargetEndpointAddress(url);
                
                call.setOperationName( 
    new QName(uri, "checkUser") );
                Object obj 
    = call.invoke(new Object[]new Integer(3)});
                UserBean user 
    = (UserBean) obj;
                System.out.println(user.getName());
                            
            }
     catch (ServiceException e) {
                e.printStackTrace();
            }
    catch(NoSuchUserException e){
                e.printErrorMessage();
            }
    catch (RemoteException e) {        
                e.printStackTrace();
            }

        }

    }

    看到第一个申明的uri了么?我们通过这个uri和service来取得对应的service。 之后我们用TypeMappingRegistry得到一个默认的TypeMapping。在map里面映射我们的bean。之后和往常的代码一样没有特 别的。invoke唤起方法,返回UserBean,并打出UserBean的name。值得注意的是后面的catch部分,我们catch了一个我们自 己申明的NoSuchUserException,抓住这个异常之后打出我们要的错误信息。

    因为1 2 4 6在数据库里都是有对应的数值的,所以当我要查找ID为3个user的name的时候,service就会返回一个NoSuchUserException给我。之后在本地抓住这个exception之后,控制台打出了如下信息。

    No such user: 3

    如果输入的是1 2 4 6的话,则会返回user的名字。在这里就不测试了。各位自己可以试试。

     

     


     


    发表于 @ 2008年04月02日 02:41:00|评论(loading...)|编辑

    新一篇: 利用AXIS开发Webservice(五) —— 如何传递文件 | 旧一篇: 用JDK+记事本来完成一个无状态SessionBean

    评论

    #singlesword2007 发表于2008-04-08 11:39:11  IP: 61.183.248.*
    写的不错!深入而且易懂,期待下一篇!
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 挠痒痒