SpringBoot 与 Axis2 集成

SpringBoot2 集成 Axis2

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
SpringBoot2 与 axis2 集成,采用 axis2-spring 包实现服务的注册,包括服务端和客户端。具体版本 SpringBoot 2.7.16,Axis2 1.7.9。


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

在已有的 SpringBoot 工程里添加 Axis2的包,提供 WebService 的服务,服务端结合 spring 并提供两种客户端的调用方式,一种是方案标准的拼 OMElement 方式;一种是通过纯 xml 字符串转 OMElement 的方式,各有各的使用场景。

需要对 springboot, servlet 有些了解。


提示:以下是本篇文章正文内容,下面案例可供参考

一、添加依赖 pom.xml

添加axis2的依赖包

1. 指定 axis2 的版本及 jar 包


<properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <dubbo.version>3.2.6</dubbo.version>
    <spring-boot.version>2.7.16</spring-boot.version>
    <!-- mac 需要指定 classifier -->
    <os.detected.classifier>osx-x86_64</os.detected.classifier>
    <!-- axis2的版本 -->
    <axis2.version>1.7.9</axis2.version>
</properties>


<!-- axis -->
<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-adb</artifactId>
    <version>${axis2.version}</version>
    <!-- 在 Spring mvc 已经依赖了 servlet 包,这里需要排除 -->
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-spring</artifactId>
    <version>${axis2.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-jaxws</artifactId>
    <version>${axis2.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-xmlbeans</artifactId>
    <version>${axis2.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.ws.commons.axiom</groupId>
    <artifactId>axiom-api</artifactId>
    <version>1.2.22</version>
</dependency>
<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-transport-http</artifactId>
    <version>${axis2.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-transport-local</artifactId>
    <version>${axis2.version}</version>
</dependency>

<!-- axis2 services/listServices jsp -->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>

二、服务端代码

1.接口及实现类

接口类 HelloService:

public interface HelloService {
    public String hello(String name);
}

实现类 HelloServiceImpl:

import com.example.dubbo.grpc.manage.ws.services.HelloService;
import org.springframework.stereotype.Service;

/**
 * 简单实现示例
 */

// helloService 必须与 services.xml 里定义的 SpringBeanName 一致
@Service("helloService")
public class HelloServiceImpl implements HelloService {
    @Override
    public String hello(String name) {
        return "Hello " + name;
    }
}

2.注入 Axis 的 Servlet

Axis 的服务端是通过 Servlet 提供服务的,SpringBoot 提供了注入 Bean 的方式注入 Servlet,源代码如下:

import lombok.extern.log4j.Log4j;
import org.apache.axis2.transport.http.AxisServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Objects;

@Configuration
@Log4j
public class Axis2WebServiceConfiguration {

    /**
     * 注册 Axis 的Servlet,指定 url-mapping 为 /service
     * @return  ServletRegistrationBean
     */
    @Bean
    public ServletRegistrationBean<AxisServlet> axisServlet() {
        ServletRegistrationBean<AxisServlet> bean = new ServletRegistrationBean<>(new AxisServlet(), "/services/*");

        String path = Objects.requireNonNull(getClass().getResource("/WEB-INF")).getPath();

        log.info("axis2.repository.path:" + path);

        bean.addInitParameter("axis2.repository.path", path);
        bean.setLoadOnStartup(1);

        return bean;
    }
}

通过 /services/helloService?wsdl 访问时能进入该 servlet 。

三.Aixs2的约定配置

Axis2有自己约定的配置,主要是 目录结构 和 services.xml 文件,必须要按约定,否则会导致服务无法启动或启动后找不到服务。

1.目录结构

1.1 配置文件目录

  1. WEB-INF/conf/axis2.xml 这个文件启动时会有提示,但并不影响运行,找不到会有默认的。
  2. resources 是指 springboot 下的资源文件
resources
├── WEB-INF
│   ├── conf
│   │   └── axis2.xml
│   └── services
│       └── axis2
│           └── META-INF
│               └── services.xml
├── application.yml
├── log4j.properties

1.2 管理页面目录

有这些文件后访问 /services/listServices 会出现管理界面。

  1. 官网下载 http://archive.apache.org/dist/axis/axis2/java/core/1.7.9/axis2-1.7.9-src.zip,解压后把 modules/webapp/src/main/webapp 复制到工程里,复制后的目录结构如下图:
webapp
├── WEB-INF
│   ├── include
│   │   ├── LeftFrame.jsp
│   │   ├── adminfooter.inc
│   │   ├── adminfooter.jsp
│   │   ├── adminheader.jsp
│   │   ├── footer.inc
│   │   ├── header.inc
│   │   ├── httpbase.jsp
│   │   ├── link-footer.inc
│   │   └── link-footer.jsp
│   ├── tags
│   │   └── status.tag
│   └── views
│       ├── admin
│       │   ├── Login.jsp
│       │   ├── SelectService.jsp
│       │   ├── activateService.jsp
│       │   ├── admin.jsp
│       │   ├── deactivateService.jsp
│       │   ├── editServiceParameters.jsp
│       │   ├── engageGlobally.jsp
│       │   ├── engageToOperation.jsp
│       │   ├── engageToService.jsp
│       │   ├── engageToServiceGroup.jsp
│       │   ├── errorModule.jsp
│       │   ├── globalModules.jsp
│       │   ├── listModules.jsp
│       │   ├── listServiceGroups.jsp
│       │   ├── listServices.jsp
│       │   ├── listSingleService.jsp
│       │   ├── upload.jsp
│       │   ├── viewContexts.jsp
│       │   ├── viewGlobalChains.jsp
│       │   ├── viewOperationSpecificChains.jsp
│       │   ├── viewServiceContext.jsp
│       │   ├── viewServiceGroupContext.jsp
│       │   └── viewphases.jsp
│       ├── listFaultyService.jsp
│       └── listServices.jsp
└── axis2-web
    ├── Error
    │   ├── AuthError.html
    │   ├── GenError.html
    │   ├── error404.jsp
    │   └── error500.jsp
    ├── HappyAxis.jsp
    ├── MainFrame.jsp
    ├── css
    │   └── axis-style.css
    ├── error.jsp
    ├── images
    │   ├── asf-logo.gif
    │   ├── axis.gif
    │   ├── axis.jpg
    │   └── axis_l.jpg
    └── index.jsp

1.3 工程的完整目录

我这的工程里还有 dubbo,这个不影响,关注 axis2 相关的即可,工程目录结构如下图:
在这里插入图片描述

2 配置文件 services.xml

services.xml 的文件位置一定要正确,src/main/resources/WEB-INF/services/axis2/META-INF/services.xml,否则会找不到注册的服务

<?xml version="1.0" encoding="UTF-8"?>
<serviceGroup>
	<!-- 定义服务名 helloService -->
    <service name="helloService" scope="application">
        <description>Hello Service Demo</description>
        <messageReceivers>
            <messageReceiver mep="http://www.w3.org/ns/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
            <messageReceiver mep="http://www.w3.org/ns/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
        </messageReceivers>

        <!-- 指定 class 的方式同样可以使用
        <parameter name="ServiceClass">com.example.manage.ws.services.impl.HelloServiceImpl</parameter>
        -->

        <!-- 需要在 HelloServiceImpl 添加注解 @Service("helloService") -->
        <parameter name="SpringBeanName">helloService</parameter>
        <parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier</parameter>

    </service>
</serviceGroup>

四.启动 WebService 服务

和正常的 SpringBoot的启动方式一致

SpringBoot启动类

Spring Boot的启动类如下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Axis2Application {

    public static void main(String[] args) {
        SpringApplication.run(Axis2Application.class, args);
    }

}

SpringBoot启动日志

1. 启动成功的日志如下图

在这里插入图片描述

2. 访问 http://127.0.0.1:8080/services/listServices 如下图:

在这里插入图片描述

3. 访问 http://127.0.0.1:8080/services/helloService?wsdl 如下图:

在这里插入图片描述

五.客户端实现

提供两个客户端类,一个参考官方标准,一个通过 xml 的纯字符串。

客户端-标准玩法

import lombok.extern.log4j.Log4j;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;

/**
 * 通过拼 Dom 实现服务调用,官方推荐的标准玩法
 * 发出的报文如下:
 * <code><?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body><hello xmlns="http://impl.services.ws.manage.grpc.dubbo.example.com"><arg0>world</arg0></hello></soapenv:Body></soapenv:Envelope></code>
 */
@Log4j
public class Axis2StandardClient {

    /**
     * 服务端调用地址,最后面的 "?wsdl" 有没有都可以
     */
    private static final String TARGET_URL = "http://127.0.0.1:8080/services/helloService?wsdl";

    /**
     * 服务调用
     * @param url   服务地址
     * @param targetNamespace   命名空间,可通过 wsdl 查看
     * @param method    方法名
     * @param args  方法入参
     * @return  返回报文
     * @throws AxisFault    标准异常
     */
    public static String invoke(String url, String targetNamespace, String method, Object... args) throws AxisFault {
        RPCServiceClient serviceClient = new RPCServiceClient();
        Options options = serviceClient.getOptions();

        EndpointReference targetEPR = new EndpointReference(url);
        options.setTimeOutInMilliSeconds(10*1000);
        options.setTo(targetEPR);

        OMElement methodElement = getMethodElement(targetNamespace, method, args);
        OMElement resElement = serviceClient.sendReceive(methodElement);
        return resElement.getFirstElement().toString();

        // 以下通过 QName 的方式调用,也是标准玩法之一
        /*QName qName = new QName(targetNamespace, method);
        Object[] params = new Object[]{"world"};
        Class<?>[] types = new Class[] {String.class};
        Object[] response = serviceClient.invokeBlocking(qName, params, types);
        return response[0].toString();*/
    }

    /**
     * 根据参数个数拼报文
     * @param targetNamespace   命名空间
     * @param method    方法名
     * @param args  方法入参
     * @return  OMElement 对象
     */
    private static OMElement getMethodElement(String targetNamespace, String method, Object[] args) {
        OMFactory factory = OMAbstractFactory.getOMFactory();
        OMNamespace omNamespace = factory.createOMNamespace(targetNamespace, "");
        OMElement methodElement = factory.createOMElement(method, omNamespace);

        for (int i = 0,len = args.length; i < len; i++) {
            OMElement element = factory.createOMElement("arg" + i, omNamespace);
            element.setText(String.valueOf(args[i]));
            methodElement.addChild(element);
        }

        methodElement.build();
        return methodElement;
    }


    public static void main(String[] args) throws Exception {
		// NameSpace 的地址可通过访问wsdl获取
		// impl.services.ws.manage.grpc.dubbo.example.com
		
        String response = invoke(TARGET_URL, "http://impl.services.ws.manage.grpc.dubbo.example.com", "hello", "world");
        log.debug("response:" + response);
    }
}

客户端-xml字符串玩法

import lombok.extern.log4j.Log4j;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;

/**
 * 简单暴力的 xml 字符串报文调用
 */
@Log4j
public class AxisSimpleStringClient {

    /**
     * 服务端调用地址,最后面的 "?wsdl" 有没有都可以
     */
    private static final String TARGET_URL = "http://127.0.0.1:8080/services/helloService?wsdl";

    /**
     * 通过模板拼 xml 报文,模板化程度需要根据使用情况调整,这里只是用来做为示例,仅控制了一个入参
     * @param param
     * @return SOAPEnvelope
     */
    private static SOAPEnvelope createMessage(String param) {
        // NameSpace 的地址可通过访问wsdl获取
		// impl.services.ws.manage.grpc.dubbo.example.com
		
        String xml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header/><soapenv:Body><hello xmlns=\"http://impl.services.ws.manage.grpc.dubbo.example.com\"><arg0>%s</arg0></hello></soapenv:Body></soapenv:Envelope>";

        String message = String.format(xml, param);

        // 关键是这段代码,能将 xml 字符串转换成 SOAPEnvelope 对象
        return OMXMLBuilderFactory.createSOAPModelBuilder(
                new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)),
                StandardCharsets.UTF_8.displayName()).getSOAPEnvelope();
    }

    public static void sendMessage() throws Exception {
        EndpointReference target = new EndpointReference(TARGET_URL);
        RPCServiceClient client = new RPCServiceClient();
        Options options = client.getOptions();
        options.setTimeOutInMilliSeconds(10*1000);
        options.setTo(target);

        SOAPEnvelope message = createMessage("world");

        // sendReceive 时不能直接使用 SOAPEnvelope 对象,否则会抛出以下异常
        // org.apache.axis2.AxisFault: Can not output XML declaration, after other output has already been done.
        OMElement request = message.getBody().getFirstElement();

        if (log.isDebugEnabled()) {
            log.debug(message.toString());
        }

        OMElement response = client.sendReceive(request);

        if (log.isDebugEnabled()) {
            log.debug(response.toString());
        }
    }

    public static void main(String[] args) throws Exception {
        sendMessage();
    }
}

总结

提示:这里对文章进行总结:

参考了一些同学的内容,或多或少有点不足,就自己整理了一个,比较完整,完整工程代码https://gitee.com/yifur/dubbo-grpc.git。

你好!要在Spring Boot集成Axis2,您可以按照以下步骤进行操作: 1. 添加Axis2依赖:在您的Spring Boot项目的pom.xml文件中,添加Axis2的依赖项。例如: ```xml <dependency> <groupId>org.apache.axis2</groupId> <artifactId>axis2</artifactId> <version>1.7.9</version> </dependency> ``` 2. 配置Axis2 Servlet:在您的Spring Boot项目中,创建一个类继承自`org.apache.axis2.transport.http.AxisServlet`,并使用`@WebServlet`注解将其标记为Servlet。例如: ```java import javax.servlet.annotation.WebServlet; import org.apache.axis2.transport.http.AxisServlet; @WebServlet(urlPatterns = "/services/*", loadOnStartup = 1) public class Axis2Servlet extends AxisServlet { // 可以保持默认实现 } ``` 3. 配置Axis2服务:在您的Spring Boot项目中创建一个类,用于配置Axis2服务。您可以通过使用`org.apache.axis2.deployment.ServiceDeployer`类进行配置。例如: ```java import org.apache.axis2.deployment.ServiceBuilder; import org.apache.axis2.deployment.ServiceDeployer; import org.apache.axis2.description.AxisService; import org.apache.axis2.engine.AxisConfiguration; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class Axis2Config { @Bean public ServletRegistrationBean<AxisServlet> axisServlet() { return new ServletRegistrationBean<>(new Axis2Servlet(), "/services/*"); } @Bean public ServiceDeployer serviceDeployer() { return new ServiceDeployer() { @Override public void deployServices(AxisConfiguration axisConfig) { // 在这里配置Axis2服务 AxisService service = new ServiceBuilder(axisConfig).populateService(getClass().getClassLoader() .getResourceAsStream("META-INF/axis2/services/YourService.xml")); axisConfig.addService(service); } }; } } ``` 在上面的示例中,您可以将`YourService.xml`替换为您的Axis2服务的配置文件。 4. 创建Axis2服务:创建您的Axis2服务的配置文件(`YourService.xml`),并将其放置在`src/main/resources/META-INF/axis2/services/`目录下。您可以在该配置文件中定义您的服务和操作。 5. 运行应用程序:现在,您可以启动Spring Boot应用程序,并访问`http://localhost:8080/services/`来访问您的Axis2服务。 请注意,上述步骤只提供了基本的集成方法。根据您的具体需求,您可能还需要进行其他配置和调整。希望对您有所帮助!如果您有任何问题,请随时提问。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值