使用CXF開放webservice接口

最近工做中須要作產品之間的對接工做,做爲服務器端對外開放服務接口,而本次所採用的是webservice開放接口。在選擇使用何種技術開放接口,曾考慮使用http開放接口,最終選擇webservice緣由有:一、此接口非網絡公開接口,只適用於本次產品對接。二、webservice接口穩定且支持跨域,使用http還要考慮跨域的問題。三、webservice支持複雜類型的數據傳輸。基於此,選用webservice開放接口。java

考慮到簡化webservice開發過程,在開發中並未對每一個功能開放webservice接口,而是依賴於接口文檔,開放統一的webservice接口,用業務編號區分不一樣的接口,統一調用。如下是開發過程:web

一、導入依賴包(cxf)spring

<apache.cxf.version>3.1.10</apache.cxf.version>

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>${apache.cxf.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>${apache.cxf.version}</version>
</dependency>

二、配置服務(web.xml)apache

<!-- cxf -->
<servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/webservice/*</url-pattern>
</servlet-mapping>

三、配置spring自動掃描json

<?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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation="   
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd 
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd 
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
    default-autowire="byName"> <!-- spring自動掃包 -->
    <context:component-scan base-package="com.my.webservice" />

    <bean id="myWebServiceExcuteUtil"
        class="com.my.webservice.utils.MyWebServiceExcuteUtil"
        init-method="init" lazy-init="default"></bean>

    <bean id="MyWebService"
        class="com.my.webservice.impl.MyWebServiceImpl">
    </bean>

    <!-- 導入jar包中的cxf配置文件。這裏不用寫,是寫好的放在jar包裏,直接引入便可。 -->
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <!-- define web service provider -->
    <!-- 要暴露給外部調用的接口,address:請求路徑 -->
    <jaxws:endpoint
        implementor="com.my.webservice.impl.TestWebServiceImpl"
        address="/testWebServiceImpl" />
    <jaxws:endpoint
        implementor="com.my.webservice.impl.MyWebServiceImpl"
        address="/myWebServiceImpl" />
</beans>

四、編寫webservice接口及實現類跨域

/**
 * $Id:$
 * Copyright 2014-2018 Hebei Sinounited Technology Company Ltd. All rights reserved.
 */
package com.my.webservice;

import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * 
 * @author Heller.Zhang
 * @since 2018年11月1日 下午5:30:02
 */
@WebService(targetNamespace = "com.my.webservice.TestWebService")
public interface TestWebService {

    public String test(@WebParam(name = "type") Integer type, @WebParam(name = "data") String data);
}
/**
 * $Id:$
 * Copyright 2014-2018 Hebei Sinounited Technology Company Ltd. All rights reserved.
 */
package com.my.webservice.impl;

import javax.jws.WebService;

import org.springframework.stereotype.Component;

import com.my.webservice.TestWebService;

/**
 * 
 * @author Heller.Zhang
 * @since 2018年11月1日 下午5:12:08
 */
@WebService(targetNamespace="com.my.webservice.TestWebService",endpointInterface="com.my.webservice.TestWebService")
@Component("TestWebService")
public class TestWebServiceImpl implements TestWebService {

    @Autowired
    private MyWebServiceExcuteUtil myWebServiceExcuteUtil;

    @Override
    public String test(Integer type, String data) {
        return myWebServiceExcuteUtil.excute(type, data);
    }

}
/**
 * $Id:$
 * Copyright 2014-2018 Hebei Sinounited Technology Company Ltd. All rights reserved.
 */
package com.my.webservice.utils;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.my.webservice.contant.GpWebServiceEnum;
import com.my.webservice.model.MyWebServiceModel;
import com.my.framework.common.spring.utils.SpringContextUtils;
import com.my.framework.exception.DaoException;
import com.my.framework.exception.ManagerException;
import com.my.framework.exception.ServiceException;
import com.my.framework.model.ResultDTO;
import com.my.framework.util.JsonHelper;

/**
 * webservice調用統一工具類
 * 
 * @author Heller.Zhang
 * @since 2018年11月2日 上午9:30:04
 */
public class MyWebServiceExcuteUtil {

    Logger logger = LoggerFactory.getLogger(MyWebServiceExcuteUtil .class);


    Map<Integer, MyWebServiceModel> map = new HashMap<Integer, MyWebServiceModel>();

    /**
     * 初始化
     * 
     * @author Heller.Zhang
     * @since 2018年11月2日 下午12:48:07
     */
    public void init() {
        logger.debug("-------------init MyWebServiceExcuteUtil-----------------");
        for (MyWebServiceEnume : MyWebServiceEnum.values()) {
            MyWebServiceModelmodel = new MyWebServiceModel();
            model.setType(e.getType());
            Object bean = SpringContextUtils.getBean(e.getBean());
            model.setBean(bean);
            Class<?> dataType = null;
            try {
                dataType = Class.forName(e.getDataType());
                model.setDataClass(dataType);
            } catch (ClassNotFoundException e1) {
                throw new RuntimeException("未找到【" + e.getDataType() + "】實體類!", e1);
            }
            Method method = BeanUtils.findMethod(bean.getClass(), e.getMethod(),
                    new Class[] { dataType});
            model.setMethod(method);
            map.put(e.getType(), model);
        }
    }

    /**
     * webservice接口調用
     * 
     * @param type 業務類型
     * @param data 數據
     * @return
     * @author Heller.Zhang
     * @since 2018年11月2日 上午9:32:52
     */
    public String excute(Integer type, String data) {
        // 獲取到webservice配置信息
        MyWebServiceModel model = map.get(type);
        if (model == null) {
            ResultDTO<Object> faildResult = new ResultDTO<Object>();
            faildResult.setSuccess(false);
            faildResult.setMsg("錯誤的業務編號!");
            return JsonHelper.serialize(faildResult);
        }
        // 將data轉換爲相應類型的數據
        Object dataObj = JsonHelper.readValueCustom(data, model.getDataClass());
        // 調用方法
        try {
            Object result = model.getMethod().invoke(model.getBean(), dataObj);
            return JsonHelper.serialize(result);
        } catch (ServiceException | ManagerException | DaoException e) {
            logger.error(e.getMessage(), e);
            ResultDTO<Object> faildResult = new ResultDTO<Object>();
            faildResult.setSuccess(false);
            faildResult.setMsg(e.getMessage());
            return JsonHelper.serialize(faildResult);
        } catch (Exception e1) {
            logger.error("調用webservice接口失敗!", e1);
            ResultDTO<Object> faildResult = new ResultDTO<Object>();
            faildResult.setSuccess(false);
            faildResult.setMsg("調用webservice接口失敗!");
            return JsonHelper.serialize(faildResult);
        }
    }
}
/**
 * $Id:$
 * Copyright 2014-2018 Hebei Sinounited Technology Company Ltd. All rights reserved.
 */
package com.my.webservice.contant;

/**
 * 業務及實現對應枚舉
 * 
 * @author Heller.Zhang
 * @since 2018年11月2日 上午9:34:51
 */
public enum MyWebServiceEnum {
    SERVICE1(0, "*****Impl", "******",
            "com.my.qo.******"),// NL,因涉及業務,故以*代替具體配置
    ;

    /** 業務編號 */
    private Integer type;

    /** 業務實現類(必須是業務模塊的service bean名稱) */
    private String bean;

    /** 業務實現方法名稱 */
    private String method;

    /** 接收數據類型(全稱) */
    private String dataType;

    MyWebServiceEnum(Integer type, String bean, String method, String dataType) {
        this.type = type;
        this.bean = bean;
        this.method = method;
        this.dataType = dataType;
    }

    /**
     * @return the type
     */
    public Integer getType() {
        return type;
    }

    /**
     * @param type the type to set
     */
    public void setType(Integer type) {
        this.type = type;
    }

    /**
     * @return the bean
     */
    public String getBean() {
        return bean;
    }

    /**
     * @param bean the bean to set
     */
    public void setBean(String bean) {
        this.bean = bean;
    }

    /**
     * @return the method
     */
    public String getMethod() {
        return method;
    }

    /**
     * @param method the method to set
     */
    public void setMethod(String method) {
        this.method = method;
    }

    /**
     * @return the dataType
     */
    public String getDataType() {
        return dataType;
    }

    /**
     * @param dataType the dataType to set
     */
    public void setDataType(String dataType) {
        this.dataType = dataType;
    }

    public static MyWebServiceEnum of(Integer type) {
        for (MyWebServiceEnum e : MyWebServiceEnum .values()) {
            if (e.getType().equals(type)) {
                return e;
            }
        }
        return null;
    }
}

以上,便將webservice配置完成並與springMVC相結合,在定義業務實現時,須要遵循必定的規則(由於依賴於接口文檔,因此須要必定的開發規則),如:入參類型、出參類型、解析方式等。上述例子中對外接口使用業務編號的方式指定不一樣的業務接口調用,數據傳輸使用json格式字符串進行序列化和反序列化。webservice接口使用統一接口。服務器

webservice地址能夠配置多個,同時每個webservice地址下能夠有多個webservice接口,本例只提供了一個接口test,以上接口結構適合於接口參數、返回數據的格式一致且接口數量較多的狀況,依賴於webservice接口文檔用以對接,因此對文檔的嚴謹和準確性要求較高。若是接口量很少,或者接口參數、返回數據的格式大多不一致的狀況下,可以使用開放多接口的形式,在webservice實現類中直接調用業務實現方法,作到一個webservice接口對應一個業務方法的結構。網絡

結語:webservice是對外開放服務接口的一種方式,在技術選型、模式選型時不必生搬硬套,適合項目的纔是最好的。app

相關文章
相關標籤/搜索