zoukankan      html  css  js  c++  java
  • 信步漫谈之Axis2—基础介绍

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

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

    axis2版本:axis2-1.5.4-bin.zip

    目录结构:

    image

    关键代码:

    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,打印信息:

    image

    需要注意的一点就是 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 是否将证书加入系统属性。

    最后,项目的结构如下:

    image

  • 相关阅读:
    Yet Another Monster Killing Problem
    Element Extermination
    最短路径
    Secret Passwords
    New Year Parties
    Water The Garden
    Zero Quantity Maximization
    Anya and Cubes
    代码规范&《数学之美》读后感
    带负边权的最短路径(有向图)——Bellman-Ford算法
  • 原文地址:https://www.cnblogs.com/alfredinchange/p/5389657.html
Copyright © 2011-2022 走看看