webservice系列1---基于web工程上写一个基本数据类型的webservic
本节摘要:之前在一篇博客中介绍过如何写一个webservice(http://www.cnblogs.com/java-pan/archive/2011/11/25/axis_webservice.html),不过那个webservice是在工作项目中直接添加的,中间少了很多麻烦,不是白手起家总感觉前面一步一步的过程不清楚。myeclipse自带的也有如何新建一个webservice工程,这也不是我要说的,项目中这个也不实用,项目中都是在当前开发的web工程中写一个webservice,谁会再去新建一个工程,那不是扯淡吗?本节在一个已经存在的web工程中,来新建类、新建配置文件,发布webservice、访问webservice。基于axis1.4的版本来完成的。 preparation1.在阅读本机之前你需要看以下相关知识:JDBC; JDBC的介绍这里就不说了,网上忒多的资料了,这个也是做java接触数据库时必会的 ibatis; 可以参考我之前的博客http://www.cnblogs.com/java-pan/archive/2012/03/21/ibatis.html XStream; 可以参考我之前的博客http://www.cnblogs.com/java-pan/archive/2011/10/25/Object_xml.html axis; 可以参考我之前的博客http://www.cnblogs.com/java-pan/archive/2011/11/25/axis_webservice.html 2.项目结构myeclipse:6.5? tomcat:5.0? system:win7 JDK:项目的版本是1.5 编译采用的是1.4?
说明:本节介绍的是基于axis的webservice,采用的版本为axis1.4 3.下载项目中用到的jar包?http://files.cnblogs.com/java-pan/lib-axis1.4.rar 以上链接包含下面的所有包。下载的jar包主要包含以下几部分: (1)oracle数据库驱动包 :classes12.jar (2)ibatis包:ibatis-2.3.4.jar (3)xstream-1.2.1.jar (4)axis包(从以下链接下载http://mirror.bjtu.edu.cn/apache/ws/axis/1_4/?下载后解压把lib下所有包导入) (5)activation.jar和mail.jar 建议导入的包 以上除最后一个jar包外,其它的程序运行必须导入。(可能axis不需要导入所有的包,不过我们就全部导入好了) 项目jar包的详细列表如下:
说明:lib下一共中13个jar包,截图的图片也有13个jar包,但是博客发布后显示的只有8个jar包,可以图片另存为看到所有的jar包。 4.class&mthodJDBC:DriverManager、Connection、PreparedStatement、ResultSet DriverManager: getConnection(String url,String user,String password)获得一个Connection对象,参数依次为数据库驱动的url、用户名、密码 Connection: prepareStatement(String sql)获得一个预处理对象PreparedStatement PreparedStatement: executeQuery()执行查询操作,返回一个结果集对象ResultSet,不要传入任何参数 ResultSet: next()返回一个布尔类型的值,用于判断是否还有记录 ? Ibatis:SqlMapClient、SqlMapClientBuilder SqlMapClient: SqlMapClient buildSqlMapClient(Reader reader)传入一个reader对象,创建一个SqlMapClient 对象 startTransaction();开始事务 getCurrentConnection()获取当前连接,回滚事务的时候用到 endTransaction结束事务 SqlMapClientBuilder: queryForObject(String s,Object obj)第一个参数为实体类对应的配置文件的id属性,第二个为传入的参数,此方法的返回值是一个Object对象 ? xstream:XStream XStream: alias(String name,Class type)设置节点的别名 alias(String name,Class type)设置某一元素节点的别名 toXML(Object obj)把对应的obj转换为xml格式的字符串 ? 其他类:Reader、Resources、StringBuffer Reader:java I/O对象,用于读取字符流的抽象类,这里就不再介绍,请查看JDK帮助文档 Resources:此类为ibatis的jar包中的类,非JDK的类 getResourceAsReader(String resource)对于resource路径的文件,获得一个Reader对象 StringBuffer:线程安全的可变字符序列 ? start新建一个web工程,项目命名为WebService,按照工程目录新建对应的文件如下: 实体类-Dept.java 1 package com.bean; 2 3 /** 4 * 5 *Module: Dept.java 6 *Description: 写一个oracle数据库自带的部门表dept的javabean 7 *Company: 8 *Author: pantp 9 *Date: May 1,2012 10 */ 11 public class Dept { 12 int deptNo; 13 public String dName; 14 public String loc; 15 16 int getDeptNo() { 17 return deptNo; 18 } 19 20 void setDeptNo(int deptNo) { 21 this.deptNo = deptNo; 22 } 23 24 public String getDName() { 25 return dName; 26 } 27 28 void setDName(String name) { 29 dName = name; 30 } 31 32 public String getLoc() { 33 return loc; 34 } 35 36 void setLoc(String loc) { 37 this.loc = loc; 38 } 39 } 数据库连接文件-ConnectDataBase.java package com.cn; import java.io.IOException; import java.io.Reader; 5 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; 9 10 import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; 12 import com.ibatis.sqlmap.client.SqlMapClientBuilder; 13 14 15 16 *Module: ConnectDataBase.java 17 *Description: 数据库连接类,采用两种方式:1.JDBC 2.Ibatis框架 18 19 20 21 22 class ConnectDataBase { //采用JDBC的方式连接数据 25 private final static String USERNAME = "scott"; 26 static String PASSWORD = "orcl"; 27 static String URL = "jdbc:Oracle:thin:@localhost:1521:orcl"; static String DRIVER = "oracle.jdbc.driver.OracleDriver"; 29 static Connection conn = null; 30 31 获取连接 static { 加载驱动 34 try { 35 Class.forName(DRIVER); 36 } catch (ClassNotFoundException e) { 37 e.printStackTrace(); 38 } 39 获得连接对象conn 40 41 conn = DriverManager.getConnection(URL,USERNAME,PASSWORD); 42 } catch (SQLException e) { 43 e.printStackTrace(); 44 } 45 } 46 47 提供一个方法供外部调用,获得JDBC连接对象conn 48 static Connection getConnection() { 49 return conn; 50 } 51 52 53 定义ibatis映射文件的位置,写配置文件的完整路径 54 static String resource = "com/ibatis/SqlMapConfig.xml"; 55 static SqlMapClient sqlMapClient = 56 57 58 Reader reader = Resources.getResourceAsReader(resource); 59 sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader); 60 reader.close(); 61 } catch (IOException e) { 62 e.printStackTrace(); 63 } 64 } 65 66 提供一个方法供外部调用,获得Ibatis的连接对象sqlMapClient 67 static SqlMapClient getSqlMapClient(){ 68 return sqlMapClient; 69 } 70 71 72 } 实体类对应的映射文件-Dept.xml <?xml version="1.0" encoding="UTF-8"?> 2 <!-- author:pantp date:2012/05/01 description:javabean对应的xml配置文件 --> <!DOCTYPE sqlMap 8 PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" 9 "http://ibatis.apache.org/dtd/sql-map-2.dtd"> 10 <sqlMaptypeAlias alias="Dept" type="com.bean.Dept" /> <!-- 精确查询 按照条件查询记录 按照部门编号DEPTNO查询 15 select parameterClass="int" resultClass id="selectById"16 select deptno,dname,loc from dept where deptno=#deptNo# 17 </select18 > 数据库连接属性文件-SqlMap.properties 1 driver=oracle.jdbc.driver.OracleDriver 2 url=jdbc:Oracle:thin:@127.0.0.1:1521:orcl 3 username=scott 4 password=orcl ibatis核心配置文件-SqlMapConfig.xml description:Ibatis框架的核心配置文件,主要是数据库连接属性文件和实体类和表的映射文件引入进来 DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"sqlMapConfig12 数据库连接的属性文件 properties resource="com/ibatis/SqlMap.properties" transactionManager type="JDBC"16 dataSource ="SIMPLE"17 property value="${driver}" name="JDBC.Driver" 18 ="${url}"="JDBC.ConnectionURL" 19 ="${username}"="JDBC.Username" 20 ="${password}"="JDBC.Password" dataSource22 transactionManager 实体类和数据库表的映射 sqlMap ="com/ibatis/Dept.xml" 26 27 > 定义查询服务的接口文件-IQueryInfoSV.java package com.interfaces; 4 *Module: IQueryInfoSV.java *Description: 定义查询的接口 12 13 interface IQueryInfoSV { 14 JDBC abstract String queryDept1(int deptNo) throws SQLException; 17 18 ibatis 19 abstract String queryDept2(20 21 } 定义查询服务的实现类-QueryInfoSVImpl.java 1 package com.impl; 2 3 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import com.bean.Dept; 7 import com.cn.ConnectDataBase; 8 9 import com.interfaces.IQueryInfoSV; 10 import com.thoughtworks.xstream.XStream; 11 import com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer; 12 import com.thoughtworks.xstream.io.xml.XppDriver; 13 14 15 16 17 18 *Module: QueryInfoSVImpl.java 19 *Description: 根据部门编号查询oracle自带的dept表,提供两种查询方式:1.JDBC 2.Ibatis 20 21 22 23 24 class QueryInfoSVImpl implements IQueryInfoSV { 25 26 采用JDBC方式连接数据库的查询操作 27 public String queryDept1(throws SQLException { 28 获取JDBC的连接 29 Connection conn = ConnectDataBase.getConnection(); 30 拼装SQL语句 31 String sql = "select deptno,loc from dept where deptno=" + deptNo; 32 获得预处理对象pst 33 PreparedStatement pst = conn.prepareStatement(sql); 34 查询结果集 35 ResultSet rs = pst.executeQuery(); 36 37 采用next()方法取得数据库数据,deptNo是逐渐采用deptNo查询,要么没有查到数据,要么只能查到一条数据 38 String result = ""; 39 Dept dept = 40 while (rs.next()) { 41 dept = new Dept(); 42 dept.deptNo = deptNo; 43 dept.dName = rs.getString("dName"); 44 dept.loc = rs.getString("loc"); 45 } 46 result = getXML(dept); 47 return result; 48 } 49 50 采用ibatis连接数据库并按部门编号精确查找 51 public String queryDept2( 52 获得ibatis的连接对象sqlMapClient 53 SqlMapClient sqlMapClient = ConnectDataBase.getSqlMapClient(); 54 Dept dept = 55 56 sqlMapClient.startTransaction(); 开始事务 57 执行查询 此处的"selectById"对应Dept.xml文件中select标签的id属性 58 dept = (Dept) sqlMapClient.queryForObject("selectById", 59 new Integer(deptNo)); 60 sqlMapClient.commitTransaction(); 提交事务 61 } 62 63 sqlMapClient.getCurrentConnection().rollback(); 回滚事务 64 } catch (SQLException e1) { 65 e1.printStackTrace(); 66 } 67 e.printStackTrace(); 68 } finally { 69 70 sqlMapClient.endTransaction(); 结束事务 71 } 72 e.printStackTrace(); 73 } 74 } 75 组装xml报文并返回 76 return getXML(dept); 77 } 78 79 采用XStream方式组装XML 80 static String getXML(Dept dept) { 81 用于保存XML的内容 82 String xmlbody = ""; 83 用于保存XML的头部 84 String xmlhead = "<?xml version="1.0" encoding="UTF-8"?>n"; 85 86 if (null != dept) { 87 构造一个xstream对象,此种构造方式解决下划线站两个字符的问题 88 XStream xstream = new XStream(new XppDriver( 89 new XmlFriendlyReplacer("-_","_"))); 90 91 设置别名,不设置的话显示为Dept_Info显示为com.bean.Dept 92 xstream.alias("DEPT_INFO",Dept.class); 93 xstream.aliasField("DEPTNO",255); line-height:1.5!important">class,"deptNo"); 94 xstream.aliasField("DNAME","dName"); 95 xstream.aliasField("LOC","loc"); 96 97 把实体类转换为XML 98 xmlbody = xstream.toXML(dept); 99 } else { 100 处理根据编号没有查询到数据的情况 101 StringBuffer sb = new StringBuffer(); 102 sb 103 .append("<DEPT_INFO><DEPTNO></DEPTNO><DNAME></DNAME><LOC></LOC></DEPT_INFO>"); 104 xmlbody = sb.toString(); 105 } 106 return xmlhead + xmlbody; 107 } 108 } 测试类-Test1.java?用于测试JDBC和ibatis的数据库连接是否正常 package com.test; import com.impl.QueryInfoSVImpl; 6 *Module: Test1.java *Description: 测试JDBC和Ibatis数据库查询是否正常 *Author: ptp 14 class Test1 { 16 测试数据库是可以正常查询 static void main(String[] args) 19 int deptNo = 10; 20 test1(deptNo); 21 test2(deptNo); 测试JDBC方式连接数据库是否正常 void test1(26 IQueryInfoSV query = new QueryInfoSVImpl(); 27 String dept = query.queryDept1(deptNo); 28 29 System.out 30 .println("n===============采用JDBC方式查询数据库连接正常 author<pantp>=======n"); 31 System.out.println(dept); 32 System.out 33 .println("n===============采用JDBC方式查询数据库连接正常==================n"); 测试ibatis方式连接数据库是否正常 37 void test2(38 IQueryInfoSV query = 39 String dept = query.queryDept2(deptNo); 40 41 System.out 42 .println("n===============采用ibatis方式查询数据库连接正常 author<pantp>========n"); 43 System.out.println(dept); 44 System.out 45 .println("n===============采用ibatis方式查询数据库连接正常==================n"); 46 } 47 48 } 测试类-Test2.java?用于测试webservice服务是否可以正常调用 import java.net.MalformedURLException; import java.net.URL; import java.rmi.RemoteException; import javax.xml.rpc.ParameterMode; import javax.xml.rpc.ServiceException; import org.apache.axis.client.Call; import org.apache.axis.encoding.XMLType; *Module: Test2.java *Description: 项目中常用调用webservice方式有两种,stub桩的形式和动态调用,本次测试就用动态调用的方式 20 21 class Test2 { 22 23 调用webservice void main(String[] args) { 25 test2(); 27 29 * 动态调用接口访问webservice服务的步骤如下: 30 * 1.创建service对象 31 * 2.创建url对象 32 * 3.创建call对象, 33 * 4.调用webservice的方法 34 * 5.处理返回结果 35 void test2() { 38 1.创建service对象,通过axis自带的类创建 39 org.apache.axis.client.Service service = new org.apache.axis.client.Service(); 41 2.创建url对象 42 String wsdlUrl = "http://127.0.0.1:8080/WebService/services/queryInfo?WSDL"; 请求服务的URL 43 URL url = new URL(wsdlUrl); 通过URL类的构造方法传入wsdlUrl地址创建URL对象 44 45 2.创建服务方法的调用者对象call,设置call对象的属性 46 Call call = (Call) service.createCall(); 47 call.setTargetEndpointAddress(url); 给call对象设置请求的URL属性 48 String serviceName = "queryDept2";webservice的方法名 49 call.setOperationName(serviceName); 给call对象设置调用方法名属性 50 call.addParameter("deptNo",XMLType.XSD_INT,ParameterMode.IN); 给call对象设置方法的参数名、参数类型、参数模式 51 call.setReturnType(XMLType.SOAP_STRING); 设置调用方法的返回值类型 52 call.setTimeout(new Integer(5000));设置超时限制 53 54 4.通过invoke方法调用webservice 55 Integer deptNo = new Integer(50); 56 String dept = (String) call.invoke(new Object[] { deptNo }); 调用服务方法 57 58 5.打印返回结果 59 System.out 60 .println("n===============调用webservice成功(无安全机制) author<pantp>=======n"); 61 System.out.println(dept); 62 System.out 63 .println("n===============调用webservice成功(无安全机制)==================n"); 64 65 } catch (MalformedURLException e) { 66 e.printStackTrace(); 67 } catch (ServiceException e) { 68 e.printStackTrace(); 69 } catch (RemoteException e) { 70 e.printStackTrace(); 71 } 72 } 73 74 } web.xml-项目配置文件 web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 6 servlet 7 servlet-name>AxisServlet 8 servlet-class>org.apache.axis.transport.http.AxisServlet 9 10 servlet-mapping11 12 url-pattern>/services/*mime-mapping15 extension>wsdlmime-type>text/xml>xsd20 21 23 web-app> server-config.wsdd-webservice服务部署的配置文件 deployment name="defaultClientConfig" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" xmlns:handler="http://xml.apache.org/axis/wsdd/providers/handler"="http://xml.apache.org/axis/wsdd/" 5 6 globalConfiguration ="GlobalConfiguration1"="" regenerateElement="false" 7 requestFlow ="RequestFlow1" 8 handler ="Handler1" type="java:org.apache.axis.handlers.JWSHandler"10 parameter ="scope" value="session"11 handler12 ="Handler2" 13 14 ="request"15 ="extension"=".jwr"16 requestFlowglobalConfiguration19 ="URLMapper" 21 type="java:org.apache.axis.handlers.http.URLMapper"="LocalResponder" 23 ="java:org.apache.axis.transport.local.LocalResponder"="Authenticate" 25 ="java:org.apache.axis.handlers.SimpleAuthenticationHandler"transport ="http"27 28 ="Handler1"="URLMapper"29 30 ="java:org.apache.axis.handlers.http.HTTPAuthHandler"31 transport33 ="local"responseFlow ="ResponseFlow1"35 ="LocalResponder"36 responseFlow38 39 service ="queryInfo" provider="java:RPC" 服务类名 41 ="className"="com.impl.QueryInfoSVImpl" 42 允许访问所有方法 43 ="allowedMethods"="*" 44 service45 deployment> ---把博客贴出来主要是请大家帮看看后面的问题,关于配置文件的介绍后面会加上详细的说明--- result 发布项目,启动tomcat。
?在浏览器访问发布的wsdl 输入如下地址:http://127.0.0.1:8080/WebService/services/queryInfo?WSDL 访问界面如图:
? ?运行Test2类中的main方法,测试结果如下图:
webservice服务存在以下2个问题: (1)如上图所示,按说在浏览器中可以正常的访问wsdl的话,就说明服务已经发布好了。为什么客户端调用会报如此错误呢? (2)如果我把访问的127.0.0.1改为localhost就不能正常的访问wsdl了,这个是什么原因呢? 急需大虾出现解决小弟的问题,我也在努力的查找中。跪求ing。 ? 为方便各位大侠帮小弟查问题,源码下载地址如下:http://files.cnblogs.com/java-pan/WebService.rar ? modified by pantp ?2012/08/22 问题定位及解决方法: ? ? ?关于此博客中的问题一直未解决,心中的石头也一直未落地; ? ? ?经过这两天的再一次拿出来查找问题、定位问题,终于得到了答案。 解决方式:把ConnectDataBase类中采用ibatis操作数据库的代码给去掉,然后再一次重新发布工程,启动tomcat, 此时,在IE浏览器可以正常的访问wsdl地址,采用webservice客户端形式(包括动态调用和stub桩的形式)也可以正常的调用webservice服务。 初步分析原因,可能是ibatis和axis的版本不兼容导致 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |