主要介绍如何使用 axis2 开发 webservice 接口。

以下以实例讲解如何编写一个 axis2 的服务端和客户端。

axis2版本:axis2-1.5.4-bin.zip

目录结构:

关键代码:

package com.alfred.check;

import java.util.Iterator;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext; public class AccessCheck {
public static void checkUserPwd() throws AxisFault {
MessageContext msgContext = MessageContext.getCurrentMessageContext();
// 获取Head
Iterator list = (Iterator) msgContext.getEnvelope().getHeader()
.getFirstElement().getChildren();
String username = "";
String password = "";
while (list.hasNext()) {
OMElement element = (OMElement) list.next();
if (element.getLocalName().equals("username")) {
username = element.getText();
}
if (element.getLocalName().equals("password")) {
password = element.getText();
}
}
if (!username.equals("admin") || !password.equals("123456")) {
throw new AxisFault(
" Authentication Fail! Check username/password ");
}
}
}

AccessCheck.java

package com.alfred.service;

import org.apache.axis2.AxisFault;

import com.alfred.check.AccessCheck;

public class SoapService {
public String sayHello(String name) throws AxisFault {
// 以下是添加axis2访问头部验证
// AccessCheck.checkUserPwd();
return "Hello," + name;
} public String getWorld() {
return "Hello,World";
}
}

SoapService.java

package com.alfred.client;

import javax.xml.namespace.QName;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient; import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace; public class ServiceClient {
public static void main(String args[]) throws AxisFault {
sendAxis2();
} /**
* 添加Header头部验证信息
*
* @return
*/
public static OMElement createHeaderOMElement() {
OMFactory factory = OMAbstractFactory.getOMFactory();
OMNamespace SecurityElementNamespace = factory.createOMNamespace(
"http://handler.com", "wsse");
OMElement authenticationOM = factory.createOMElement("Authentication",
SecurityElementNamespace);
OMElement usernameOM = factory.createOMElement("username",
SecurityElementNamespace);
OMElement passwordOM = factory.createOMElement("password",
SecurityElementNamespace);
usernameOM.setText("admin");
passwordOM.setText("123456");
authenticationOM.addChild(usernameOM);
authenticationOM.addChild(passwordOM);
return authenticationOM;
} /**
* 发送axis2的接口信息
* @throws AxisFault
*/
private static void sendAxis2() throws AxisFault {
// 使用RPC方式调用WebService
RPCServiceClient serviceClient = new RPCServiceClient(); // 向Soap Header中添加校验信息
serviceClient.addHeader(createHeaderOMElement()); Options options = serviceClient.getOptions();
// 指定调用WebService的URL
EndpointReference targetEPR = new EndpointReference(
"http://127.0.0.1:8080/aw/services/mySoapService");
options.setTo(targetEPR);
// 指定sayHello方法的参数值,如果有多个,继续往后面增加即可
Object[] opAddEntryArgs = new Object[] { "alfred" };
// 指定sayHello方法返回值的数据类型的Class对象
Class[] classes = new Class[] { String.class };
// 在创建QName对象时,QName类的构造方法的第一个参数表示WSDL,文件的命名空间名,也就是<wsdl:definitions>元素的targetNamespace属性值
// 第二个参数是要调用的方法名
QName opAddEntry = new QName("http://service.alfred.com", "sayHello");
// 返回参数类型,这个和axis1有点区别
// invokeBlocking方法有三个参数:
// 第一个参数的类型是QName对象,表示要调用的方法名;
// 第二个参数表示要调用的WebService方法的参数值,参数类型为Object[];
// 第三个参数表示WebService方法的返回值类型的Class对象,参数类型为Class[];
// 当方法没有参数时,invokeBlocking方法的第二个参数值不能是null,而要使用new Object[]{}
// 如果被调用的WebService方法没有返回值,应使用RPCServiceClient类的invokeRobust方法,
// 该方法只有两个参数,它们的含义与invokeBlocking方法的前两个参数的含义相同
Object ret = serviceClient.invokeBlocking(opAddEntry, opAddEntryArgs,
classes)[0];
System.out.println(ret);
} }

ServiceClient.java

<?xml version="1.0" encoding="UTF-8"?>
<serviceGroup>
<!-- 可以指定发布多个service -->
<service name="mySoapService">
<description>
axis2 example
</description>
<!-- 指定接口类地址 -->
<parameter name="ServiceClass">
com.alfred.service.SoapService
</parameter>
<!-- Operation级消息接收器:可以为不同的操作指定不同的消息接收器
<operation name="sayHello">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</operation>
<operation name="getWorld">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</operation>
-->
<!-- 服务级消息接收器 -->
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
</messageReceivers>
</service>
</serviceGroup>

services.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!--Axis2 config start-->
<display-name>Apache-Axis2</display-name>
<servlet>
<servlet-name>AxisServlet</servlet-name>
<servlet-class>org.apache.axis2.transport.http.AxisServlet</servlet-class>
<!--<init-param>-->
<!--<param-name>axis2.xml.path</param-name>-->
<!--<param-value>/WEB-INF/conf/axis2.xml</param-value>-->
<!--<param-name>axis2.xml.url</param-name>-->
<!--<param-value>http://localhost/myrepo/axis2.xml</param-value>-->
<!--<param-name>axis2.repository.path</param-name>-->
<!--<param-value>/WEB-INF</param-value>-->
<!--<param-name>axis2.repository.url</param-name>-->
<!--<param-value>http://localhost/myrepo</param-value>-->
<!--</init-param>-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>AxisAdminServlet</servlet-name>
<servlet-class>
org.apache.axis2.webapp.AxisAdminServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/servlet/AxisServlet</url-pattern>
</servlet-mapping> <servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping> <servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>*.jws</url-pattern>
</servlet-mapping>
<!--Axis2 end--> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

