一、前言:
工作中,接觸到很多系統要互相對接,因為大多數公司(項目)所用的平台不同,要想一方提供數據信息供對方提取,首先想到的就是開放出一個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
