1. 程式人生 > >Webservice與CXF框架快速入門

Webservice與CXF框架快速入門

strong put 1.0 reat jdk AI NPU button RM

1. Webservice

Webservice是一套遠程調用技術規範

遠程調用RPC, 實現了系統與系統進程間的遠程通信.
java領域有很多可實現遠程通訊的技術,如:RMI(Socket + 序列化)、Binary-RPC(Http+二進制, 代表Hessian)、XML-RPC(Http+XML, 代表Burlap, WebService用的SOAP)、JMS(使用消息機制)、Mina(使用NIO)等, 底層都是基於http/socket和網絡IO來實現的.
從效率上來講, RMI > Hessian >> Burlap >> web service.

構成webservice的幾個要素:

1.WSDL:web服務描述語言. 即webservice服務的使用說明書, 自動生成,無需編寫

通過訪問類似http://127.0.0.1:12345/weather?wsdl的地址可以查看
它長如下這樣子, 閱讀順序從下往上

技術分享圖片


2.SOAP:簡單對象訪問協議 http post + xml
必有 envelope 標簽,將XML文檔標識為一條 SOAP 消息
必有 body 標簽,傳輸的信息
可選 header 標簽,包含頭部信息
可選 fault 標簽,提供有關在處理此消息所發生錯誤的信息

技術分享圖片
SOAP常用有1.1, 1.2兩個版本. jdk的Jaxws只支持發布SOAP1.1服務.

如要SOAP1.2服務, 需要引入jaxws-ri, 並在實現類上加入註解@BindingType(SOAPBinding.SOAP12HTTP_BINDING)

3.UDDI

:提供webservice服務的註冊和搜索功能, 不實用

服務端

public interface WeatherInterface {
    public String queryWeather(String cityName);
}
技術分享圖片
// 實現類前加WebService註解
//@BindingType(SOAPBinding.SOAP12HTTP_BINDING) @WebService public class WeatherImpl implements WeatherInterface { @Override public String queryWeather(String cityName) { String weather = "晴"; return weather; } }
技術分享圖片
public class WeatherServer {
    public static void main(String[] args) {
        //Endpoint發布服務, 參數1: 服務地址, 參數2: 服務實現類
        Endpoint.publish("http://127.0.0.1:12345/weather", new WeatherImpl());
    }
}

對於定義的服務實現類, 可以用註解進行修飾

@WebService 定義服務,在類上邊

targetNamespace:指定命名空間

name:portType的名稱

portName:port的名稱

serviceName:服務名稱

endpointInterface:如果一個服務類實現了多個服務接口,但只需要發布一個接口的方法,可通過此註解指定要發布服務的接口

@WebMethod 定義方法,在方法上邊

operationName:方法名

exclude:設置為true表示此方法不是webservice方法,不會發布,默認是false

@WebResult 定義返回值,在方法返回值前邊

name:返回結果值的名稱

@WebParam 定義參數,在方法參數前邊

name:指定參數的名稱

客戶端

首先, 用命令wsimport -s . http://127.0.0.1:12345/weather?wsdl生成支持類, 導入工程中

第一種使用方式 使用相關類

技術分享圖片
public class Client1 {

    public static void main(String[] args) throws IOException {
        // WSDL的地址, 非服務地址
        URL url = new URL("http://127.0.0.1:12345/weather?wsdl");
        //創建服務名稱
        //參數一: namespaceURI – WSDL文檔中  types/targetNamespace
        //參數二: localPart - 服務視圖名, WSDL文檔中 service-name
        QName qname = new QName("http://WebXml.com.cn/", "WeatherWS");
        //創建服務視圖
        //參數1: wsdlDocumentLocation  WSDL地址
        //參數2: serviceName  服務名稱
        Service service = Service.create(url, qname);
        //獲取服務類  getPort(WSDL文檔中portType-name)
        WeatherWSSoap weatherWSSoap = service.getPort(WeatherWSSoap.class);
        //調用方法   WSDL文檔中portType-operation-name
        String result = weatherWSSoap.queryWeather("北京");
        System.out.println(result);
    }
}
技術分享圖片

第二種使用方式 http工具訪問

技術分享圖片
public class Client2 {

