一、前言:
工作中,接触到很多系统要互相对接,因为大多数公司(项目)所用的平台不同,要想一方提供数据信息供对方提取,首先想到的就是开放出一个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!一个基本的接口开发过程到此结束。
参考地址:
CXF报安全性错误 Cannot create a secure XMLInputFactory
WebService-JDK的wsimport命令和cxf的wsdl2java命令的区别和使用