Java开发或调用WebService的几种方式

这篇具有很好参考价值的文章主要介绍了Java开发或调用WebService的几种方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java开发或调用WebService的几种方式

一.JDK自带的 JAX-WS 方式开发WebService服务

1.服务端开发与发布

  1. 编写接口
@WebService
public interface JaxWsDemo {
    String helloJaxWS(String userName);
}
  1. 编写接口的实现类
@WebService
public class JaxWsDemoImpl implements JaxWsDemo {
    @WebMethod
    @WebResult(name = "jaxWSResult")
    @Override
    public String helloJaxWS(@WebParam(name = "userName")String userName) {
        return "hello," + userName + "This is a Web Service developed through JAX-WS";
    }
}
  1. 发布服务
public class JAXWSPublishMain {
    public static void main(String[] args) {
        String address = "http://127.0.0.1:8888/JaxWSTest";
        Endpoint.publish(address, new JaxWsDemoImpl());
        System.out.println("WebService 服务已发布!");
    }
}
  1. 访问已发布的WebService服务

打开浏览器输入http://127.0.0.1:8888/JaxWSTest?wsdl访问,如下面内容
Java开发或调用WebService的几种方式,WebService,java,开发语言

截图内容1

<!--
 Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. 
-->
<!--
 Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. 
-->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://wsimpl.jaxws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://wsimpl.jaxws/" name="JaxWsDemoImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://wsimpl.jaxws/" schemaLocation="http://127.0.0.1:8888/JaxWSTest?xsd=1"/>
</xsd:schema>
</types>
<message name="helloJaxWS">
<part name="parameters" element="tns:helloJaxWS"/>
</message>
<message name="helloJaxWSResponse">
<part name="parameters" element="tns:helloJaxWSResponse"/>
</message>
<portType name="JaxWsDemoImpl">
<operation name="helloJaxWS">
<input wsam:Action="http://wsimpl.jaxws/JaxWsDemoImpl/helloJaxWSRequest" message="tns:helloJaxWS"/>
<output wsam:Action="http://wsimpl.jaxws/JaxWsDemoImpl/helloJaxWSResponse" message="tns:helloJaxWSResponse"/>
</operation>
</portType>
<binding name="JaxWsDemoImplPortBinding" type="tns:JaxWsDemoImpl">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="helloJaxWS">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="JaxWsDemoImplService">
<port name="JaxWsDemoImplPort" binding="tns:JaxWsDemoImplPortBinding">
<soap:address location="http://127.0.0.1:8888/JaxWSTest"/>
</port>
</service>
</definitions>

浏览器中输入wsdl文档中的 http://127.0.0.1:8888/JaxWSTest?xsd=1可查看绑定的参数等信息看如下图:

Java开发或调用WebService的几种方式,WebService,java,开发语言

截图内容2

<!--
 Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. 
-->
<xs:schema xmlns:tns="http://wsimpl.jaxws/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://wsimpl.jaxws/">
<xs:element name="helloJaxWS" type="tns:helloJaxWS"/>
<xs:element name="helloJaxWSResponse" type="tns:helloJaxWSResponse"/>
<xs:complexType name="helloJaxWS">
<xs:sequence>
<xs:element name="userName" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="helloJaxWSResponse">
<xs:sequence>
<xs:element name="jaxWSResult" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
  1. jdk自带生成WebService的wsimport命令
-encoding : 指定编码格式

-keep:是否生成java源文件

-d:指定.class文件的输出目录

-s:指定.java文件的输出目录,   此目录必须存在

-p:定义生成类的包名,不定义的话有默认包名

-verbose:在控制台显示输出信息

-b:指定jaxws/jaxb绑定文件或额外的schemas

-extension:使用扩展来支持SOAP1.2
# 举例
wsimport -encoding utf-8 -keep -d D:\temp -p com.lawyer.user -verbose http://IP:port/serverName?wsdl 

2.客户端开发与测试

  1. 生成客户端源码

切换到要生成客户端源码的路径下,如下:

cd F:\SpringBootProjects\webServiceDemo\jwsDemo\src\main\java\demoOne\client>

根据wsdl文档地址生成源码信息:

