webservice訪問的幾種方式


  今天在對接的客戶用到了webservice,最終采用wsimport生成本地代理方式以SDK的形式對接,但是想的完整的總結一下ws的幾種調用方式。

  發布服務的IP地址是:192.168.125.116

  客戶端訪問ws服務的IP是:192.168.125.115

1.發布ws服務:   

   參考:https://www.cnblogs.com/qlqwjy/p/9644078.html

 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/jaxws http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <jaxws:endpoint id="userServiceWS"
        implementor="cn.xm.exam.service.impl.webservice.UserWebServiceImpl" address="/userServiceWS">
    </jaxws:endpoint>

</beans>

web.xml如下:

    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/WS/*</url-pattern>
    </servlet-mapping>

 

package cn.xm.exam.service.webservice;

import java.util.Set;

import javax.jws.WebService;

import cn.xm.exam.bean.system.User;

@WebService
public interface UserWebService {

    /**
     * 根據用戶身份證號碼查詢用戶信息及其角色信息及其權限信息
     * 
     * @param useridcard
     * @return user
     */
    public User getUserByUseridcard(String useridcard) throws Exception;

    /**
     * 根據用戶編號查詢角色code的集合
     * 
     * @param userid
     * @return 角色集合
     */
    public Set<String> getRoleByUserid(String userid) throws Exception;

}

 

package cn.xm.exam.service.impl.webservice;

import java.util.Set;

import javax.annotation.Resource;
import javax.jws.WebService;

import org.springframework.stereotype.Service;

import cn.xm.exam.bean.system.User;
import cn.xm.exam.mapper.system.UserMapper;
import cn.xm.exam.service.webservice.UserWebService;
import cn.xm.exam.utils.ValidateCheck;

@Service
@WebService(targetNamespace = "http://webservice.service.exam.xm.cn")
public class UserWebServiceImpl implements UserWebService {
    @Resource
    private UserMapper userMapper;

