码迷,mamicode.com
首页 > Web开发 > 详细

WebService的发布及客户端的调用

时间:2014-11-16 15:54:01      阅读:635      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   io   color   ar   os   sp   

一.目录

1.JAX-WS发布WebService

1.1 创建一个简单的WS

1.2 打包部署和发布

2.CXF+Spring发布WebService

3.客户端的调用方式

二.正文

1. JAX-WS发布WebService

JAX-WS (Java API for XML Web Services) 是一组专门用于实现 XML Web Services 的 Java API。JDK 1.6 自带 JAX-WS 版本为 2.1。不过,JAX-WS 只提供 web services 的基础功能,所以如果你希望实现 web services 的复杂功能,比如 WS-Security,WS-Policy,WS-RM 等,那就需要切换到 Apache CXF 、Metro 或者 Axis。

1.1 创建一个简单的WebService

首先,还是来看一下jdk API1.7中javax.jws包下面关于注解@WebService的描述吧。它是用来标记一个被定义为Web Service的实现类或接口的。元素endpointInterface是用来指明服务端接口的。这就是我们在定义接口和实现的时候要用的了。

bubuko.com,布布扣

接着,新建一个Java项目,定义好服务接口和具体实现类,如下:

package com.lglan.webservice.server;

import javax.jws.WebService;

@WebService
public interface GreetingService {

    public String greeting(String userName);
}
package com.lglan.webservice.server.impl;

import java.util.Calendar;

import javax.jws.WebService;

import com.lglan.webservice.server.GreetingService;

@WebService(endpointInterface="com.lglan.webservice.server.GreetingService")
public class GreetingServiceImpl implements GreetingService {

    public String greeting(String userName) {
        // TODO Auto-generated method stub
        return "Hello " + userName + ", currentTime is "
        + Calendar.getInstance().getTime();
    }

}

最后,就是来发布服务了,这里用到了javax.xml.ws.Endpoint类的publish方法,详见API文档

public static Endpoint publish(String address,
               Object implementor)
Creates and publishes an endpoint for the specified implementor object at the given address.
package com.lglan.webservice.server.app;

import javax.xml.ws.Endpoint;

import com.lglan.webservice.server.impl.GreetingServiceImpl;

public class WebServiceMain {
    
    public static void main(String[] args) {
        System.out.println("web service start");
        GreetingServiceImpl implementor= new GreetingServiceImpl();
        String address="http://localhost:8080/greetingService";
        Endpoint.publish(address, implementor);
        System.out.println("web service started");
    }

}

运行上面的类,在浏览器中请求http://localhost:8080/greetingService?wsdl就能看到我们发布的webservice接口了。

1.2 打包部署和发布

以上我们是通过在IDE中直接执行java application来发布服务的,那如何把项目进行打包部署呢?当然,最常见的方法就是把项目发布成web项目然后在web容器中启动(该方法在第二部分介绍)。这里,最简单的方法就是在jre中直接运行编译后的WebServiceMain.class文件,跟我们在IDE中一样,不需要容器,只要有jre环境就行。

用maven的assembly插件来打包是最方便的了(当然,要用maven来管理项目,用maven谁用谁知道),只要在项目的pom.xml中配置assembly插件,然后在assembly.xml中描述你想要怎么打包就行了。

pom.xml的<plugins></plugins>节点中加入:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration> <!--描述文件路径-->
        <descriptor>src/main/assembly/assembly.xml</descriptor>
    </configuration>
    <executions> <!--执行器 mvn assembly:assembly-->
        <execution>
            <id>make-assembly</id> <!--名字任意 -->
            <phase>package</phase> <!-- 绑定到package生命周期阶段上 -->
            <goals>
                <goal>single</goal> <!-- 只运行一次 --> 
            </goals>
        </execution>
    </executions>
</plugin>

assembly.xml

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <id>assembly</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>src/main/assembly/bin</directory><!-- 源路径 -->
            <outputDirectory>bin</outputDirectory><!-- 输出路径 -->
            <fileMode>0755</fileMode><!-- 文件权限rwx -->
        </fileSet>
        <fileSet>
            <directory>src/main/resources</directory>
            <outputDirectory>conf</outputDirectory>
            <fileMode>0644</fileMode>
        </fileSet>
    </fileSets>
    <dependencySets>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
        </dependencySet>
    </dependencySets>
</assembly>

