一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

如何在SpringMVC項(xiàng)目中部署WebService服務(wù)并打包生成客戶端

 三十的狼 2020-11-18

場景

某SpringMVC項(xiàng)目原本為一個HTTP的WEB服務(wù)項(xiàng)目,之后想在該項(xiàng)目中添加WebService支持,使該項(xiàng)目同時提供HTTP服務(wù)和WebService服務(wù)。其中WebService服務(wù)通過 /ws/** 地址攔截。

配置

通過配置讓SpringMVC支持WebService。

依賴

首先通過Maven引入必要依賴包。

  • org.apache.cxf
  • org.apache.neethi
  • com.ibm.wsdl4j
  • org.apache.XmlSchema

Web.xml

通過配置Web.xml使Spring框架具備WebService特性,這里通過添加Servlet(這里使用CXFServlet)實(shí)現(xiàn)。假設(shè)SpringMVC本身的DispatcherServlet已經(jīng)啟用,則在第2啟動順序添加CXFServlet。并添加servlet-mapping匹配請求。
配置如下

<!-- 在上下文中添加配置文件 -->
<context-param>
    <param-name>patchConfigLocation</param-name>
    <param-value>
        /WEB-INF/applicationServlet.xml
        /WEB-INF/webservice.xml
    <param-value>
</context-param>
<!-- 添加servlet -->
<servlet>
    <servlet-name>ws</servlet-name>
    <servlet-class>org.apache.cxf.trasport.servlet.CXFServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>ws</servlet-name>
    <url-pattern>/ws/**</url-pattern>
</servlet-mapping>

webservice.xml

將webservice的接口配置單獨(dú)分離出來。配置如下:

<beans xmlns="http://www./schema/beans"
    xmlns:xsi="http://www./2001/XMLSchema-instance"
    xmlns:p="http://www./schema/p"
    xmlns:jaxws="http://cxf./jaxws"
    xmlns:context="http://www./schema/context"
    xmlns:mvc="http://www./schema/mvc"
    xsi:schemaLocation="
        http://www./schema/beans
        http://www./schema/beans/spring-beans.xsd
        http://www./schema/mvc
        http://www./schema/mvc/spring-mvc.xsd
        http://cxf./jaxws
        http://cxf./schemas/jaxws.xsd
        http://www./schema/context
        http://www./schema/context/spring-context.xsd">
    <!-- cxf必要配置 -->
    <import resource="classpath:META-INF/cxf/cxf.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />

    <!-- 接口的實(shí)現(xiàn)類聲明 -->
    <jaxws:endpoint id="ticketDecodeAuthService" 
        implementorClass="com.xxx.apps.web.ws.server.decode.XXXServiceImpl" 
        address="/ticketDecodeAuth" />

</beans>

接口編寫

對應(yīng)上文聲明的接口文檔在寫在相應(yīng)的位置上(如本文例子則寫在com.xxx.apps.web.ws.server.decode包中)
代碼如下:

@WebService
@SOAPBinding(style = Style.RPC)
public interface XXXService {

    public WSReturn getAuth(String userName, String password) throws Exception;

}

接口實(shí)現(xiàn)類:

@WebService
@SOAPBinding(style = Style.RPC)
@SuppressWarnings("deprecation")
public class XXXServiceImpl implements XXXService {

    private static final Logger LOGGER = Logger.getLogger(XXXServiceImpl.class);

    @Override
    public WSReturn getAuth(String userName, String password) throws Exception {
        // WSReturn 是自定義的通用接口返回包裝,可以用別的
        WSReturn res = new WSReturn();
        // TODO : your code here
        return res;
    }

}

發(fā)布接口效果

啟動SpringMVC項(xiàng)目,根據(jù)配置文件定義,接口地址類似:http://ip:port/項(xiàng)目名/ws/**
若本例配置則有如下接口可以查看:

查看所有接口列表

http://ip:port/項(xiàng)目名/ws

某具體端口(XXXService)為例

這也是客戶端調(diào)用時候的地址
http://ip:port/項(xiàng)目名/ws/XXXService?wsdl
這里可以看到端口的規(guī)范定義

客戶端編寫

客戶端代碼

通過CXF的動態(tài)代理方式編寫,以反射方式將class直接引入可以實(shí)現(xiàn)統(tǒng)一調(diào)用方法。這樣該Client即可調(diào)用任意接口。
代碼如下:

/**
 * webservice服務(wù)客戶端
 * @author WSY
 *
 */
