我的第一次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命令的區別和使用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM