我的第一次WebService接口开发教程
一、前言:
工作中,接触到很多系统要互相对接,因为大多数公司(项目)所用的平台不同,要想一方提供数据信息供对方提取,首先想到的就是开放出一个WebService接口调用文档和WebService地址,这样对方就能根据文档地址编程去调用。于是便在网上搜罗相关资料,尝试写一个WebService接口,非科班出身,仅供大家参考、指教。
二、WebService优点:
- 可远程调用(WebService可以向全世界提供信息,或提供某项功能,只要有网就OK)。
- 跨平台调用(WebService可以在Windows上调用linux上的WebService服务,反之同理)。
- 跨语言调用(WebService可以在Java语言中调用asp.net语言提供的WebService服务,反之其他编程语言同理)
- ......
三、详细开发步骤:
1)使用JDK开发WebService
WebService服务端
1.1首先我们先创建一个java项目,目录及Util工具类和所应用的包:
这里我用的是 C3p0 JDBC连接池方式我给大家提供MySql和oracle工具类,代码如下:
MySql:
package Util;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class JDBCUtil2 {
static ComboPooledDataSource dataSource = null;
static{
dataSource = new ComboPooledDataSource();
}
public static DataSource getDataSource(){
return dataSource;
}
/**
* 获取连接对象
* @return
* @throws SQLException
*/
public static Connection getConn() throws SQLException{
return dataSource.getConnection();
}
/**
* 释放资源
* @param conn
* @param st
* @param rs
*/
public static void release(Connection conn , Statement st , ResultSet rs){
closeRs(rs);
closeSt(st);
closeConn(conn);
}
public static void release(Connection conn , Statement st){
closeSt(st);
closeConn(conn);
}
private static void closeRs(ResultSet rs){
try {
if(rs != null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}
private static void closeSt(Statement st){
try {
if(st != null){
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
st = null;
}
}
private static void closeConn(Connection conn){
try {
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
public static void main(String[] args) throws Exception{
System.out.println(getConn());
System.out.println("---------------------------南清风工具类测试-------------------------------");
System.out.println("+++++++++++++++++++MySql Connection Successful!+++++++++++++++++++++");
System.out.println("---------------------------------------------------------------------");
}
}
Oracle:
package Util;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class JDBCUtil {
private static ComboPooledDataSource ds = new ComboPooledDataSource();
private static ThreadLocal<Connection> tl=new ThreadLocal<>();
/**
* 从线程中获取连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
//从线程中获取conneciton
Connection conn = tl.get();
if(conn==null){
conn=ds.getConnection();
//和当前线程绑定
tl.set(conn);
}
return conn;
}
// 获取数据源
public static DataSource getDataSource() {
return ds;
}
// 释放资源
public static void closeResource( Statement st, ResultSet rs) {
closeResultSet(rs);
closeStatement(st);
}
// 释放资源
public static void closeResource(Connection conn, Statement st, ResultSet rs) {
closeResource(st, rs);
closeConn(conn);
}
// 释放 connection
public static void closeConn(Connection conn) {
if (conn != null) {
try {
conn.close();
//和线程解绑
tl.remove();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
// 释放 statement ctrl + shift + f 格式化代码
public static void closeStatement(Statement st) {
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
st = null;
}
}
// 释放结果集
public static void closeResultSet(ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
}
//开启事务
public static void startTransaction() throws SQLException{
getConnection().setAutoCommit(false);
}
/**
* 事务提交且释放连接
*/
public static void commitAndClose(){
Connection conn = null;
try {
conn=getConnection();
//事务提交
conn.commit();
//关闭资源
conn.close();
//解除版定
tl.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 事务回滚且释放资源
*/
public static void rollbackAndClose(){
Connection conn = null;
try {
conn=getConnection();
//事务回滚
conn.rollback();
//关闭资源
conn.close();
//解除版定
tl.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception{
System.out.println(getConnection());
System.out.println("---------------------------南清风工具类测试-------------------------------");
System.out.println("+++++++++++++++++++Oracle Connection Successful!+++++++++++++++++++++");
System.out.println("---------------------------------------------------------------------");
}
}
1.2我们现在需要写一个接口类、封装对象类、实现类和拦截器,代码如下:
接口类:
package Dao;
import java.sql.SQLException;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface fwsyq {
@WebMethod()
String Get_fwsyq(
@WebParam(name="cxtj",targetNamespace = "http://Dao.Get_fwsyq_impl.Get_fwsyq")String cxtj,
@WebParam(name="cxnr",targetNamespace = "http://Dao.Get_fwsyq_impl.Get_fwsyq")String cxnr) throws SQLException;
}
Bean封装类:
package Bean;
public class fwsyq_table2 {
private int id;
private String SLID;
private String DJYY;
private String DYH;
private String QLR;
private String BH;
private String ZH;
private float JZMJ;
private String FDZL;
private String XZ;
private String DJSJ;
private String djbzt;
public fwsyq_table2() {
super();
}
public fwsyq_table2(int id, String sLID, String dJYY, String dYH, String qLR, String bH, String zH, float jZMJ,
String fDZL, String xZ, String dJSJ, String djbzt) {
this.id = id;
SLID = sLID;
DJYY = dJYY;
DYH = dYH;
QLR = qLR;
BH = bH;
ZH = zH;
JZMJ = jZMJ;
FDZL = fDZL;
XZ = xZ;
DJSJ = dJSJ;
this.djbzt = djbzt;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSLID() {
return SLID;
}
public void setSLID(String sLID) {
SLID = sLID;
}
public String getDJYY() {
return DJYY;
}
public void setDJYY(String dJYY) {
DJYY = dJYY;
}
public String getDYH() {
return DYH;
}
public void setDYH(String dYH) {
DYH = dYH;
}
public String getQLR() {
return QLR;
}
public void setQLR(String qLR) {
QLR = qLR;
}
public String getBH() {
return BH;
}
public void setBH(String bH) {
BH = bH;
}
public String getZH() {
return ZH;
}
public void setZH(String zH) {
ZH = zH;
}
public float getJZMJ() {
return JZMJ;
}
public void setJZMJ(float jZMJ) {
JZMJ = jZMJ;
}
public String getFDZL() {
return FDZL;
}
public void setFDZL(String fDZL) {
FDZL = fDZL;
}
public String getXZ() {
return XZ;
}
public void setXZ(String xZ) {
XZ = xZ;
}
public String getDJSJ() {
return DJSJ;
}
public void setDJSJ(String dJSJ) {
DJSJ = dJSJ;
}
public String getDjbzt() {
return djbzt;
}
public void setDjbzt(String djbzt) {
this.djbzt = djbzt;
}
@Override
public String toString() {
return "fwsyq_table2 [id=" + id + ", SLID=" + SLID + ", DJYY=" + DJYY + ", DYH=" + DYH + ", QLR=" + QLR
+ ", BH=" + BH + ", ZH=" + ZH + ", JZMJ=" + JZMJ + ", FDZL=" + FDZL + ", XZ=" + XZ + ", DJSJ=" + DJSJ
+ ", djbzt=" + djbzt + "]";
}
}
接口实现类:
package Dao;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import Bean.fwsyq_table;
import Util.JDBCUtil2;
import net.sf.json.JSONArray;
public class Get_fwsyq_impl implements fwsyq {
@Override
public String Get_fwsyq(String cxtj, String cxnr) {
try {
QueryRunner qr = new QueryRunner(JDBCUtil2.getDataSource());if(cxtj!=null && cxnr!=null){
String sql="select id,slid,djyy,dyh,qlr,bh,zh,jzmj,fdzl,xz,djsj,djbzt from bqh_fq1 where "+cxtj+"="+"‘"+cxnr+"‘" +"order by id";
String sql1="select count(*) from bqh_fq1 where "+cxtj+"="+"‘"+cxnr+"‘";
List<fwsyq_table> data = qr.query(sql, new BeanListHandler<fwsyq_table>(fwsyq_table.class));
Long total=(Long) qr.query(sql1, new ScalarHandler()); //统计查询总数
System.out.println("来自客户端接口访问:查询成功!");
int count=total.intValue();
int code=0;
String msg=""查询成功"";
String json1="{"code":"+code+","msg":"+msg+","count":"+count+","data":"+JSONArray.fromObject(data).toString()+"}";
System.out.println(json1);
return json1;
}else {
List<fwsyq_table> data =null;
System.out.println("来自客户端接口访问:查询失败!");
int code=4;
int count=0;
String msg=""查询失败"";
String json1="{"code":"+code+","msg":"+msg+","count":"+count+","data":"+JSONArray.fromObject(data).toString()+"}";
return json1;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
1.3使用Endpoint类发布WebService
package Publish_interface;
import javax.xml.ws.Endpoint;
import Dao.Get_fwsyq_impl;
public class Get_FWSYQ {
public static void main(String[] args){
//发布接口地址
String address="http://192.168.0.188:9999/BDBDCDJ/Get_fwsyq";
//jdk方法实现
Endpoint.publish(address, new Get_fwsyq_impl());
System.out.println("Published successfully!");
}
}
1.4启动main方法运行这个类,打印出结果Published successfully,表示服务发布成功:
1.5打开浏览器,访问我们发布的地址(注意后面得加?wsdl),大家可以看到这样的效果:
WSDL结构描述:
1.6我们可以用SoaoUI工具来测试一下接口:
OK,这样一个简单的WebService接口就OK了。
2)使用CXF开发WebService
cxf是java开发webService的一种实现框架技术。目前,cxf是主流的webService实现框架。
2.1使用cxf开发需引入cxf开发jar包
Jetty是一个内嵌的web服务器,使用JaxWsServerFactoryBean类创建工厂设置接口地址、接口类、接口实现类,创建即可发布。所以我们得引入jetty包,作为WebService发布的Server。
2.2增加一个拦截器:
package Interceptor;
import java.util.List;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
public MyInterceptor(){
// 在调用方法之前调用拦截器
super(Phase.PRE_INVOKE);
}
/**
* 拦截获取消息
*/
public void handleMessage(SoapMessage message) throws Fault {
Object obj = message.getContent(List.class).get(0);
System.out.println("参数1:"+obj);
Object obj1 = message.getContent(List.class).get(1);
System.out.println("参数2:"+obj1);
if(!obj.equals("slid") || obj1==null){
throw new Fault(new IllegalArgumentException("参数1错误,请求失败"));
}
if(obj1==null || obj1.equals("")){
throw new Fault(new IllegalArgumentException("参数2为空,请求失败"));
}
}
}
2.3使用jaws发布WebService
package Publish_interface;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import Dao.Get_fwsyq_impl;
import Dao.fwsyq;
import Interceptor.MyInterceptor;
public class CXF_Get_FWSYQ {
public static void main(String[] args) {
//1.使用jaws发布webservice
JaxWsServerFactoryBean jsfb=new JaxWsServerFactoryBean();
//2.设置发布服务的地址
jsfb.setAddress("http://192.168.0.188:9999/BDBDCDJ/Get_fwsyq");
//3.设置接口服务
jsfb.setServiceClass(fwsyq.class);
//4.设置服务的实现对象
jsfb.setServiceBean(new Get_fwsyq_impl());
jsfb.getInInterceptors().add(new LoggingInInterceptor()); // 添加in拦截器 日志拦截器
jsfb.getOutInterceptors().add(new LoggingOutInterceptor()); // 添加out拦截器
//添加自定义拦截器
jsfb.getInInterceptors().add(new MyInterceptor());
//5.通过工厂创建服务
jsfb.create();
System.out.println("Published successfully!");
}
}
2.4启动main方法运行这个类,打印出结果Cxfweb service published successfully,表示服务发布成功:
2.5打开浏览器,访问我们发布的地址(注意后面得加?wsdl),大家可以看到这样的效果:
2.6我们可以用Postman工具来测试一下接口:
上边验证拦截器是否生效,下边正常填写参数,成功返回查询结果:
四、客户端调用接口:
3.1 新建一个客户端java web项目
3.2 java自带wsimport命令生成webservice客户端代码及服务调用
通过wsimport命令生成客户端代码(通过cmd进入到当前项目的src路径下,wsimport.exe命令在jdk的bin目录下)
- 第一种方式【远程地址】wsimport -s . 接口地址(加?wsdl)
- 第二种方式【xml文件】wsimport -s . 文件路径(文件路径后面不需要加?wsdl)
wsimport -s . http://192.168.0.188:9999/BDBDCDJ/Get_fwsyq?wsdl
我们在看一下客户端项目:刷新一下如下:
3.3新建一个测试类,调用一下接口方法:
package Test_client;
import dao.Fwsyq;
import dao.FwsyqService;
public class Test_class {
public static void main(String[] args) throws Exception {
//构建服务视图对象(从service标签name属性获取)
FwsyqService service=new FwsyqService();
//获取服务的实现类(从portType的name属性获取
Fwsyq prot=service.getPort(Fwsyq.class);
//调用方法(portType下的operation属性获取
String info=prot.getFwsyq("slid", "202106070001");
System.out.println("调用服务端接口方法结果是:"+info);
}
}
3.4运行测试类结果如下:
Client console:
server console::
OK!一个基本的接口开发过程到此结束。
参考地址:
WebService几个常见的异常
CXF报安全性错误 Cannot create a secure XMLInputFactory
WebService-JDK的wsimport命令和cxf的wsdl2java命令的区别和使用
我的第一次WebService接口开发教程
[db:回答]