public class WSClient {

        private static Logger logger = LoggerFactory.getLogger(WSClient.class);

        /**
         * 調(diào)用代理
         * @param cls 服務(wù)接口代理
         * @param method 方法名
         * @param wsdl wsdl地址
         * @param params 參數(shù)Object[]
         * @return
         * @throws Exception
         */
        @SuppressWarnings("rawtypes")
        public static WSReturn invoke(Class cls,String method,String wsdl, Object[] params) throws Exception{
            synchronized(WSClient.class){
                logger.info("[WSClient invoking] - class:"+cls.getName()+"; method:"+method+"; wsdl:"+
                        wsdl+"; params:"+getParams(params));

                JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
                factory.getInInterceptors().add(new LoggingInInterceptor());
                factory.getOutInterceptors().add(new LoggingOutInterceptor());
                factory.setServiceClass(cls);
                factory.setAddress(wsdl);
                Object cInstance = factory.create();
                Method invokeMethod = null;
                for(Method m : cls.getDeclaredMethods()){
                    if(m.getName().equalsIgnoreCase(method)){
                        invokeMethod = m;
                        break;
                    }
                }
                if(invokeMethod == null)
                    throw new Exception("ERROR:method not found");

                WSReturn res = (WSReturn) invokeMethod.invoke(cInstance, params);
                return res;
            }

            private static String getParams(Object[] params){
                StringBuilder sb = new StringBuilder("{");
                for(Object b : params){
                    sb.append(b).append(",");
                }
                if(sb.length()==1)
                    return "{}";
                else 
                    return sb.substring(0,sb.length()-1)+"}";
            }
    }
}

打包

寫個Ant腳本將一些必要的Java類和定義的Interface(不要打?qū)崿F(xiàn)類)打成包。本文中將Client代碼也寫在了Service端了,所以將WSClient也一并打包進(jìn)去。這樣在編寫對應(yīng)的客戶端時候,僅需專注于功能實(shí)現(xiàn)即可。

<?xml version="1.0"?>
<project name="tws-interfaces" default="jar" basedir=".">

    <!-- Give user a chance to override without editing this file or typing -D -->
    <property name="coredir" location="." />
    <property name="classdir" location="${basedir}/target/classes" />

    <target name="jar" description="Build the jars for core">
        <delete file="${coredir}/webservice-interfaces-1.0.jar" />
        <jar destfile="${coredir}/webservice-interfaces-1.0.jar">
            <fileset dir="${classdir}">
                <include name="**/com/xxx/apps/web/ws/server/**/*Service.class" />
                <include name="**/com/xxx/apps/web/ws/server/tokenservice/**/*.class" />
                <include name="**/com/xxx/apps/web/ws/server/WSReturn.class"/>
                <include name="**/com/xxx/apps/comm/ResultState.class"/>
                <include name="**/com/xxx/apps/web/ws/server/wsclient/WSClient.class"/>
                <include name="**/com/xxx/apps/comm/RespResult.class"/>
                <exclude name="**/com/xxx/apps/web/ws/server/**/*Impl.class" />
            </fileset>
        </jar>
        <copy todir="../xxxclient/lib" file="./webservice-interfaces-1.0.jar"></copy>
    </target>

</project>

客戶端項(xiàng)目實(shí)現(xiàn)

