WebService的services.xml问题

WebService有多种实现方式,这里使用的是axis2

问题:

在本地开发,访问本地的http://localhost:8080/services/ims?wsdl,正常访问

但是打成jar包,不管是linux还是window启动,都访问不到,报错信息如下

java 复制代码
2023-12-28 09:56:20.749 [http-nio-8092-exec-1] WARN  o.a.axiom.util.stax.dialect.StAXDialectDetector[214] - Unable to determine dialect of the StAX implementation at jar:file:/opt/testWebservice.jar!/BOOT-INF/lib/woodstox-core-6.4.0.jar!/
2023-12-28 09:56:21.110 [http-nio-8092-exec-1] ERROR o.apache.axis2.deployment.WarBasedAxisConfigurator[254] - org.apache.axis2.deployment.DeploymentException: The system cannot locate the specified repository location: file:/opt/testWebservice.jar!/BOOT-INF/classes!/WEB-INF: loading repository from classpath
org.apache.axis2.deployment.DeploymentException: The system cannot locate the specified repository location: file:/opt/testWebservice.jar!/BOOT-INF/classes!/WEB-INF
	at org.apache.axis2.deployment.DeploymentEngine.loadRepository(DeploymentEngine.java:146)
	at org.apache.axis2.deployment.WarBasedAxisConfigurator.getAxisConfiguration(WarBasedAxisConfigurator.java:205)
	at org.apache.axis2.context.ConfigurationContextFactory.createConfigurationContext(ConfigurationContextFactory.java:64)
	at org.apache.axis2.transport.http.AxisServlet.initConfigContext(AxisServlet.java:622)
	at org.apache.axis2.transport.http.AxisServlet.init(AxisServlet.java:471)
	at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1106)
	at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:763)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:115)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1790)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
2023-12-28 09:56:21.160 [http-nio-8092-exec-1] INFO  org.apache.axis2.transport.http.AxisServlet[115] - java.lang.NullPointerException
2023-12-28 09:56:21.161 [http-nio-8092-exec-1] ERROR o.a.c.c.C.[Tomcat].[localhost].[/].[axisServlet][175] - Allocate exception for servlet [axisServlet]
java.lang.NullPointerException: null
	at org.apache.axis2.deployment.DeploymentEngine.loadServices(DeploymentEngine.java:136)
	at org.apache.axis2.deployment.WarBasedAxisConfigurator.loadServices(WarBasedAxisConfigurator.java:275)
	at org.apache.axis2.context.ConfigurationContextFactory.createConfigurationContext(ConfigurationContextFactory.java:95)
	at org.apache.axis2.transport.http.AxisServlet.initConfigContext(AxisServlet.java:622)
	at org.apache.axis2.transport.http.AxisServlet.init(AxisServlet.java:471)
	at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1106)
	at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:763)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:115)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1790)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

原因

axis2默认加载的是项目中的WEB-INF/services/conf/META-INF/services.xml,打包以后默认加载的就是jar中的WEB-INF/services/conf/META-INF/services.xml,但是打包后,又不能读取到services.xml,所以报错了

解决

通过IO流,将services.xml保存到本地,然后指定要加载的路径为本地的这个services.xml

java 复制代码
import com.tmkj.tcp.FileCopyUtils;
import org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder;
import org.apache.axis2.transport.http.AxisServlet;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ClassUtils;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;

@Configuration
public class AxisWebserviceConfig {

    private final static Logger log = LoggerFactory.getLogger(AxisWebserviceConfig.class);

    /*@Bean
    public ServletRegistrationBean<AxisServlet> axisServlet() throws Exception {
        ServletRegistrationBean<AxisServlet> registrationBean = new ServletRegistrationBean<>();
        registrationBean.setServlet(new AxisServlet());

        //将 AxisServlet 映射到 /services/* 的URL路径上,所有请求路径以 /services/* 开头的请求将由 AxisServlet 处理
        registrationBean.addUrlMappings("/services/*");
        // InputStream 对象用于从类路径中读取 services.xml 文件
        InputStream in= ClassUtils.getDefaultClassLoader().getResourceAsStream("WEB-INF/services/conf/META-INF/services.xml");
        //获取应用程序的当前工作目录,就是当前项目或者jar所在的目录
        String root = System.getProperty("user.dir");
        //设置本地存储的services.xml的路径
        String path=root+"/WEB-INF/services/conf/META-INF/services.xml";
        //将前面InputStream的流文件保存到本地指定的路径
        FileUtils.copyInputStreamToFile(in,new File(path));

        log.info("xml配置文件path={}","{"+root+"/WEB-INF"+"}");

        //向 AxisServlet 添加一个初始化参数。初始化参数的名称是 axis2.repository.path ,它的值是 services.xml 文件的路径,这个 root+"/WEB-INF" 已经是我们指定的本地的services.xml路径了,如果不指定,默认加载的就是项目中的WEB-INF/services/conf/META-INF/services.xml,打包以后默认加载的就是jar中的WEB-INF/services/conf/META-INF/services.xml
        registrationBean.addInitParameter("axis2.repository.path", root+"/WEB-INF");
        //设置 AxisServlet 的加载顺序。加载顺序为1,应用程序启动时将加载 AxisServlet
        registrationBean.setLoadOnStartup(1);
        return registrationBean;
    }*/