执行maven install 或 package命令后,项目会被打包成三个文件夹:/bin, /conf, /lib,其中/conf下面放的是配置文件,/lib下面放的是项目依赖的所有的jar包(包括项目自身的jar包)。那么,/bin目录下是什么呢?这里放的是我们自己编写的用来启动和停止服务的脚本,例如:windows下面的.bat文件和Unix或Linux下的.sh脚本文件。好吧,我们就来写启动脚本吧,在项目中新建src/main/assembly/bin路径,创建脚本如下:

start.bat (其中goto start … :start中间代码是被跳过的,这里用这种方法来达到注掉一段代码的目的了,bubuko.com,布布扣)

@echo off  
setlocal enabledelayedexpansion  

goto start
    ::方法一,用start命令来启动java.exe
    echo %JAVA_HOME%  
    set jre="%JAVA_HOME%\bin\java"  
    set tempclass="%JAVA_HOME%\lib\dt.jar";"%JAVA_HOME%\lib\tools.jar";
    cd ..\lib
    for %%i in (*) do set tempclass=!tempclass!;%%i;
    start "GreetingService" %jre% -classpath !tempclass! com.lglan.webservice.server.app.WebServiceApp  
:start

::方法二,本地配置好jdk的环境变量,直接执行java指令
set LIB_JARS=""
cd ..\lib  
for %%i in (*) do set LIB_JARS=!LIB_JARS!;..\lib\%%i;
java -Xms64m -Xmx1024m -XX:MaxPermSize=64M -classpath ..\conf;%LIB_JARS% com.lglan.webservice.server.app.WebServiceApp

endlocal

start.sh

