Java WebService记

JAS-WS 的全称为 Java API for XML Services ,代指Java程序设计语言中用于创建 Web Services 的API。Java程序员通过该API可快速开发基于XML的 Web Services 客户端及服务端。

Web Services 是应用程序组件之一,可被其他应用程序使用, XML 是 Web Services 的基础, Web Services 包含以下三大要素。

SOAPWSDLUUDI

Web Services开发

常用的 Web Services 框架有 Apache Axis1 、 Apache Axis2 、 Apache CXF ,而 Apache Axis1 已经逐渐被淘汰所以本文不会讨论,重点关注 Apache Axis2 及 Apache CXF 。

Apache Axis2

在IDEA中新建 Axis2Demo 项目后右键选择 添加框架的支持 并选中 Web Application 。

从Apache Axis2官网处下载 war包 进行部署,将 axis2.war 解压后把 WEB-INF 和 axis2-web目录复制到项目的 web 目录下(如下图所示)并启动Tomcat Server。

访问 http://localhost:8080/Axis2Demo_war_exploded/axis2-web/index.jsp 出现下图的页面表示部署成功。

Axis2配置

在 Axis1 中的全局配置和 Servcies 的配置均在 server-config.wsdd 中进行配置,而 Axis2则将全局配置单独存放于 WEB-INF/conf/axis2.xml 中, services 的配置文件则位于 servcies。

发布服务(Publish Service)

新建一个 HelloService 类并编译为 HelloService.class 复制至 WEB-INF/pojo 目录下并重启服务。

// 不能声明packagepublicclassHelloService{publicHelloService(){}publicStringsayHello(){return"hello";    }publicStringsayHelloToPerson(String name){if(name ==null) {            name ="nobody";        }return"hello, "+ name;    }}

重启服务后再次访问 http://localhost:8080/Axis2Demo_war_exploded/services/HelloService?wsdl 即可发现新发布的服务,点击 HelloService 即可查看Axis自动为该服务生成的WSDL,其描述了如何调用服务的方法及返回内容:

使用 SoapUI 客户端调用 HelloService 服务方法:

而之所以 WEB-INF/pojo 目录下的 .class 文件会自动发布为服务是因为在 axis2.xml 配置文件中的 deployer 标签中所配置的该选项。

<!-- 如果需要在其他目录自动发布服务只需添加新的标签即可 -->

上述的方式发布服务需要将编译后的类放置在某个具体的目录中,且不能包含 package ,而使用 *.aar 的方式则可以解决此问题。首先在Project的根目录下新建 META-INF/services.xml ,文件内容可以参考官方示例 version.aar 。

<?xml version="1.0"encoding="UTF-8"?>一个简单的WebService<!-- 服务全类名 -->com.ws.test.services.HelloService<!-- 信息接收器, 无返回值用:RPCInOnlyMessageReceiver--><!-- 信息接收器, 有返回值用:RPCMessageReceiver-->

最终结构为如下所示,在项目根目录中执行 jar cvf HelloService.aar . 进行打包。

将打包后的文件复制至 WEB-INF/services 目录下,即可在服务列表中看到新注册的服务,或者在 Axis 后台中也可以上传包部署(因此如果应用程序的Axis后台可访问且为默认凭据即可部署恶意Service获取权限)。

客户端服务调用

调用 Web Service 可通过代码的方式实现也可以通过WSDL构造SOAP协议调用方法,最简便的方法则是使用SoapUI,其会根据 Web Service 的WSDL生成对应方法的SOAP协议请求。

// 代码实现Web Service调用importjavax.xml.namespace.QName;importorg.apache.axis2.addressing.EndpointReference;importorg.apache.axis2.client.Options;importorg.apache.axis2.rpc.client.RPCServiceClient;publicclassWebServiceClient {publicstaticvoidmain(String[] args)throwsException {        RPCServiceClient serviceClient =newRPCServiceClient();Optionsoptions= serviceClient.getOptions();        EndpointReference targetEPR =newEndpointReference("http://192.168.0.105:8080/Axis2Demo_war_exploded/services/HelloService");options.setTo(targetEPR);        Object[] entryArgs =newObject[]{4,2};        QName qName =newQName("http://ws.apache.org/axis2","add");        Object result = serviceClient.invokeBlocking(qName, entryArgs,newClass[]{int.class})[0];        qName =newQName("http://ws.apache.org/axis2","send");        serviceClient.invokeRobust(qName,newObject[]{"hello world!"});    }}

Soap UI

Apache CXF

Apache CXF是一个开源的、全功能的,容易使用的Web服务框架。CXF是两个项目的结合:由IONA技术公司开发的Celtix和由Codehaus主持的团队开发的XFire。

CXF支持的特性非常广泛,但特性主要在以下一些方面:

支持的Web服务标准包括:

SOAP

WS-Addressing

WS-Policy

WS-ReliableMessaging

WS-Security

WS-SecurityPolicy

WS-SecureConversation

JAS-WS API,用于Web服务开发

WSDL优先支持工具

Java优先支持

JAX-RS(JSR 311 1.0)API,用于RESTful Web服务开发

:arrow_up:内容摘自Wiki百科。

发布服务

使用 Maven 构建项目,POM文件内容如下:

<?xml version="1.0"encoding="UTF-8"?>4.0.0org.exampleCXFDemo1.0-SNAPSHOTorg.apache.cxfcxf-rt-frontend-jaxws3.4.0org.apache.cxfcxf-rt-transports-http3.4.0org.apache.cxfcxf-rt-transports-http-jetty3.4.0org.apache.cxfcxf-rt-transports-http-jetty3.4.0