依賴

首先通過Maven引入必要依賴包。

  • org.apache.cxf.cxf-rt-frontend-jaxws
  • org.apache.cxf.cxf-rt-databinding-aegis
  • org.apache.cxf.cxf-rt-transports-http
  • org.apache.cxf.cxf-rt-transports-http-jetty
  • commons-codec.commons-codec

    最重要的:引入server端打包好的jar包,里邊有WSClient和必要的接口

        <dependency>
            <groupId>com.xxx</groupId>
            <artifactId>xxxserver</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/webservice-interfaces-1.0.jar</systemPath>
        </dependency>

WSClient調(diào)用

通過直接調(diào)用jar包中的WSClient即可調(diào)用遠(yuǎn)程WebService接口。
調(diào)用示例代碼如下:

/** 這里將調(diào)用注釋復(fù)制過來
     * 調(diào)用代理
     * @param cls 服務(wù)接口代理
     * @param method 方法名
     * @param wsdl wsdl地址
     * @param params 參數(shù)Object[]
     * @return
     * @throws Exception
     */
WSReturn res= WSClient.invoke(XXXService.class
                , "getAuth"
                ,endpoints.get(XXXService.class.getName())
                , new Object[]{"admin","admin"});
        if(token.getStatusId() == ResultState.SUCESS){
            tokenValue = (String) token.getMap().get("token");
        } else {
            logger.error("獲取token失敗:"+token.getMsg());
        }

一些坑

一定要引入cxf的必要配置

雖然在項(xiàng)目中看不到,但是這些xml文件在cxf的jar包中。

    <!-- cxf必要配置 -->
    <import resource="classpath:META-INF/cxf/cxf.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />

Interface的類路徑一定要統(tǒng)一

如服務(wù)端的 XXXService.javacom.xxx.web.ws.server 中,則在客戶端的XXXService.java類也應(yīng)該在相同的路徑即: com.xxx.web.ws.server 。 所以為方便起見,用Ant直接打包比較方便,不容易錯。

客戶端并發(fā)問題

本例中調(diào)用WSClient,通過反射機(jī)制調(diào)用,共用一個Factory,因此在并發(fā)時候容易出現(xiàn)問題,需要在WSClient中加鎖

原文地址:https://blog.csdn.net/tzdwsy/article/details/51938786      

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    亚洲国产一级片在线观看| 亚洲欧美国产中文色妇| 国产精品久久熟女吞精| 久久热中文字幕在线视频| 91老熟妇嗷嗷叫太91| 国产极品粉嫩尤物一区二区 | 中文字幕亚洲精品人妻| 亚洲伦理中文字幕在线观看| 中国少妇精品偷拍视频| 成人精品欧美一级乱黄| 空之色水之色在线播放| 日本午夜免费观看视频| 国产亚洲欧美一区二区| 狠狠做五月深爱婷婷综合| 欧美午夜不卡在线观看| 国产91色综合久久高清| 久久青青草原中文字幕| 三级理论午夜福利在线看| 黑丝国产精品一区二区| 草草草草在线观看视频| 久久精品国产99国产免费| 国产日韩久久精品一区| 日本一区二区三区黄色| 欧美精品中文字幕亚洲| 亚洲精品国产精品日韩| 在线免费视频你懂的观看| 在线免费看国产精品黄片| 国产又粗又猛又长又大| 亚洲视频一区自拍偷拍另类| 午夜国产精品国自产拍av| 国产一区二区三区口爆在线| 国产亚洲精品岁国产微拍精品| 日本人妻精品中文字幕不卡乱码 | 中文字字幕在线中文乱码二区| 欧美日韩精品一区二区三区不卡| 国产精品午夜福利免费在线| 日本高清不卡一二三区| 国产又粗又爽又猛又黄的| 美女黄色三级深夜福利| 国内精品偷拍视频久久| 久久热这里只有精品视频|