    public static void main(String[] args) throws IOException {
        // 服務地址
        URL url = new URL("http://127.0.0.1:12345/weather");
        // 創建連接對象
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 設置參數
        // Http發送方式:POST必須大寫
        connection.setRequestMethod("POST");
        // content-type
        connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
        // 設置輸入輸出,默認connection沒有讀寫權限,
        connection.setDoInput(true);
        connection.setDoOutput(true);
        // 發送請求
        String soapXML = getXML("北京");
        OutputStream os = connection.getOutputStream();
        os.write(soapXML.getBytes());
        // 接收響應
        int responseCode = connection.getResponseCode();
        if(200 == responseCode){
            InputStream is = connection.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            
            StringBuilder sb = new StringBuilder();
            String temp = null;
            while(null != (temp = br.readLine())){
                sb.append(temp);
            }
            System.out.println(sb.toString());
            
            is.close();
            isr.close();
            br.close();
        }
        os.close();
    }
    
    // 組織SOAP數據
    public static String getXML(String cityName){
        String soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
        +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
            +"<soap:Body>"
            +"<getWeatherInfo xmlns=\"http://WebXml.com.cn/\">"
                +"<cityName>"+cityName+"</cityName>"
              +"<userID></userID>"
            +"</getWeatherInfo>"
          +"</soap:Body>"
        +"</soap:Envelope>";
        return soapXML;
    }
}
技術分享圖片

第三種使用方式 瀏覽器訪問

技術分享圖片
<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script type="text/javascript">
    function queryWeather() {
        var xhr = new XMLHttpRequest();
        xhr.open("post", "http://127.0.0.1:12345/weather", true);
        xhr.setRequestHeader("content-type","text/xml;charset=utf-8");
        //設置回調函數
        xhr.onreadystatechange=function(){
            if(4 == xhr.readyState && 200 == xhr.status){
                alert(xhr.responseText);
            }
        }
        //組織SOAP協議數據
        var soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
        +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
            +"<soap:Body>"
            +"<getWeatherInfo xmlns=\"http://WebXml.com.cn/\">"
                +"<cityName>"+document.getElementById("cityName").value+"</cityName>"
              +"<userID></userID>"
            +"</getWeatherInfo>"
          +"</soap:Body>"
        +"</soap:Envelope>";
        //發送數據
        xhr.send(soapXML);
    }
  </script>
 </head>
 <body>
       天氣查詢:<input type="text" id="cityName"/> <input type="button" value="查詢" onclick="javascript:queryWeather();"/>
 </body>
</html>
技術分享圖片

2. CXF框架

CXF是一個開源的webservice框架
CXF支持SOAP1.1/1.2,REST 協議
CXF支持XML,JSON(僅REST下) 的數據格式

服務端 JAX-WS方式(SOAP)

//@BindingType(SOAPBinding.SOAP12HTTP_BINDING)  默認發布SOAP1.1, 該註解發布SOAP1.2
@WebService
public interface WeatherInterface {
    public String queryWeather(String cityName);
}
技術分享圖片
public class WeatherImpl implements WeatherInterface {
    @Override
    public String queryWeather(String cityName) {
        String weather = "晴";
        return weather;
    }
}
技術分享圖片 技術分享圖片
//與spring整合後可不要該類
public class WeatherServer {
    public static void main(String[] args) {
        JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();
        //設置服務接口
        jaxWsServerFactoryBean.setServiceClass(WeatherInterface.class);
        //設置服務實現類
        jaxWsServerFactoryBean.setServiceBean(new WeatherImpl());
        //設置服務地址
        jaxWsServerFactoryBean.setAddress("http://127.0.0.1:12345/ws/weather");
        //發布
        jaxWsServerFactoryBean.create();
    }
}
技術分享圖片

與web整合, spring+CXFservlet替代WeatherServer類

技術分享圖片
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
                            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
                            http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
    
    <!-- 服務實現類 -->
    <bean id ="weatherImpl" class="com.zx.server.WeatherImpl"/>
     
    <!-- 攔截器  --
    <bean id ="inIntercepter" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
    <bean id ="outIntercepter" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
    -->
    
    <!-- 方式1 用JaxWsServerFactoryBean發布SOAP協議的服務 -->
    <jaxws:server address="/weather" serviceClass="com.zx.server.WeatherInterface">
        <jaxws:serviceBean>
            <ref bean="weatherImpl"/>  <!-- 實現類 -->
        </jaxws:serviceBean>
        <!-- 配置攔截器 --
        <jaxws:inInterceptors>
            <ref bean="inIntercepter"/>
        </jaxws:inInterceptors>
        <jaxws:outInterceptors>
            <ref bean="outIntercepter"/>
        </jaxws:outInterceptors>
        -->
    </jaxws:server>

    <!-- 方式2 用Endpoint發布SOAP協議的服務 -->    
    <jaxws:endpoint address="/weather" implementor="com.zx.server.WeatherImpl"/>        