    @Bean
    public ServletRegistrationBean<AxisServlet> axisServlet(){
        ServletRegistrationBean<AxisServlet> registrationBean = new ServletRegistrationBean<>();
        registrationBean.setServlet(new AxisServlet());
        //将 AxisServlet 映射到 /services/* 的URL路径上,所有请求路径以 /services/* 开头的请求将由 AxisServlet 处理
        registrationBean.addUrlMappings("/services/*");

        /**
         * 在项目中:获取当前程序编译后截止/WEB-INF路径,这个WEB-INF在resources目录下,最后结果就是E:/test/target/classes/WEB-INF
         * 在jar包中:结果是:file:/opt/yunwang/evn.jar!/BOOT-INF/lib/woodstox-core-6.4.0.jar!/
         */
        
        String path = this.getClass().getResource("/WEB-INF").getPath().toString();
        //在jar中的话,把file:截取掉
        if(path.toLowerCase().startsWith("file:")){
            path = path.substring(5);
        }
        //如果是jar中,路径中会有!
        if(path.indexOf("!") != -1){
            try{
                //复制classpath下的文件到jar包的同级目录下
                FileCopyUtils.copy("WEB-INF/services/conf/META-INF/services.xml");
            }catch (Exception e){
                e.printStackTrace();
            }
            path = path.substring(0, path.lastIndexOf("/", path.indexOf("!"))) + "/WEB-INF";
        }
        log.info("xml配置文件path={}","{"+path+"}");

        //向 AxisServlet 添加一个初始化参数。初始化参数的名称是 axis2.repository.path ,它的值是 services.xml 文件的路径,这个 root+"/WEB-INF" 已经是我们指定的本地的services.xml路径了,如果不指定,默认加载的就是项目中的WEB-INF/services/conf/META-INF/services.xml,打包以后默认加载的就是jar中的WEB-INF/services/conf/META-INF/services.xml
        registrationBean.addInitParameter("axis2.repository.path", path);
        registrationBean.setLoadOnStartup(1);
        return registrationBean;
    }
/*    @Bean
    public ApplicationContextHolder getApplicationContextHolder(){
        return new  ApplicationContextHolder();
    }*/
}

以上两个axisServlet方法,都是一样的,将jar中的文件通过流放在本地,放开一个就行,第一个直接用,第二个是用了一个工具类,以下是工具类

java 复制代码
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 将jar内的文件复制到jar包外的同级目录下
 */
public class FileCopyUtils {
    private static final Logger log = LoggerFactory.getLogger(FileCopyUtils.class);

    private static InputStream getResource(String location) throws IOException {
        InputStream in = null;
        try {
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            in = resolver.getResource(location).getInputStream();
            byte[] byteArray = IOUtils.toByteArray(in);
            return new ByteArrayInputStream(byteArray);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("getResource is error: {}", e);
            return null;
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }

    /**
     * 获取项目所在文件夹的绝对路径
     *
     * @return
     */
    private static String getCurrentDirPath() {
        URL url = FileCopyUtils.class.getProtectionDomain().getCodeSource().getLocation();
        String path = url.getPath();
        if (path.startsWith("file:")) {
            path = path.replace("file:", "");
        }
        if (path.contains(".jar!/")) {
            path = path.substring(0, path.indexOf(".jar!/") + 4);
        }

        File file = new File(path);
        path = file.getParentFile().getAbsolutePath();
        return path;
    }

    private static Path getDistFile(String path) throws IOException {
        String currentRealPath = getCurrentDirPath();
        Path dist = Paths.get(currentRealPath + File.separator + path);
        Path parent = dist.getParent();
        if (parent != null) {
            Files.createDirectories(parent);
        }
        Files.deleteIfExists(dist);
        return dist;
    }

    /**
     * 复制classpath下的文件到jar包的同级目录下
     *
     * @param location 相对路径文件,例如kafka/kafka_client_jaas.conf
     * @return
     * @throws IOException
     */
    public static String copy(String location) throws IOException {
        InputStream in = getResource("classpath:" + location);
        Path dist = getDistFile(location);
        Files.copy(in, dist);
        in.close();
        return dist.toAbsolutePath().toString();
    }

}
相关推荐
gc_22992 个月前
测试ASP.NET Core的WebApi项目调用WebService
webapi·vs2022·webservice
埃和智能4 个月前
PLC通过IGT-SER系列智能网关快速实现WebService接口调用案例
http·三菱plc·post·webservice·西门子plc·web服务接口·平台对接
bigbearxyz4 个月前
Java客户端调用SOAP方式的WebService服务实现方式分析
java·webservice·soap
梁萌7 个月前
Java调用WebServices接口
java·接口·webservice·soapui
Hi~晴天大圣8 个月前
jmeter实现webservice接口测试
jmeter·webservice
流华追梦11 年前
C# 面试题大全
面试·c#·.net·webservice·dataset
辛丑年正月十五1 年前
使用CXF调用WSDL(二)
webservice·cxf·org.apache.cxf·cxf调用webservice·cxf解析wsdl
杰夫贾维斯1 年前
使用命令wsdl2java
webservice
FromCyun1 年前
C# .Net6 指定WSDL, 生成Webservice,调用该接口服务
c#·.net·webservice·wsdl·.net6