#!/bin/bash
LIB_JARS=.  
for i in ls lib/*.jar   
do   
LIB_JARS=$LIB_JARS:./lib/$i  
done  
$JAVA_HOME/bin/java -classpath $LIB_JARS com.lglan.webservice.server.app.WebServiceApp

stop.sh

#!/bin/sh
APP_MAIN=com.lglan.webservice.server.app.WebServiceApp

tradePortalPID=0
 
getTradeProtalPID(){
    javaps=`$JAVA_HOME/bin/jps -l | grep $APP_MAIN`
    if [ -n "$javaps" ]; then
        tradePortalPID=`echo $javaps | awk {print $1}`
    else
        tradePortalPID=0
    fi
}

shutdown(){
    getTradeProtalPID
    echo "========================================================================================"
    if [ $tradePortalPID -ne 0 ]; then
        echo -n "Stopping $APP_MAIN(PID=$tradePortalPID)..."
        kill -9 $tradePortalPID
        if [ $? -eq 0 ]; then
            echo "[Success]"
            echo "================================================================================"
        else
            echo "[Failed]"
            echo "================================================================================"
        fi
        getTradeProtalPID
        if [ $tradePortalPID -ne 0 ]; then
            shutdown
        fi
    else
        echo "$APP_MAIN is not running"
        echo "===================================================================================="
    fi
}

shutdown

好了,按照上面的方法用maven打个包,解压之后,在相应的操作系统下执行start脚本就可以发布服务了。

2.CXF+Spring发布WebService

首先,要导入依赖的jar包,直接在pom.xml的<dependencies></dependencies>中添加

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-api</artifactId>
    <version>2.5.0</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>2.5.0</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-bindings-soap</artifactId>
    <version>2.5.0</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>2.5.0</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-ws-security</artifactId>
    <version>2.5.0</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-jetty</artifactId>
    <version>2.4.6</version>
</dependency>

通过Spring来管理服务类,由cxf的jaxws.xsd定义了服务端的节点jaxws:endpoint,配置文件如下:

<?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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <context:component-scan base-package="com.lglan.webservice.server"/>
  
    <jaxws:endpoint id="GreetingService" implementor="com.lglan.webservice.server.impl.GreetingServiceImpl" address="http://localhost:8080/greetingService" /> 
    
</beans>

配置完成了,接下来写个main方法来启动服务吧。

package com.lglan.webservice.server.app;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class WebServiceStart {
    
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:cxf-spring.xml");
        ac.start();
        System.in.read();
    }

}

直接运行上面的类,在浏览器中输入http://localhost:8080/greetingService?wsdl就能看到发布成功了。

当然,这里还可以通过cxf-rt-frontend-jaxws包下面的org.apache.cxf.jaxws.JaxWsServerFactoryBean来创建服务,不需要在spring配置中添加服务类的bean了,代码如下:

package com.lglan.webservice.server.app;

import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

import com.lglan.webservice.server.impl.GreetingServiceImpl;

public class WebServiceMain2 {
    
    public static void main(String[] args) {
        //工厂模式创建jax
        JaxWsServerFactoryBean jwsFactoryBean = new JaxWsServerFactoryBean();
        jwsFactoryBean.setServiceClass(GreetingServiceImpl.class);
        jwsFactoryBean.setAddress("http://localhost:8080/greetingService");
        //获取一个server对象,并启动
        Server server = jwsFactoryBean.create();
        server.start();
        
    }
}

最后再讲一下怎么在web容器中发布Web Service :

第一步:将原来的Java项目转成Web项目,具体步骤请参考:

http://blog.sina.com.cn/s/blog_7deb4bd601019llp.html

第二步:项目的根路径下(这里对应webapp目录)添加web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="
    http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:cxf-spring.xml</param-value><!-- 这里指定spring配置文件 -->
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

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

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

还有,不要忘记修改原endpoint节点的address,在cxf-spring.xml配置文件中,修改后如下:

<?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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <context:component-scan base-package="com.lglan.webservice.server"/>
  
    <jaxws:endpoint id="GreetingService" implementor="com.lglan.webservice.server.impl.GreetingServiceImpl" address="/greetingService" /> 
    
</beans>

第三步,在tomcat中启动项目,访问配置的服务路径http://localhost:8080/cxf_ws_demo/services/greetingService?wsdl,发布成功!

bubuko.com,布布扣

二.客户端的调用方式

上面讲服务发布的方法,提到了三种:javax.xml.ws.Endpoint类的publish方法;cxf-rt-frontend-jaxws包下面的org.apache.cxf.jaxws.JaxWsServerFactoryBean类来创建服务;在spring配置文件中配置服务类。那么,客户端的调用也有类似的几种方法。

在写实现调用的方法之前,我们先来搭建一个客户端项目,在IDE中建一个maven管理的Java项目,pom文件中加了cxf依赖的jar包(同服务端,可选),cmd中执行cxf指令:wsdl2java –d D:\client –client http://localhost:8080/greetingService?wsdl,导入刚才cxf生成的客户端依赖包,准备工作完成。

方法1:继承javax.xml.ws.service类来创建service实例,该service类为我们提供了一个service()方法来获得服务,然后提供getPort()方法来动态调用服务接口。可喜的是,这个类完全不用我们自己来写,通过上面cxf指令生成的客户端代码包中已经给我们建好了,我们只要拿来用就行了。此例中,service类代码如下:

package com.lglan.webservice.server.impl;

import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceFeature;
import com.lglan.webservice.server.GreetingService;
import javax.xml.ws.Service;

/**
 * This class was generated by Apache CXF 2.2.8
 * Sat Nov 15 20:17:20 CST 2014
 * Generated source version: 2.2.8
 * 
 */


@WebServiceClient(name = "GreetingServiceImplService", 
                  wsdlLocation = "http://localhost:8080/greetingService?wsdl",
                  targetNamespace = "http://impl.server.webservice.lglan.com/") 
public class GreetingServiceImplService extends Service {

    public final static URL WSDL_LOCATION;
    public final static QName SERVICE = new QName("http://impl.server.webservice.lglan.com/", "GreetingServiceImplService");
    public final static QName GreetingServiceImplPort = new QName("http://impl.server.webservice.lglan.com/", "GreetingServiceImplPort");
    static {
        URL url = null;
        try {
            url = new URL("http://localhost:8080/greetingService?wsdl");
        } catch (MalformedURLException e) {
            System.err.println("Can not initialize the default wsdl from http://localhost:8080/greetingService?wsdl");
            // e.printStackTrace();
        }
        WSDL_LOCATION = url;
    }

    public GreetingServiceImplService(URL wsdlLocation) {
        super(wsdlLocation, SERVICE);
    }