</beans>
技術分享圖片

endPoint 只支持發布實現類
JaxWsServerFactoryBean還可以發布接口

web.xml

技術分享圖片
  <!-- 配置CXF的Servlet -->
  <servlet>
      <servlet-name>CXF</servlet-name>
      <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>CXF</servlet-name>
      <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>
技術分享圖片

客戶端

首先, 類似wsimport, 使用CXF下的Wsdl2java生成支持類, 導入工程中

技術分享圖片
public class WeatherClient {
    public static void main(String[] args) {
        JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
        //設置服務接口
        jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class);
        //設置服務地址
        jaxWsProxyFactoryBean.setAddress("http://127.0.0.1:12345/ws/weather");
        //獲取服務接口, 可與spring整合替代
        WeatherInterface weatherInterface = jaxWsProxyFactoryBean.create(WeatherInterface.class);
        //調用查詢方法
        String weather = weatherInterface.queryWeather("保定");
        System.out.println(weather);
    }
}
技術分享圖片

與spring整合後由spring生成weatherInterface實例

  <!-- 用JaxWsProxyFactoryBean建立客戶端 -->    
    <jaxws:client id="weatherClient" address="http://127.0.0.1:12345/ws/weather" serviceClass="com.zx.WeatherInterface"/>

服務端 JAX-RS方式(REST風格)

基礎bean

技術分享圖片
@XmlRootElement(name="student")  //能被格式化為XML
public class Student {
    private long id;
    private String name;
    private Date birthday;
    public getXXX(), setXXX();  // get set方法
}
技術分享圖片

服務接口

技術分享圖片
@WebService
@Path("/student") //將請求路徑“/student”映射到接口上
public interface StudentInterface {

    @POST // 指定請求方式 GET / POST
    @Produces(MediaType.APPLICATION_XML) //指定服務數據類型 XML / JSON
    @Path("/query/{id}")  //將請求路徑/query映射到方法上, 參數註入配合@PathParam註解
    public Student query(@PathParam("id")long id);
    
    @GET
    @Produces({"application/json;charset=utf-8",MediaType.APPLICATION_XML})  //同時指定json和xml, 添加訪問參數?_type=json返回json; 添加?_type=xml返回XML
    @Path("/queryList/{name}")
    public List<Student> queryList(@PathParam("name")String name);
}
技術分享圖片

服務實現, 僅舉例

技術分享圖片
public class StudentImpl implements StudentInterface {
    @Override
    public Student query(long id) {
        Student st = new Student();
        st.setId(110);
        st.setName("張三");
        st.setBirthday(new Date());
        return st;
    }

    @Override
    public List<Student> queryList(String name) {
        Student st = new Student();
        st.setId(110);
        st.setName("張三");
        st.setBirthday(new Date());
        List<Student> list = new ArrayList<Student>();
        list.add(st);
        return list;
    }
}
技術分享圖片

發布

技術分享圖片
public class StudentServer {
    public static void main(String[] args) {
        //JAXRSServerFactoryBean 發布REST的服務
        JAXRSServerFactoryBean jaxRSServerFactoryBean = new JAXRSServerFactoryBean();
        jaxRSServerFactoryBean.setServiceBean(new StudentImpl());
        jaxRSServerFactoryBean.setResourceClasses(StudentImpl.class);
        jaxRSServerFactoryBean.setAddress("http://127.0.0.1:12345/ws/user");
        jaxRSServerFactoryBean.create();
    }
}
技術分享圖片

與web整合, spring+CXFservlet替代StudentServer類

技術分享圖片
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
                            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
                            http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
    <!-- 配置服務實現類 -->
    <bean id = "studentImpl" class="com.zx.StudentImpl"/>
    
    <!-- 使用JAXRSServerFactoryBean發布REST的服務 -->    
    <jaxrs:server address="/user">
        <jaxrs:serviceBeans>
            <ref bean="studentImpl"/>
        </jaxrs:serviceBeans>
    </jaxrs:server>
</beans>
技術分享圖片

web.xml

技術分享圖片
  <!-- 配置CXF的Servlet -->
  <servlet>
      <servlet-name>CXF</servlet-name>
      <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>CXF</servlet-name>
      <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>
技術分享圖片

REST風格下WSDL訪問網址為http://127.0.0.1:12345/ws/user?_wadl

Webservice與CXF框架快速入門