F:\SpringBootProjects\webServiceDemo\jwsDemo\src\main\java\demoOne\client>
wsimport -d F:\SpringBootProjects\webServiceDemo\jwsDemo\src\main\java\demoOne\client
-keep -verbose http://127.0.0.1:8888/JaxWSTest?wsdl

参数说明:

wsimport : 导入命令,如果使用cxf就换成 wsdl2java  命令 
-d [源码位置]      : 指定要生成的源码的目录,不指定则默认在哪个目录打开的cmd窗口,就生在那个目录下
-keep : 是否生成*.java的源文件,写了此参数则直接生成*.java与*.class文件,不写此参数则只有*.class文件 
-verbose : 显示文件生成过程中的详细信息
-p [包名]: 指定要生成在哪个包下,不指定生成时取默认
  1. 客户端代码生成后测试
package demoOne.client;

import demoone.JaxWsDemoImplService;

/**
 * Created by IntelliJ IDEA.
 * User: jinshengyuan
 * Date: 2019-03-13
 * Time: 10:34
 * description: 客户端测试
 **/
public class ClientTest {
    public static void main(String[] args) {
        demoone.JaxWsDemoImplService implService = new JaxWsDemoImplService();
       demoone.JaxWsDemoImpl jaxWsDemo = (demoone.JaxWsDemoImpl)implService.getJaxWsDemoImplPort();
       String aa = jaxWsDemo.helloJaxWS("Tom ");
        System.out.println("调用WebService执行结果:"+aa);
    }
}

执行结果:

调用WebService执行结果:hello,Tom This is a Web Service developed through JAX-WS

二.Axis1.4调用.Net返回值为DataSet类型的WebService接口

1.相关说明

  1. JDK版本:1.8.0_172
  2. axis版本:Axis1.4

2. Axis1.4客户端WebService服务

1.Axis1.4下载

  1. 官网:http://axis.apache.org/axis/
  2. 下载后是一个压缩文件:axis-bin_1.4.zip
  3. 非maven环境,则导入axis-bin_1.4.zip包下的lib目录下的所有jar包,如下图:

Java开发或调用WebService的几种方式,WebService,java,开发语言

4.maven环境的话,在pom.xml中添加下面的依赖即可

<!--Axis1.4 及其依赖 begin-->
        <!-- https://mvnrepository.com/artifact/org.apache.axis/axis -->
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/jaxrpc/jaxrpc -->
        <!-- https://mvnrepository.com/artifact/axis/axis-jaxrpc -->
        <dependency>
            <groupId>axis</groupId>
            <artifactId>axis-jaxrpc</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/axis/axis-ant -->
        <dependency>
            <groupId>axis</groupId>
            <artifactId>axis-ant</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/axis/axis-saaj -->
        <dependency>
            <groupId>axis</groupId>
            <artifactId>axis-saaj</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/wsdl4j/wsdl4j -->
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.6.3</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-discovery/commons-discovery -->
        <dependency>
            <groupId>commons-discovery</groupId>
            <artifactId>commons-discovery</artifactId>
            <version>0.5</version>
        </dependency>
        <!--Axis1.4 及其依赖 end-->
		<!-- 引入dom4j 解析数据时用-->
 <!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
        <dependency>
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.1</version>
        </dependency>

2.WebService服务接口地址及方法

  1. 地址:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx
  2. 调用的方法:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportDataSet
    Java开发或调用WebService的几种方式,WebService,java,开发语言

3.编写调用WebService服务的方法及数据解析

  1. 编写调用WebService服务的客户端java类,并打印结果,类名为:Axis1_Client
package com.yuan;


import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.message.MessageElement;
import org.apache.axis.types.Schema;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.junit.Test;

import javax.xml.namespace.QName;
import java.net.URL;
import java.util.Iterator;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: jinshengyuan
 * Date: 2019-01-15
 * Time: 15:13
 * description:
 **/
