posts - 64,  comments - 9,  trackbacks - 0

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

关键字: webservice axis throw customer exception

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

 

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

Sql代码 复制代码
  1. create table users(id integer primary keyname varchar(20) not null);   
  2.     
  3. insert into users values(1, 'Lincoln'),(2, 'Michael'),(4, 'Mahone'),(6, 'Sara');  

 

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

Java代码 复制代码
  1. package com.chnic.bean;   
  2.   
  3. public class UserBean implements java.io.Serializable{   
  4.   
  5.     private static final long serialVersionUID = 1L;   
  6.     private int id;   
  7.     private String name;   
  8.        
  9.     public UserBean(){   
  10.            
  11.     }   
  12.     public int getId() {   
  13.         return id;   
  14.     }   
  15.     public void setId(int id) {   
  16.         this.id = id;   
  17.     }   
  18.     public String getName() {   
  19.         return name;   
  20.     }   
  21.     public void setName(String name) {   
  22.         this.name = name;   
  23.     }   
  24. }  

 

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

Java代码 复制代码
  1. package com.chnic.exception;   
  2.   
  3. import java.rmi.RemoteException;   
  4.   
  5. public class NoSuchUserException extends RemoteException {   
  6.   
  7.     private String errorMessage = "No such user: ";   
  8.     private int id;   
  9.     private static final long serialVersionUID = 1L;   
  10.   
  11.     public NoSuchUserException() {   
  12.     }   
  13.   
  14.     public void printErrorMessage(){   
  15.         System.out.println(errorMessage + id);   
  16.     }   
  17.   
  18.     public int getId() {   
  19.         return id;   
  20.     }   
  21.   
  22.     public void setId(int id) {   
  23.         this.id = id;   
  24.     }   
  25. }  

 

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

Java代码 复制代码
  1. package com.chnic.webservice;   
  2.   
  3. import java.sql.Connection;   
  4. import java.sql.PreparedStatement;   
  5. import java.sql.ResultSet;   
  6. import java.sql.SQLException;   
  7.   
  8. import com.chnic.bean.UserBean;   
  9. import com.chnic.exception.NoSuchUserException;   
  10. import java.sql.DriverManager;   
  11.   
  12. public class CheckUserInfo {   
  13.     private String url = "jdbc:mysql://localhost:3306/test";   
  14.     private String user = "root";   
  15.     private String password = "root";   
  16.        
  17.        
  18.     public CheckUserInfo(){    
  19.            
  20.     }   
  21.        
  22.     public Connection getConn(){   
  23.         try {   
  24.             Class.forName("com.mysql.jdbc.Driver");   
  25.             return DriverManager.getConnection(url, user, password);   
  26.         } catch (ClassNotFoundException e) {   
  27.             e.printStackTrace();   
  28.         } catch (SQLException e) {   
  29.             e.printStackTrace();   
  30.         }   
  31.         return null;   
  32.     }   
  33.        
  34.     public UserBean checkUser(int id) throws NoSuchUserException{   
  35.         Connection conn = null;   
  36.         try {   
  37.             conn = this.getConn();   
  38.             PreparedStatement statement =    
  39.                 conn.prepareStatement("select * from users where id = ?");   
  40.             statement.setInt(1, id);   
  41.             ResultSet rs = statement.executeQuery();   
  42.             boolean flag = false;   
  43.             UserBean user = null;   
  44.                 
  45.             while(rs.next()){   
  46.                 flag = true;   
  47.                 user = new UserBean();   
  48.                 user.setId(id);   
  49.                 user.setName(rs.getString(2));   
  50.             }   
  51.             rs.close();   
  52.             if(flag)   
  53.                 return user;   
  54.             else{   
  55.                 NoSuchUserException userException = new NoSuchUserException();   
  56.                 userException.setId(id);   
  57.                    
  58.                 throw userException;   
  59.             }   
  60.         } catch (SQLException e) {   
  61.             e.printStackTrace();   
  62.         }finally{   
  63.             this.closeConn(conn);   
  64.         }   
  65.         return null;   
  66.     }   
  67.        
  68.     public void closeConn(Connection conn){    
  69.         try {   
  70.             conn.close();   
  71.         } catch (SQLException e) {   
  72.             e.printStackTrace();   
  73.         }   
  74.     }   
  75. }  
 

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

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

 