编写一个服务接口,定义 sayHi 方法:

packageorg.example.services;importjavax.jws.WebService;// 声明这是一个Ws服务接口@WebServicepublicinterfaceHelloWorld{// 定义服务方法StringsayHi(String name);}

编写一个服务接口的实现类:

packageorg.example.services;importjavax.jws.WebService;@WebService(endpointInterface ="org.example.services.HelloWorld", serviceName ="HelloWorld")publicclassHelloWorldImplimplementsHelloWorld{publicStringsayHi(String name){return"hi, "+ name;    }}

再编写一个发布服务的主类 Main :

importorg.apache.cxf.jaxws.JaxWsServerFactoryBean;importorg.example.services.HelloWorld;importorg.example.services.HelloWorldImpl;publicclassMain {publicstaticvoidmain(String[] args){        HelloWorldImpl implementor =newHelloWorldImpl();        JaxWsServerFactoryBean svrFactory =newJaxWsServerFactoryBean();        svrFactory.setServiceClass(HelloWorld.class);        svrFactory.setAddress("http://localhost:9000/helloworld");        svrFactory.setServiceBean(implementor);        svrFactory.create();    }}

运行后即可访问 http://localhost:9000/helloworld?wsdl 查看该服务,从WSDL的描述文件中也能看出 HelloWorld 服务提供了 sayHi 方法,且该方法需要一个字符串参数,返回值也为字符串。

使用 SoapUI 调用该方法示例:

通过代码也可以实现客户端调用 Web Service :

importorg.example.services.HelloWorld;importjavax.xml.namespace.QName;importjavax.xml.ws.Service;importjavax.xml.ws.soap.SOAPBinding;publicclassWsClient{privatestaticfinalQNameSERVICE_NAME= newQName("http://services.example.org/","HelloWorld");privatestaticfinalQNamePORT_NAME= newQName("http://services.example.org/","HelloWorldPort");publicstaticvoid main(String[] args) {Serviceservice =Service.create(SERVICE_NAME);StringendpointAddress ="http://localhost:9000/helloworld";        service.addPort(PORT_NAME,SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);HelloWorldhelloWorld = service.getPort(HelloWorld.class);System.out.println(helloWorld.sayHi("SearchNull"));    }}

Spring整合CXF

在Spring框架中可以集合 Apache CXF 框架发布 Web Service 服务,通过 Maven 或其他方式将CXF所需的Jar包导入项目中,编写 Web Service 接口及实现类即可。

packageorg.example.webservices;importjavax.jws.WebMethod;importjavax.jws.WebParam;importjavax.jws.WebResult;importjavax.jws.WebService;/** *@WebService注解标记一个webservice接口 * *@paramtargetNamespace    指定命名空间,默认使用包名的反转. *@paramserviceName    对外发布的服务名称 *@paramportName    wsdl:portName,默认为服务名 + Port*/@WebService(    targetNamespace ="http://services.example.org/",    serviceName ="HelloService",    portName ="HelloServicePort")publicinterfaceIHelloService{/**    *@WebResult注解指定从返回值至WSDL或XML元素的映射,将此注解应用于客户端或服务端接口(SEI)方法之上。    *    *@paramname    当返回值列示在 WSDL 文件中并且在连接上的消息中找到该返回值时,指定该返回值的名称。对于 RPC 绑定,这是用于表示返回值的    *@paramtargetNamespace    指定返回值的 XML 命名空间。仅当操作类型为 RPC 或者操作是文档类型并且参数类型为 BARE 时才使用此参数。(字符串)    *    *@WebMethod注解表示作为 Web Service 的方法,将此注解应用于服务端接口(SEI)的方法上。    *    *@paramoperationName    指定与此方法相匹配的 wsdl:operation 的名称,默认值为Java方法的名称    *    *@WebParam注解用于指定方法参数即Web Service方法的消息部件和XML元素的映射    *@paramname    参数的名称,如果操作是RPC(远程过程调用)类型并且未指定portName属性,则表示参数的wsdl:port属性的名称    */@WebResult(name ="helloRequest", targetNamespace ="http://services.example.org/")@WebMethod(operationName="sayHello")publicString hello(@WebParam(name ="msg")String name);}

Web Service 接口的实现类

packageorg.example.webservices.impl;importjavax.jws.WebService;importjavax.jws.soap.SOAPBinding;importjavax.jws.soap.SOAPBinding.Style;importorg.springframework.stereotype.Service;importorg.exmaple.webservices.IHelloService;@WebService(    endpointInterface ="org.example.services.IHelloService")@SOAPBinding(style=Style.RPC)public class IHelloServiceImpl implements IHelloService {    @Overridepublic String hello(String name) {return"Hello, " +name;    }}

实现 Web Service 的服务端后则需要对Spring项目整合CXF的一些配置,在 web.xml 中配置CXF框架路由。

cxforg.apache.cxf.transport.servlet.CXFServlet1cxf/services/*

在Spring配置(eg: application.xml)文件中加入以下配置项:

最后启动项目访问 http://localhost:8080/services?wsdl 即可查看发布的服务。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,014评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,832评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 171,062评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,620评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,636评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,148评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,522评论 3 427
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,501评论 0 278
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,032评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,069评论 3 344
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,211评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,848评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,541评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,013评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,136评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,712评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,240评论 2 363

推荐阅读更多精彩内容