    public GreetingServiceImplService(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public GreetingServiceImplService() {
        super(WSDL_LOCATION, SERVICE);
    }

    /**
     * 
     * @return
     *     returns GreetingService
     */
    @WebEndpoint(name = "GreetingServiceImplPort")
    public GreetingService getGreetingServiceImplPort() {
        return super.getPort(GreetingServiceImplPort, GreetingService.class);
    }

    /**
     * 
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns GreetingService
     */
    @WebEndpoint(name = "GreetingServiceImplPort")
    public GreetingService getGreetingServiceImplPort(WebServiceFeature... features) {
        return super.getPort(GreetingServiceImplPort, GreetingService.class, features);
    }

}

好了,我们可以通过以上类来获得服务接口并调用了,方法如下:

package com.lglan.webservice.client;

import java.net.URL;

import com.lglan.webservice.server.GreetingService;
import com.lglan.webservice.server.impl.GreetingServiceImplService;

public class TestGreetingService3 {
    public static void main(String[] args) throws Exception {
        GreetingServiceImplService gs = new GreetingServiceImplService(new URL("http://localhost:8080/cxf_ws_demo/services/greetingService?wsdl"));
        GreetingService port = gs.getGreetingServiceImplPort();
        System.out.println(port.greeting("World"));
    }

}

方法2:通过cxf-rt-frontend-jaxws包下面的org.apache.cxf.jaxws.JaxWsProxyFactoryBean类来获取客户端的代理类并创建服务接口,实现方法如下:

package com.lglan.webservice.client;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;  

import com.lglan.webservice.server.GreetingService;

  
public class TestGreetingService {  
    public static void main(String[] args) {  
        //创建WebService客户端代理工厂  
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();  
        //注册WebService接口  
        factory.setServiceClass(GreetingService.class);  
        //设置WebService地址  
        factory.setAddress("http://localhost:8080/cxf_ws_demo/services/greetingService?wsdl");  
        GreetingService greetingService = (GreetingService)factory.create();  
        System.out.println("invoke webservice...");  
        System.out.println("message context is:"+greetingService.greeting("World"));     
    }  
}

方法3:spring配置服务接口的bean

客户端添加spring的配置文件wsdl-service.xml,在<jaxws:client/>节点中配置服务地址和接口,如下:

<?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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <context:component-scan base-package="com.lglan.webservice.server"/>
     
    <jaxws:client id="GreetingService" serviceClass="com.lglan.webservice.server.GreetingService" 
                    address="http://localhost:8080/cxf_ws_demo/services/greetingService?wsdl"/>
                    
<!--   <bean id="proxyFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
    <property name="serviceClass"     value="com.lglan.webservice.server.GreetingService"/>
    <property name="address"         value="http://localhost:8080/cxf_ws_demo/services/greetingService?wsdl"/>   
    </bean>
 
  <bean id="GreetingService" class="com.lglan.webservice.server.GreetingService"
    factory-bean="proxyFactory" factory-method="create"/> -->

</beans>

最后,通过读spring的配置文件来实例化服务接口类并调用服务提供的方法:

package com.lglan.webservice.client;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.lglan.webservice.server.GreetingService;

public class TestGreetingService2 {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("wsdlService.xml");
        GreetingService greeting = (GreetingService) ac.getBean("GreetingService");
        System.out.println(greeting.greeting("World"));
    }

}

总之,客户端调用服务的方式有很多,可以按照自己的喜欢来,不用关心服务端是如何实现的。关于客户端的调用最近计划整理一篇接口测试客户端搭建的文章,更多内容就在那里详述吧。

附:demo源码地址 http://pan.baidu.com/s/1o69LtME

三.参考

webservice:

http://cxf.apache.org/docs/a-simple-jax-ws-service.html

http://cxf.apache.org/docs/writing-a-service-with-spring.html

http://blessht.iteye.com/blog/1105562/

http://www.ithov.com/linux/125942.shtml

http://www.cnblogs.com/doosmile/archive/2012/06/21/2557351.html

http://www.blogjava.net/icewee/archive/2012/07/06/382399.html

http://www.cnblogs.com/frankliiu-java/articles/1641949.html

打包部署:

http://blog.csdn.net/WANGYAN9110/article/details/38646677

http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html

http://menjoy.iteye.com/blog/382200

http://blog.csdn.net/junmuzi/article/details/12239303

http://blog.csdn.net/jadyer/article/details/7960802

http://blog.sina.com.cn/s/blog_7deb4bd601019llp.html

 

全文完…

WebService的发布及客户端的调用

标签:des   style   blog   http   io   color   ar   os   sp   

原文地址:http://www.cnblogs.com/beetle-shu/p/4100761.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!