Xml代码 复制代码
  1. <deployment xmlns="http://xml.apache.org/axis/wsdd/"    
  2.     xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">  
  3.        
  4.     <service name="AxisExceptionTest" provider="java:RPC">  
  5.         <namespace>http://faults.samples</namespace>  
  6.         <parameter name="className" value="com.chnic.webservice.CheckUserInfo"/>  
  7.         <parameter name="allowedMethods" value="checkUser"/>  
  8.         <parameter name="scope" value="Session"/>  
  9.            
  10.         <operation name="checkUser"    
  11.                    qname="operNS:checkUser"    
  12.                    xmlns:operNS="getSingleUser"    
  13.                    returnQName="getUserReturn"    
  14.                    returnType="rtns:User"    
  15.                    xmlns:rtns="http://faults.samples" >  
  16.                       
  17.             <parameter name="id" type="tns:int"    
  18.                 xmlns:tns="http://www.w3.org/2001/XMLSchema"/>              
  19.             <fault name="NoSuchEmployeeFault"    
  20.                    qname="fns:fault"    
  21.                    xmlns:fns="http://faults.samples"    
  22.                    class="samples.faults.NoSuchEmployeeFault"    
  23.                    type="tns:NoSuchUserFault"    
  24.                    xmlns:tns="http://faults.samples"/>  
  25.         </operation>  
  26.            
  27.                       
  28.         <typeMapping qname="myns:NoSuchUserFault"    
  29.             xmlns:myns="urn:CustomerFault"  
  30.             type="java:com.chnic.exception.NoSuchUserException"  
  31.             serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"  
  32.             deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"  
  33.             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>  
  34.            
  35.         <typeMapping qname="myns:User"  
  36.             xmlns:myns="urn:CustomerBean"  
  37.             type="java:com.chnic.bean.UserBean"  
  38.             serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"  
  39.             deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"  
  40.             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>  
  41.     </service>  
  42. </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都是类似,对以一下大概就知道什么意思了。在这里也不多解释了。现在来看测试代码。

 

Java代码 复制代码
  1. package com.chnic.test;   
  2.   
  3. import java.rmi.RemoteException;   
  4.   
  5. import javax.xml.namespace.QName;   
  6. import javax.xml.rpc.Call;   
  7. import javax.xml.rpc.Service;   
  8. import javax.xml.rpc.ServiceException;   
  9. import javax.xml.rpc.ServiceFactory;   
  10. import javax.xml.rpc.encoding.TypeMapping;   
  11. import javax.xml.rpc.encoding.TypeMappingRegistry;   
  12.   
  13. import org.apache.axis.encoding.ser.BeanDeserializerFactory;   
  14. import org.apache.axis.encoding.ser.BeanSerializerFactory;   
  15.   
  16. import com.chnic.bean.UserBean;   
  17. import com.chnic.exception.NoSuchUserException;   
  18.   
  19.   
  20. public class TestException {   
  21.   
  22.     public static void main(String[] args){   
  23.         String uri = "http://faults.samples";   
  24.         String serviceName = "EmployeeInfoService";   
  25.         ServiceFactory serviceFactory;   
  26.         String url = "http://localhost:8080/axis/services/AxisExceptionTest";   
  27.         try {   
  28.             serviceFactory = ServiceFactory.newInstance();   
  29.             QName serQ = new QName(uri, serviceName);   
  30.             Service service = serviceFactory.createService(serQ);   
  31.                
  32.             TypeMappingRegistry registry = service.getTypeMappingRegistry();   
  33.             TypeMapping map = registry.getDefaultTypeMapping();   
  34.                            
  35.             QName employeeQName = new QName("urn:CustomerBean""User");   
  36.             map.register(UserBean.class, employeeQName,    
  37.                 new BeanSerializerFactory(UserBean.class, employeeQName),    
  38.                 new BeanDeserializerFactory(UserBean.class, employeeQName));   
  39.   
  40.             QName faultQName = new QName("urn:CustomerFault""NoSuchUserFault");   
  41.             map.register(NoSuchUserException.class, faultQName,    
  42.                 new BeanSerializerFactory(NoSuchUserException.class, faultQName),    
  43.                 new BeanDeserializerFactory(NoSuchUserException.class, faultQName));   
  44.                        
  45.             Call call = service.createCall();   
  46.             call.setTargetEndpointAddress(url);   
  47.                
  48.             call.setOperationName( new QName(uri, "checkUser") );   
  49.             Object obj = call.invoke(new Object[]{ new Integer(3)});   
  50.             UserBean user = (UserBean) obj;   
  51.             System.out.println(user.getName());   
  52.                            
  53.         } catch (ServiceException e) {   
  54.             e.printStackTrace();   
  55.         }catch(NoSuchUserException e){   
  56.             e.printErrorMessage();   
  57.         }catch (RemoteException e) {           
  58.             e.printStackTrace();   
  59.         }   
  60.     }   
  61. }  

 

看到第一个申明的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的名字。在这里就不测试了。各位自己可以试试。

posted on 2009-07-03 18:45 super_nini 阅读(605) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航:
 
<2009年7月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿

随笔档案

文章档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