public class Axis1_Client {
    /**
     * 使用dom4j解析数据
     */
    @Test
    public void axisWSInvoke(){
        String dataSetDataStr = axisInvokeNetDataSetData();
        //System.out.println(dataSetDataStr);
        if(dataSetDataStr != null){
            try {
                Document doc = DocumentHelper.parseText(dataSetDataStr);// 将字符串转为XML
                Element root = doc.getRootElement();// 获取根节点
                Iterator iterator =  root.elementIterator("Zone");//迭代节点
                String id,zone;
                while(iterator.hasNext()){
                  Element element = (Element) iterator.next();
                  id = element.elementTextTrim("ID");//取出Zone节点下的ID元素的值
                  zone = element.elementTextTrim("Zone");//取出Zone节点下的Zone元素的值
                    System.out.println("Id:"+id+"=============================Zone:"+zone);
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 调用.Net写的返回值为DataSet类型的WebService服务
     * @return
     */
    public String axisInvokeNetDataSetData(){
        Service service = new Service();
        String strXml = null;
        Call call = null;
        try {
            call = (Call) service.createCall();
            call.setTargetEndpointAddress(new URL("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx"));//WSURL,注意不要带?wsdl
            //调用方法方法前设置相关参数
            call.setOperationName(new QName("http://WebXml.com.cn/", "getSupportDataSet"));
            call.setReturnType(XMLType.XSD_SCHEMA);//返回类型,这里一定要传入 XMLType.XSD_SCHEMA 类型
            call.setUseSOAPAction(true);
            call.setSOAPActionURI("http://WebXml.com.cn/getSupportDataSet");//soapAction
            Object obj = call.invoke((Object[]) null);
            Schema schema = (Schema) obj;
            MessageElement[] messageElements = schema.get_any();
            List messageHead = messageElements[0].getChildren();//消息头,DataSet对象
            List messageBody = messageElements[1].getChildren();//消息体信息,DataSet对象,最终需要解析的数据
            if (messageBody.size() > 0) {
                String head = messageHead.get(0).toString();//消息头,DataSet对象
                String diffgr = messageBody.get(0).toString();//消息体的字符串形式
                strXml = diffgr;
                System.out.println("head:\n"+head);
                System.out.println("diffgr:\n" + diffgr);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return strXml;
    }
}
  1. 输出结果:
Id:1=============================Zone:直辖市
Id:2=============================Zone:特别行政区
Id:3=============================Zone:黑龙江
Id:4=============================Zone:吉林
Id:5=============================Zone:辽宁
Id:6=============================Zone:内蒙古
Id:7=============================Zone:河北
Id:8=============================Zone:河南
Id:9=============================Zone:山东
Id:10=============================Zone:山西
Id:11=============================Zone:江苏
Id:12=============================Zone:安徽
Id:13=============================Zone:陕西
Id:14=============================Zone:宁夏
Id:15=============================Zone:甘肃
Id:16=============================Zone:青海
Id:17=============================Zone:湖北
Id:18=============================Zone:湖南
Id:19=============================Zone:浙江
Id:20=============================Zone:江西
Id:21=============================Zone:福建
Id:22=============================Zone:贵州
Id:23=============================Zone:四川
Id:24=============================Zone:广东
Id:25=============================Zone:广西
Id:26=============================Zone:云南
Id:27=============================Zone:海南
Id:28=============================Zone:新疆
Id:29=============================Zone:西藏
Id:30=============================Zone:台湾
Id:31=============================Zone:亚洲
Id:32=============================Zone:欧洲
Id:33=============================Zone:非洲
Id:34=============================Zone:北美洲
Id:35=============================Zone:南美洲
Id:36=============================Zone:大洋洲

三. CXF 开发WebService接口

1. jax-ws实现

场景:CXF结合Spring实现发布与调用简单的WebService

  • 导入包
  1. pom.xml引入cxf的依赖即可
  • 开发java接口与实现类代码
  1. 编写接口
package com.ssm.webservice;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

/**
 * Created by IntelliJ IDEA.
 * User: jinshengyuan
 * Date: 2018-11-09
 * Time: 9:04
 * description:
 **/
@WebService
public interface Hello {
     @WebMethod
     @WebResult(name = "result") String sayHello(@WebParam(name = "name") String name);
}

  1. 编写接口的实现类
package com.ssm.webservice.impl;

import com.ssm.dao.sysManagement.ComLogMapper;
import com.ssm.model.ComLog;
import com.ssm.service.sysManagement.ComLogService;
import com.ssm.utils.CommonsUtil;
import com.ssm.webservice.Hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by IntelliJ IDEA.
 * User: jinshengyuan
 * Date: 2018-11-09
 * Time: 9:06
 * description:
 **/
public class HelloImpl implements Hello {

    //这里跟controller中调用Service一样,使用@Autowired注解自动注入service
    @Autowired
    ComLogService comLogService;
    @Override
    public String sayHello(String name) {
        //从数据库中获取当前系统日期
        Date date = comLogService.getCurrentDatetime();
        String currentDateTime = null;
        if(date != null){
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            currentDateTime = dateFormat.format(date);
            System.out.println("系统日期:"+currentDateTime);
        }

        return "hello," + name + ",当前时间为:"+currentDateTime;
    }
}

  • 与spring集成
  1. spring.xml文件中的核心配置
 <!-- 引入CXF配置文件,低版本(3.0以下)还需引入其他两个文件 -->
    <import resource="classpath:META-INF/cxf/cxf.xml" />

    <!-- 配置方式1   注意:serviceClass为接口类并非接口的实现类 -->
    <jaxws:server serviceClass="com.ssm.webservice.Hello" address="/webServiceTestA"></jaxws:server>
    <!--访问地址:http://localhost:8080/ssm/webService/webServiceTestA?wsdl-->

    <!-- 配置方式2    注意:implementor为接口的具体实现类,与springmvc整合时,推荐使用这种方式,如果使用配置方式1,则会在访问时,提示如下错误:
     org.apache.cxf.interceptor.Fault: Could not instantiate service class com.ssm.webservice.Hello because it is an interface.
     -->
    <jaxws:endpoint implementor="com.ssm.webservice.impl.HelloImpl" address="/webServiceTest"></jaxws:endpoint>
    <!--访问地址:http://localhost:8080/ssm/webService/webServiceTest?wsdl-->
  1. web.xml中的配置
 <!-- cxf服务启动servlet -->
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <!--工程名(ssm)后面紧跟的 url-->
        <url-pattern>/webService/*</url-pattern>
    </servlet-mapping>
  • 测试
  1. 打开浏览器,输入http://localhost:8080/ssm/webService/webServiceTest?wsdl进行测试

2. CXF-RESTFul服务实现

  • JAX-RS概述

JAX-RS是Java提供用于开发RESTful Web服务基于注解(annotation)的API。JAX-RS旨在定义一个统一的规范,使得Java程序员可以使用一套固定的接口来开发REST应用,避免了依赖第三方框架。同时JAX-RS使用POJO编程模型和基于注解的配置并集成JAXB,可以有效缩短REST应用的开发周期。JAX-RS只定义RESTful API,具体实现由第三方提供,如Jersey、Apache CXF等。

JAX-RS包含近五十多个接口、注解和抽象类:

  • javax.ws.rs包含用于创建RESTful服务资源的高层次(High-level)接 口和注解。
  • javax.ws.rs.core包含用于创建RESTful服务资源的低层次(Low-level)接口和注解。
  • javax.ws.rs.ext包含用于扩展JAX-RS API支持类型的APIs。

JAX-RS常用注解:文章来源地址https://www.toymoban.com/news/detail-796515.html

  • @Path:标注资源类或方法的相对路径。
  • @GET、@PUT、@POST、@DELETE:标注方法的HTTP请求类型。
  • @Produces:标注返回的MIME媒体类型。
  • @Consumes:标注可接受请求的MIME媒体类型。
  • @PathParam、@QueryParam、@HeaderParam、@CookieParam、@MatrixParam、@FormParam:标注方法的参数来自于HTTP请求的位置。@PathParam来自于URL的路径,@QueryParam来自于URL的查询参数,@HeaderParam来自于HTTP请求的头信息,@CookieParam来自于HTTP请求的Cookie。

到了这里,关于Java开发或调用WebService的几种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JAVA开发(通过Apollo注入配置信息的几种方式)

    在springCloud中有一个重要的组件就是配置中心,config:server,用于配置springboot中需要注入的各种配置项。但是现在发现越来越多的企业使用Apollo进行集成。博主在开发中也是使用Apollo进行配置。本文总结Apollo的的使用,集成到springboot,和注入方式等。   Apollo是携程框架部门研

    2024年02月09日
    浏览(42)
  • Java 调用 WebService 服务的 3 种方式

    虽然 WebService 这个框架已经过时,但是有些公司还在使用,在调用他们的服务的时候就不得不面对各种问题,本篇文章总结了最近我调用他司 WebService 的心路历程。3 种方式可以分别尝试,哪种能通用哪个。 soapui 下载地址:百度网盘、夸克网盘。 依赖: 代码: 注意:拼接

    2024年02月13日
    浏览(65)
  • Java 客户端调用 WebService 接口的一种方式

      通过SoapUI创建一个SOAP Project;   项目名称自定义,WSDL地址维护WebService接口地址。点击OK即可   项目创建完成后,展开WebService项,可以看到具体的接口,打开接口下的Request,右侧面板Form标签下可以清晰的看到请求入参,点击Submit请求按钮可以看到Overview标签下的响应结

    2024年01月18日
    浏览(32)
  • Java读取文件的几种方式

    1. 使用流读取文件 2. 使用JDK1.7提供的NIO读取文件(适用于小文件) 3. 使用JDK1.7提供的NIO读取文件(适用于大文件) 4. 使用JDK1.4提供的NIO读取文件(适用于超大文件) 5. 使用cmmons-io依赖提供的FileUtils工具类读取文件 添加依赖: 6. 使用cmmons-io依赖提供的IOtils工具类读取文件 添加依赖:

    2024年02月16日
    浏览(34)
  • java 读取文件的几种方式

    在 Java 中有几种常用的方式来读取文件: 使用 FileInputStream 类以字节的方式读取文件。 使用 BufferedReader 在字符输入流上包装一个缓冲区,以行为单位读取文件。 使用 Scanner 类以分隔符为标志读取文件。 使用 Files 类的 readAllLines 方法一次性读取所有行。 使用 ObjectInputStream 反

    2024年02月14日
    浏览(29)
  • java:解析json的几种方式

    Java是一种流行的编程语言,它提供了很多实用的库和工具,在处理JSON数据时也不例外。在本文中,我们将介绍Java中如何解析JSON数据。 JSON是一种轻量级的数据交换格式,它已经成为Web应用程序中最流行的数据格式之一。Java提供了许多库来处理JSON数据,包括Jackson、Gson和JS

    2024年02月03日
    浏览(36)
  • Java 终止线程的几种方式

    所谓正常运行结束,就是程序正常运行结束,线程自动结束。 一般run()方法执行完,线程就会正常结束,然而,常常有些线程是伺服线程。他们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设

    2024年02月07日
    浏览(28)
  • Java创建对象的几种方式

    在Java中,对象是程序中的一种基本元素,它通过类定义和创建。本篇教程旨在介绍Java中创建对象的几种方式,包括使用new、反射、clone、反序列化等方式。 在Java中,最常用的创建对象方式是使用new。使用new创建对象的具体步骤如下: 使用new并指定

    2024年02月12日
    浏览(25)
  • Java实现异步的几种方式

    普通线程实现异步,但频繁创建、销毁线程比较耗资源,所以一般交给线程池执行 结果: Future异步 和普通线程实现异步区别不大,只是使用Future是要获取执行后的返回值 结果: Spring的@Async异步 使用@Async注解实现异步的前提是需要在启动类上标注@EnableAsync来开启异步配置

    2024年02月04日
    浏览(43)
  • Java判断null的几种方式

    组内code review时,有同学提到字符串判断空值的写法,如下两种, (1)null在后, (2)null在前, 这两种写法,有什么区别? 这两个测试,都可以执行,有种解释是,null放在前面是为了避免少写一个\\\"=\\\",因为\\\"null=\\\"书写会报错,防止笔误写成\\\"=null\\\",不会报错,进而漏掉问题。

    2024年02月13日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包