webservice系列1---基于web工程上写一个基本数据类型的webservice

来源:互联网 发布:bat和华为offer知乎 编辑:程序博客网 时间:2024/04/29 09:31

本节摘要:之前在一篇博客中介绍过如何写一个webservice(http://www.cnblogs.com/java-pan/archive/2011/11/25/axis_webservice.html),不过那个webservice是在工作项目中直接添加的,中间少了很多麻烦,不是白手起家总感觉前面一步一步的过程不清楚。myeclipse自带的也有如何新建一个webservice工程,这也不是我要说的,项目中这个也不实用,项目中都是在当前开发的web工程中写一个webservice,谁会再去新建一个工程,那不是扯淡吗?本节在一个已经存在的web工程中,来新建类、新建配置文件,发布webservice、访问webservice。基于axis1.4的版本来完成的。

preparation

1.在阅读本机之前你需要看以下相关知识:

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&mthod

JDBC: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:线程安全的可变字符序列

append(String str)将指定的字符串追加到此字符序列

toString()返回此序列中数据的字符串表示形式

 

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, 201210  */11 public class Dept {12     public int deptNo;13     public String dName;14     public String loc;15 16     public int getDeptNo() {17         return deptNo;18     }19 20     public void setDeptNo(int deptNo) {21         this.deptNo = deptNo;22     }23 24     public String getDName() {25         return dName;26     }27 28     public void setDName(String name) {29         dName = name;30     }31 32     public String getLoc() {33         return loc;34     }35 36     public void setLoc(String loc) {37         this.loc = loc;38     }39 }
复制代码

数据库连接文件-ConnectDataBase.java

复制代码
 1 package com.cn; 2  3 import java.io.IOException; 4 import java.io.Reader; 5  6 import java.sql.Connection; 7 import java.sql.DriverManager; 8 import java.sql.SQLException; 9 10 import com.ibatis.common.resources.Resources;11 import com.ibatis.sqlmap.client.SqlMapClient;12 import com.ibatis.sqlmap.client.SqlMapClientBuilder;13 14 /**15  * 16  *Module:          ConnectDataBase.java17  *Description:    数据库连接类,采用两种方式:1.JDBC 2.Ibatis框架18  *Company:       19  *Author:           pantp20  *Date:              May 1, 201221  */22 public class ConnectDataBase {23 24     //采用JDBC的方式连接数据25     private final static String USERNAME = "scott";26     private final static String PASSWORD = "orcl";27     private final static String URL = "jdbc:Oracle:thin:@localhost:1521:orcl";28     private final static String DRIVER = "oracle.jdbc.driver.OracleDriver";29     static Connection conn = null;30     31     // 获取连接32     static {33         // 加载驱动34         try {35             Class.forName(DRIVER);36         } catch (ClassNotFoundException e) {37             e.printStackTrace();38         }39         // 获得连接对象conn40         try {41             conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);42         } catch (SQLException e) {43             e.printStackTrace();44         }45     }46     47     //提供一个方法供外部调用,获得JDBC连接对象conn48     public static Connection getConnection() {49         return conn;50     }51     52     53     // 定义ibatis映射文件的位置,写配置文件的完整路径54     private static String resource = "com/ibatis/SqlMapConfig.xml";55     private static SqlMapClient sqlMapClient = null;56     static {57         try {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的连接对象sqlMapClient67     public static SqlMapClient getSqlMapClient(){68         return sqlMapClient;69     }70 71 72 }
复制代码

实体类对应的映射文件-Dept.xml

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?> 2 <!--  3     author:pantp 4     date:2012/05/01 5     description:javabean对应的xml配置文件 6 --> 7 <!DOCTYPE sqlMap       8     PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"       9     "http://ibatis.apache.org/dtd/sql-map-2.dtd">10 11 <sqlMap>12     <typeAlias alias="Dept" type="com.bean.Dept" />13 14     <!-- 精确查询 按照条件查询记录  按照部门编号DEPTNO查询 -->15     <select parameterClass="int" resultClass="Dept" id="selectById">16         select deptno,dname,loc from dept where deptno=#deptNo#17     </select>18 19 </sqlMap>
复制代码

数据库连接属性文件-SqlMap.properties

1 driver=oracle.jdbc.driver.OracleDriver2 url=jdbc:Oracle:thin:@127.0.0.1:1521:orcl3 username=scott4 password=orcl

ibatis核心配置文件-SqlMapConfig.xml

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?> 2 <!--  3     author:pantp 4     date:2012/05/01 5     description:Ibatis框架的核心配置文件,主要是数据库连接属性文件和实体类和表的映射文件引入进来 6 --> 7 <!DOCTYPE sqlMapConfig       8     PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"       9     "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">10 11 <sqlMapConfig>12 13     <!-- 数据库连接的属性文件 -->14     <properties resource="com/ibatis/SqlMap.properties" />15     <transactionManager type="JDBC">16         <dataSource type="SIMPLE">17             <property value="${driver}" name="JDBC.Driver" />18             <property value="${url}" name="JDBC.ConnectionURL" />19             <property value="${username}" name="JDBC.Username" />20             <property value="${password}" name="JDBC.Password" />21         </dataSource>22     </transactionManager>23 24     <!-- 实体类和数据库表的映射 -->25     <sqlMap resource="com/ibatis/Dept.xml" />26 27 </sqlMapConfig>
复制代码

定义查询服务的接口文件-IQueryInfoSV.java

复制代码
 1 package com.interfaces; 2  3 import java.sql.SQLException; 4  5 /** 6  *  7  *Module:          IQueryInfoSV.java 8  *Description:    定义查询的接口 9  *Company:       10  *Author:           pantp11  *Date:              May 1, 201212  */13 public interface IQueryInfoSV {14 15     //JDBC16     public abstract String queryDept1(int deptNo) throws SQLException;17     18     //ibatis19     public abstract String queryDept2(int deptNo) throws SQLException;20     21 }
复制代码

定义查询服务的实现类-QueryInfoSVImpl.java

复制代码
  1 package com.impl;  2   3 import java.sql.Connection;  4 import java.sql.PreparedStatement;  5 import java.sql.ResultSet;  6 import com.bean.Dept;  7 import com.cn.ConnectDataBase;  8 import com.ibatis.sqlmap.client.SqlMapClient;  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 import java.sql.SQLException; 15  16 /** 17  *  18  *Module:          QueryInfoSVImpl.java 19  *Description:     根据部门编号查询oracle自带的dept表,提供两种查询方式:1.JDBC 2.Ibatis 20  *Company:        21  *Author:           pantp 22  *Date:              May 1, 2012 23  */ 24 public class QueryInfoSVImpl implements IQueryInfoSV { 25  26     // 采用JDBC方式连接数据库的查询操作 27     public String queryDept1(int deptNo) throws SQLException { 28         // 获取JDBC的连接 29         Connection conn = ConnectDataBase.getConnection(); 30         // 拼装SQL语句 31         String sql = "select deptno,dname,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 = null; 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(int deptNo) throws SQLException { 52         // 获得ibatis的连接对象sqlMapClient 53         SqlMapClient sqlMapClient = ConnectDataBase.getSqlMapClient(); 54         Dept dept = null; 55         try { 56             sqlMapClient.startTransaction();// 开始事务 57             // 执行查询 此处的"selectById"对应Dept.xml文件中select标签的id属性 58             dept = (Dept) sqlMapClient.queryForObject("selectById", 59                     new Integer(deptNo)); 60             sqlMapClient.commitTransaction();// 提交事务 61         } catch (SQLException e) { 62             try { 63                 sqlMapClient.getCurrentConnection().rollback();// 回滚事务 64             } catch (SQLException e1) { 65                 e1.printStackTrace(); 66             } 67             e.printStackTrace(); 68         } finally { 69             try { 70                 sqlMapClient.endTransaction();// 结束事务 71             } catch (SQLException e) { 72                 e.printStackTrace(); 73             } 74         } 75         // 组装xml报文并返回 76         return getXML(dept); 77     } 78  79     // 采用XStream方式组装XML 80     public 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", Dept.class, "deptNo"); 94             xstream.aliasField("DNAME", Dept.class, "dName"); 95             xstream.aliasField("LOC", Dept.class, "loc"); 96              97             // 把实体类转换为XML 98             xmlbody = xstream.toXML(dept); 99         } else {100             // 处理根据编号没有查询到数据的情况101             StringBuffer sb = new StringBuffer();102             sb103                     .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的数据库连接是否正常

复制代码
 1 package com.test; 2  3 import java.sql.SQLException; 4 import com.impl.QueryInfoSVImpl; 5 import com.interfaces.IQueryInfoSV; 6  7 /** 8  *  9  *Module:          Test1.java10  *Description:     测试JDBC和Ibatis数据库查询是否正常11  *Company:       12  *Author:           ptp13  *Date:              May 1, 201214  */15 public class Test1 {16 17     // 测试数据库是可以正常查询18     public static void main(String[] args) throws SQLException {19         int deptNo = 10;20         test1(deptNo);21         test2(deptNo);22     }23 24     //测试JDBC方式连接数据库是否正常 25     public static void test1(int deptNo) throws SQLException {26         IQueryInfoSV query = new QueryInfoSVImpl();27         String dept = query.queryDept1(deptNo);28 29         System.out30                 .println("\n===============采用JDBC方式查询数据库连接正常  author<pantp>=======\n");31         System.out.println(dept);32         System.out33                 .println("\n===============采用JDBC方式查询数据库连接正常==================\n");34     }35 36     //测试ibatis方式连接数据库是否正常37     public static void test2(int deptNo) throws SQLException {38         IQueryInfoSV query = new QueryInfoSVImpl();39         String dept = query.queryDept2(deptNo);40 41         System.out42                 .println("\n===============采用ibatis方式查询数据库连接正常 author<pantp>========\n");43         System.out.println(dept);44         System.out45                 .println("\n===============采用ibatis方式查询数据库连接正常==================\n");46     }47 48 }
复制代码

测试类-Test2.java 用于测试webservice服务是否可以正常调用

复制代码
 1 package com.test; 2  3 import java.net.MalformedURLException; 4 import java.net.URL; 5 import java.rmi.RemoteException; 6  7 import javax.xml.rpc.ParameterMode; 8 import javax.xml.rpc.ServiceException; 9 10 import org.apache.axis.client.Call;11 import org.apache.axis.encoding.XMLType;12 13 /**14  * 15  *Module:          Test2.java16  *Description:     项目中常用调用webservice方式有两种,stub桩的形式和动态调用,本次测试就用动态调用的方式17  *Company:       18  *Author:           pantp19  *Date:              May 1, 201220  */21 public class Test2 {22 23    // 调用webservice24     public static void main(String[] args) {25         test2();26     }27     28     /**29      * 动态调用接口访问webservice服务的步骤如下:30      * 1.创建service对象 31      * 2.创建url对象 32      * 3.创建call对象,33      * 4.调用webservice的方法34      * 5.处理返回结果35      */36     public static void test2() {37         try {38             // 1.创建service对象,通过axis自带的类创建39             org.apache.axis.client.Service service = new org.apache.axis.client.Service();40 41             // 2.创建url对象42             String wsdlUrl = "http://127.0.0.1:8080/WebService/services/queryInfo?WSDL";// 请求服务的URL43             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方法调用webservice55             Integer deptNo = new Integer(50);56             String dept = (String) call.invoke(new Object[] { deptNo });// 调用服务方法57 58             //5.打印返回结果59             System.out60                     .println("\n===============调用webservice成功(无安全机制) author<pantp>=======\n");61             System.out.println(dept);62             System.out63                     .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-项目配置文件

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?> 2 <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  5     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 6   <servlet> 7     <servlet-name>AxisServlet</servlet-name> 8     <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class> 9   </servlet>10     <servlet-mapping>11         <servlet-name>AxisServlet</servlet-name>12         <url-pattern>/services/*</url-pattern>13     </servlet-mapping>14     <mime-mapping>15         <extension>wsdl</extension>16         <mime-type>text/xml</mime-type>17     </mime-mapping>18     <mime-mapping>19         <extension>xsd</extension>20         <mime-type>text/xml</mime-type>21     </mime-mapping>22 23 </web-app>
复制代码

server-config.wsdd-webservice服务部署的配置文件

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?> 2 <deployment name="defaultClientConfig" 3     xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" 4     xmlns:handler="http://xml.apache.org/axis/wsdd/providers/handler" xmlns="http://xml.apache.org/axis/wsdd/"> 5      6     <globalConfiguration name="GlobalConfiguration1" type="" regenerateElement="false"> 7         <requestFlow name="RequestFlow1" type="" regenerateElement="false"> 8             <handler name="Handler1" 9                 type="java:org.apache.axis.handlers.JWSHandler" regenerateElement="false">10                 <parameter name="scope" value="session" regenerateElement="false"/>11             </handler>12             <handler name="Handler2"13                 type="java:org.apache.axis.handlers.JWSHandler" regenerateElement="false">14                 <parameter name="scope" value="request" regenerateElement="false"/>15                 <parameter name="extension" value=".jwr" regenerateElement="false"/>16             </handler>17         </requestFlow>18     </globalConfiguration>19     20     <handler name="URLMapper"21         type="java:org.apache.axis.handlers.http.URLMapper" regenerateElement="false"/>22     <handler name="LocalResponder"23         type="java:org.apache.axis.transport.local.LocalResponder" regenerateElement="false"/>24     <handler name="Authenticate"25         type="java:org.apache.axis.handlers.SimpleAuthenticationHandler" regenerateElement="false"/>26     <transport name="http" type="" regenerateElement="false">27         <requestFlow name="RequestFlow1" type="" regenerateElement="false">28             <handler name="Handler1" type="URLMapper" regenerateElement="false"/>29             <handler name="Handler2"30                 type="java:org.apache.axis.handlers.http.HTTPAuthHandler" regenerateElement="false"/>31         </requestFlow>32     </transport>33     <transport name="local" type="" regenerateElement="false">34         <responseFlow name="ResponseFlow1" type="" regenerateElement="false">35             <handler name="Handler1" type="LocalResponder" regenerateElement="false"/>36         </responseFlow>37     </transport>38 39     <service name="queryInfo" provider="java:RPC">40         <!-- 服务类名 -->41         <parameter name="className" value="com.impl.QueryInfoSVImpl" />42         <!-- 允许访问所有方法 -->43         <parameter name="allowedMethods" value="*" />44     </service>45 </deployment>
复制代码

---把博客贴出来主要是请大家帮看看后面的问题,关于配置文件的介绍后面会加上详细的说明---

result

发布项目,启动tomcat。
运行Test1.java中的main方法,测试JDBC和ibatis数据库查询是否正常,查询结果如下:

 在浏览器访问发布的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的版本不兼容导致

0 0
原创粉丝点击