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的版本不兼容导致
- webservice系列1---基于web工程上写一个基本数据类型的webservice
- webservice系列1---基于web工程上写一个基本数据类型的webservice
- 基于maven的web工程搭建CXF2.2.3 webservice
- Web Service (012---webservice使用CXF写基于Spring的WebService[服务端+客户端])
- 写一个简单的webservice
- [ webservice ] webservice系列1
- 开发基于CXF的 RESTful WebService web 项目 webservice发布
- 开发基于CXF的 RESTful WebService web 项目 webservice发布
- webservice之实现一个基于JWS的webservice项目
- webservice之实现一个基于JWS的webservice项目
- webservice之实现一个基于JWS的webservice项目
- webservice之实现一个基于JWS的webservice项目
- webservice之实现一个基于JWS的webservice项目
- WEBSERVICE复习系列-001一个简单的WEBSERVICE示例
- cxf开发基于web的webservice项目1
- 做一个基于WebService的系统
- Myeclipse创建一个基于Xfire的webservice
- java写的webservice
- 软工视频 之 初识
- Cavium OCTEON与DPDK(Intel data plan develop kit
- Java NIO 学习(一)
- C++ map的基本操作和使用
- ArrayUtils学习笔记
- webservice系列1---基于web工程上写一个基本数据类型的webservice
- linux下mysql的root密码忘记解决方案
- SharePoint 2013 帮助不可用(Unfortunately, help seems to be broken)
- 数据结构之排序算法整理(3)
- 两分钟彻底让你明白Android Activity生命周期
- sysbench的简单安装与数据库测试
- Redis操作记录
- 【DP】 HDOJ 4991 Ordered Subsequence
- Git fetch和git pull的区别