    @Override
    public User getUserByUseridcard(String useridcard) {
        if (ValidateCheck.isNull(useridcard)) {
            return null;
        }
        User user = null;
        try {
            user = userMapper.getUserByUseridcard(useridcard);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }

    @Override
    public Set<String> getRoleByUserid(String userid) {
        if (ValidateCheck.isNull(userid)) {
            return null;
        }
        Set<String> role = null;
        try {
            role = userMapper.getRoleByUserid(userid);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return role;
    }

}

 

啟動之后查看ws服務:

查看wsdl:

2.訪問ws的幾種方式

1.wsimport生成本地代理的方式(簡單--類似於SDK訪問)

生成本地代碼(如果需要下載源碼,加上 -keep 參數即可)

wsimport http://192.168.125.116:85/Exam/WS/userServiceWS?wsdl

 發現雖然我們只是發布了一個webservice,但是下載的時候會將接口中依賴的bean等信息也一起發布。

 

打包

jar cvf ./test.jar ./

 

放入eclipse進行測試

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;

import cn.xm.exam.service.webservice.Exception_Exception;
import cn.xm.exam.service.webservice.User;
import cn.xm.exam.service.webservice.UserWebService;
import cn.xm.exam.service.webservice.UserWebServiceImplService;

public class Test {
    public static void main(String[] args) throws Exception_Exception,
            MalformedURLException {
        // 創建的時候用URL指定WSDL的地址;用QName指定targetNamespace和name。當然可以不指定,不指定使用的是默認值
        // UserWebServiceImplService userWebServiceImplService = new  UserWebServiceImplService();
        UserWebServiceImplService userWebServiceImplService = new UserWebServiceImplService(
                new URL("http://192.168.125.116:85/Exam/WS/userServiceWS?wsdl"),
                new QName("http://webservice.service.exam.xm.cn",
                        "UserWebServiceImplService"));
        UserWebService userWebServiceImplPort = userWebServiceImplService
                .getUserWebServiceImplPort();
        User userByUseridcard = userWebServiceImplPort
                .getUserByUseridcard("140581197705070518");
        System.out.println(userByUseridcard.getUsername());
    }
}

結果:

  返回從192.168.125.116返回數據庫查詢的信息。 也就是說我們調用ws接口的時候實際底層是http+xml,因此我們可以通過ws接口調用到服務器的信息。 

 

2.  CXF動態調用:(推薦這種)

依賴的包:

 

測試代碼如下:

import javax.xml.namespace.QName;

import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

public class Test2 {
    public static void main(String[] args) {
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();

        org.apache.cxf.endpoint.Client client = dcf.createClient("http://localhost:85/Exam/WS/userServiceWS?wsdl"); // url為調用webService的wsdl地址

        QName name = new QName("http://webservice.service.exam.xm.cn/", "getUserByUseridcard");// namespace是命名空間,methodName是方法名

        Object[] objects;
        try {
            objects = client.invoke(name, "140581197705070518");// 第一個參數是上面的QName,第二個開始為參數,可變數組
            System.out.println(objects);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意:

(1)QName的第一個參數必須帶斜杠,也就是必須寫為http://webservice.service.exam.xm.cn/,否則會報下面異常:

org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name {http://webservice.service.exam.xm.cn}getUserByUseridcard.
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:331)
    at Test2.main(Test2.java:15)

(2)發布的webservice的接口和實現類要在同一個包,或者在實現類用注解聲明發布的webservice地址。

  CXF發布用的是業務類(xxxServiceImpl.java),那么默認的命名空間就會是業務類所在包(路徑),而對外界暴露的則是接口類(XXXService.java),那么對於客戶端(第三方)調用訪問時,需要按照接口類所在包(路徑)進行命名空間的定義。所以需要接口與實現在同一個包或者在實現類指定接口地址。

如下:(最好以/結尾---下面沒有以斜杠結尾)

@Service
@WebService(targetNamespace = "http://webservice.service.exam.xm.cn")
public class UserWebServiceImpl implements UserWebService {
  。。。

(3)查看namespace相關信息:(兩兩相同是因為上面發布的時候沒有以/結尾,最好以/結尾四個namespace就會相同)

 

3.通過axis包訪問(簡單)

   所需5個jar包 axis-1.4.jar axis-jaxrpc-1.4.jar commons-logging-1.2.jar  commons-discovery-0.2.jar wsdl4j-1.6.3.jar

 這個在測試的時候直接返回bean報錯(解決辦法就是加類型轉換器),因此我返回的是String數據。接口和實現類修改如下:

package cn.xm.exam.service.webservice;

import java.util.Set;

import javax.jws.WebResult;
import javax.jws.WebService;

import cn.xm.exam.bean.system.User;

@WebService
public interface UserWebService {

    /**
     * 根據用戶身份證號碼查詢用戶信息及其角色信息及其權限信息
     * 
     * @param useridcard
     * @return user
     */
    public String getUsernameByUseridcard(String useridcard) throws Exception;

    /**
     * 根據用戶編號查詢角色code的集合
     * 
     * @param userid
     * @return 角色集合
     */
    public Set<String> getRoleByUserid(String userid) throws Exception;

}

 

package cn.xm.exam.service.impl.webservice;

import java.util.Set;

import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.springframework.stereotype.Service;

import cn.xm.exam.bean.system.User;
import cn.xm.exam.mapper.system.UserMapper;
import cn.xm.exam.service.webservice.UserWebService;
import cn.xm.exam.utils.ValidateCheck;

@Service
@WebService(targetNamespace = "http://webservice.service.exam.xm.cn")
public class UserWebServiceImpl implements UserWebService {
    @Resource
    private UserMapper userMapper;

    @Override
    public String getUsernameByUseridcard(String useridcard) {
        if (ValidateCheck.isNull(useridcard)) {
            return null;
        }
        User user = null;
        try {
            user = userMapper.getUserByUseridcard(useridcard);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return user == null ? "" : user.getUsername();
    }

    @Override
    public Set<String> getRoleByUserid(String userid) {
        if (ValidateCheck.isNull(userid)) {
            return null;
        }
        Set<String> role = null;
        try {
            role = userMapper.getRoleByUserid(userid);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return role;
    }

}

 

測試代碼:

代碼一:

package zd.dms.wbws;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;

public class AxisClient {
    public static void main(String[] args) {
        String webServiceURL = "http://localhost:85/Exam/WS/userServiceWS?wsdl";
        String namespaceURI = "http://webservice.service.exam.xm.cn/";
        String method = "getUsernameByUseridcard";
        List<Map<String, Object>> params = new ArrayList<Map<String, Object>>();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("paramName", "arg0");
        map.put("paramType", XMLType.XSD_STRING);
        map.put("paramValue", "140581197705070518");
        params.add(map);
        String result = (String) AxisClient.getResult(webServiceURL, namespaceURI, method, null, params,
                XMLType.XSD_STRING);
        System.out.println(result);
    }

    /**
     * Axis方式訪問WebService接口
     * 
     * @param webServiceURL
     *            webService地址,末尾為?wsdl時不需要寫
     * @param namespaceURI
     *            命名空間
     * @param method
     *            方法名稱
     * @param soapAction
     *            soapAction
     * @param params
     *            參數
     * @param returnType
     *            返回值類型
     * @return
     */
    public static Object getResult(String webServiceURL, String namespaceURI, String method, String soapAction,
            List<Map<String, Object>> params, QName returnType) {
        if (null == params || params.size() == 0)
            return null;
        // 創建客戶端
        Service service = new Service();
        Call call = null;
        try {
            call = (Call) service.createCall();
            // 設置訪問地址
            call.setTargetEndpointAddress(new URL(webServiceURL));
            // 是否使用SOAPAction
            if (null == soapAction || "".equals(soapAction)) {
                call.setUseSOAPAction(false);
            } else {
                call.setUseSOAPAction(true);
                // 設置SOAPAction地址
                call.setSOAPActionURI(soapAction);
            }
            // 設置訪問方法名稱
            call.setOperationName(new QName(namespaceURI, method));
            // 添加解析類型的地址
            call.setEncodingStyle(namespaceURI);
            // 設置返回值類型
            call.setReturnType(returnType);
            // 添加參數名稱
            Object[] obj = new Object[params.size()];
            for (int i = 0; i < params.size(); i++) {
                Map<String, Object> map = params.get(i);
                call.addParameter(new QName((String) map.get("paramName")), (QName) map.get("paramType"),
                        ParameterMode.IN);
                obj[i] = map.get("paramValue");
            }
            return call.invoke(obj);
        } catch (ServiceException e) {
            e.printStackTrace();
            return null;
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null;
        } catch (RemoteException e) {
            e.printStackTrace();
            return null;
        }
    }
}

 

代碼二:

package zd.dms.wbws;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;

public class TestUseWebservice2 {
    public static void main(String[] args) {
        Object ticket = testWS();
        System.out.println(ticket);
    }

    public static Object testWS() {
        try {
            // wsdl的地址
            String endpoint = "http://localhost:85/Exam/WS/userServiceWS?wsdl";
            // 直接引用遠程的wsdl文件
            // 以下都是固定格式
            Service service = new Service();
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(endpoint);

            // WSDL里面描述的方法名稱 填寫方法名是需加上命名空間,否則會找不到對應的方法
            call.setOperationName(new QName("http://webservice.service.exam.xm.cn/", "getUsernameByUseridcard"));
            // 添加解析類型的地址
            call.setEncodingStyle("webservice.service.exam.xm.cn");

            // 給方法傳遞參數,並且調用方法
            call.addParameter("arg0", XMLType.XSD_STRING, ParameterMode.IN);
            call.setReturnType(XMLType.XSD_ENTITY);// 設置返回類型
            return call.invoke(new Object[] { "140581197705070518" });
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

 

  由於webservice采用SOAP協議,相當於http+xml,因此我們訪問的時候可以獲取到服務器的數據。

  而RPC相當於接口和實現分離,我們獲取到接口,然后實現類可以從RPC的注冊中心進行獲取。當然RPC也可以獲取遠程的數據。其實webservice和RPC可以通過生成代理對象獲取遠程的數據。我們用RPC以本地方式調用服務,實則會向服務器的具體實現類發送請求並獲取數據。(當然這中間有對方法、請求參數的包裝以及解碼等工作)

 

CXF訪問參考:https://www.cnblogs.com/qlqwjy/p/9644078.html

 


免責聲明!

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



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