web.xml

在浏览器地址栏输入地址:http://127.0.0.1:8080/aw/services/mySoapService?wsdl(使用tomcat服务器,项目名为aw),可以看到显示出 webservice 的 wsdl 信息,说明部署成功。

在 ServiceClient 中,调用 sayHello,打印信息:

需要注意的一点就是 services.xml 文件的存放位置是固定的:WEB-INF/services/ 任意名字的文件夹 /META-INF/services.xml

Axis2 访问验证

axis2 接口可以通过向信息头部(Header)中添加验证信息,对接口调用者的身份进行验证。具体配置步骤是:

1、服务端在想要进行访问验证的接口方法中(sayHello),添加验证模块(AccessCheck.checkUserPwd());

2、验证模块通过获取 webservice 访问信息头部,提取验证信息,对客户端传递的验证信息进行进行检查判断;

3、客户端调用接口时,加入访问验证信息;

// 向Soap Header中添加校验信息
serviceClient.addHeader(createHeaderOMElement());

Axis2 的 https 访问

axis2 如果需要进行 https 访问,需要加入全局配置文件 axis2.xml (Axis2 下提供了三种配置文件,第一种是整个系统的全局配置 axis2.xml,第二种是服务配置 services.xml,第三种是模块配置 module.xml),默认该文件是存储在 /WEB-INF/conf/axis2.xml。axis2.xml 文件可以在 axis2 的开发包下获取。

在 axis2.xml 中加入一段:

<transportReceiver name="https" class="org.apache.axis2.transport.http.AxisServletListener">
<parameter name="port">443</parameter>
</transportReceiver>

配置完成后访问 https://127.0.0.1/aw/services/mySoapService?wsdl 显示出 webservice 的 wsdl 信息,说明配置成功。

客户端如果想要访问 https 的服务端,需将服务端证书加入系统属性中

//指定服务端证书
System.setProperty("javax.net.ssl.keyStore",ProjConf.SERVER_KEYSTORE);
System.setProperty("javax.net.ssl.keyStorePassword",ProjConf.SERVER_KEYSTORE_PASSWORD); System.setProperty("javax.net.ssl.trustStore",ProjConf.SERVER_TRUSTSTORE);
System.setProperty("javax.net.ssl.trustStorePassword",ProjConf.SERVER_TRUSTSTORE_PASSWORD);

如果想要手动指定 axis2.xml 文件路径(例如改为 config 文件夹下),可以在 web.xml 中配置(见上方 web.xml)

<init-param>
<param-name>axis2.xml.path</param-name>
<param-value>/WEB-INF/config/axis2.xml</param-value>
</init-param>

常见错误

1、javax.servlet.ServletException: org.apache.axis2.AxisFault: The system is attempting to engage a module that is not available: addressing

解决方法:到 axis2.xml 中查找

<!-- Comment this to disable Addressing -->
<module ref="addressing"/>

将 addressing 的引用注释掉。

2、https is forbidden

解决方法:核实 axis2.xml 文件位置是否正确,默认是在 WEB-INF/conf/axis2.xml,以及 axis2.xml 中是否配置了 https。

3、unable to find valid certification path to requested target

解决方法:核实客户端访问 https 是否将证书加入系统属性。

最后,项目的结构如下:

最新文章

  1. HTML 5 胜出:XHTML2 宣告夭折
  2. 一个奇葩的SQL
  3. 《Continuous Delivery》 Notes 1: The problem of delivering software
  4. Python基础第二篇
  5. ajax get和post请求 后端接收并返回数据
  6. ruby sass Encoding::CompatibilityError for changes
  7. __m128i的理解[转]
  8. Spinnerd的功能和用法
  9. Leetcode: Sliding Window Median
  10. 关于win10环境下Anaconda python,用pip安装包及升级时SSL报错的问题
  11. NetSec2019 20165327 Exp2 后门原理与实践
  12. 我们来说一说TCP神奇的40ms
  13. Notepad++的一个用法 转换为unix 格式的文件
  14. django-simple-captcha 组件使用
  15. Java Web之Http协议
  16. [C++]PAT乙级1012.数字分类 (20/20)
  17. LeetCode--No.001 Two Sum
  18. JS 中函数名后面加与不加括号的区别
  19. 关于three.js中添加文字的方式[转]
  20. nargout 【转】

热门文章

  1. Linux下安装jdk1.7
  2. vue-router利用url传递参数
  3. windows版mysql5.7.18安装
  4. mysql 5.7配置项最详细的解释
  5. Redis入门到高可用(十二)—— pipeline
  6. SLAM最近的工作
  7. 进程间通信IPC机制和生产者消费者模型
  8. 玩nginx部署不同的web app
  9. react 嵌套组件的通信
  10. FlexViewer之整体框架解析