springboot集成webservice soap

需求:最近公司要求对接客户端的一个webservice soap协议的接口,根据手机号查询到用户信息。之前只做过http、ws、sse协议的接口,故记下soap协议分享一下。

协议请求:

根据批量手机号查询实体(自有或合作伙伴)人员接口
请求报文:
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header>
        <msghead>
            <appId>88888900</appId>
            <appSecret>d6491592ad2a4832aa744caefae123</appSecret>
            <token>CE0000001532919192384c23af9d87f164df4a49bc48489ce4be</token>
            <reqTimestamp>1422343231</reqTimestamp>
            <functionId>queryEntUserByBatchPhone</functionId>
            <signature>fsere3</signature>
            <version>1.3.5</version>
        </msghead>
    </soap:Header>
    <soap:Body>
        <ns2:queryEntUserByBatchPhone
            xmlns:ns2="http://webservice.cfms.richinfo.cn/">
            <batchPhone>13802883264,15820712220,18825176420</batchPhone>
        </ns2:queryEntUserByBatchPhone>
    </soap:Body>
</soap:Envelope>

返回报文:
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns2:queryEntUserByBatchPhoneResponse
            xmlns:ns2="http://webservice.cfms.richinfo.cn/">
            <return>
                <code>0</code>
                <data>
                    <entUser>
                        <companyEmail>test@cmic.com</companyEmail>
                        <departMentId>3037</departMentId>
                        <departMentName>工程部(信息中心)</departMentName>
                        <email>123@139.com</email>
                        <empNo>11133</empNo>
                        <isValid>1</isValid>
                        <mobilePhone>13802</mobilePhone>
                        <orgFullName>有限公司\系统工程部(信息安全中心)</orgFullName>
                        <orgId>4909</orgId>
                        <orgName>信息技室</orgName>
                        <portalUserId>test</portalUserId>
                        <portalUserName>谢x欣</portalUserName>
                        <position>1</position>
                        <sex>1</sex>
                        <userCategory>1</userCategory>
                        <userId>125</userId>
                    </entUser>
                </data>
                <msg>根据批量手机号查询实体(自有或合作伙伴)人员信息成功</msg>
            </return>
        </ns2:queryEntUserByBatchPhoneResponse>
    </soap:Body>
</soap:Envelope>

一、为什么要用soap?使用http不行吗?

以下是soap和http的对比,简单来说就是soap协议更加严格定义了数据的传输格式,更适合银行支付、政府服务系统、健康医疗系统等。

对比维度SOAP(简单对象访问协议)HTTP 请求(基于 HTTP 协议)
本质定位数据交换协议(定义数据格式和交互规则)传输协议(定义数据在网络中的传输方式)
消息格式严格固定的 XML 格式(必须包含<Envelope>等标签)无强制格式,可传输 JSON、XML、表单、文本等
依赖关系依赖底层传输协议(常用 HTTP,也支持 SMTP、TCP 等)独立的传输协议,不依赖其他协议
数据格式约束有严格约束(基于 XML Schema 定义数据类型)无约束,开发者可自由定义数据格式
传输方式通常通过 HTTP POST 传输(消息作为 HTTP Body)支持多种方法(GET/POST/PUT/DELETE 等),按需选择
适用场景企业级复杂系统集成(如银行、ERP 对接,需事务 / 安全保障)轻量交互场景(如 App 接口、前后端分离、开放平台 API)
功能复杂度内置丰富功能(安全、事务、错误处理等规范)功能简单(仅基础传输能力,需自行实现额外功能)
错误处理通过<Fault>标签在 XML 中定义错误(统一格式)通过 HTTP 状态码(如 200/404/500)和自定义 Body 表示
性能较差(XML 冗余大,解析复杂)较好(尤其搭配 JSON 时,轻量且解析快)

二、springboot集成webservice soap

1、引入依赖配置

springboot版本
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>



相关的pom依赖
        <!-- Apache CXF Spring Boot Starter -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!-- JAXB Runtime implementation -->
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>4.0.2</version>
        </dependency>

        <!-- HTTP Client for SOAP calls -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>

2、服务端实现

模拟一个soap协议的服务接口:


import com.oak.springbootredis.service.UserService;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;

/**
 * webservice配置类
 */
@Configuration
public class CxfConfig {
    @Autowired
    private Bus bus;

    @Autowired
    private UserService userService;

    /**
     * 创建webservice服务
     * @return
     */
    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(bus, userService);
        endpoint.publish("/orgAndUserService");
        return endpoint;
    }
}
import com.oak.springbootredis.domain.resp.QueryUserResponse;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

/**
 * @author xyguo
 * @date 2025/7/15
 */
@WebService(targetNamespace = "http://webservice.cfms.richinfo.cn/")
public interface UserService {

    @WebMethod
    @WebResult(name = "return")
    QueryUserResponse queryEntUserByBatchPhone(@WebParam(name = "batchPhone") String batchPhone);
}    

import cn.hutool.core.collection.ListUtil;
import com.oak.springbootredis.domain.resp.EntUser;
import com.oak.springbootredis.domain.resp.QueryUserResponse;
import com.oak.springbootredis.domain.resp.ResponseData;
import com.oak.springbootredis.service.UserService;
import org.springframework.stereotype.Service;

import javax.jws.WebService;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@WebService(
        serviceName = "UserService",
        targetNamespace = "http://webservice.cfms.richinfo.cn/",
        endpointInterface = "com.oak.springbootredis.service.UserService"
)
public class UserServiceImpl implements UserService {

    /**
     * 模拟接口返回数据
     *
     * @param batchPhone
     * @return
     */
    @Override
    public QueryUserResponse queryEntUserByBatchPhone(String batchPhone) {
        QueryUserResponse response = new QueryUserResponse();
        response.setCode("0");
        response.setMsg("根据批量手机号查询实体(自有或合作伙伴)人员信息成功");
        if (response.getData()==null){
            response.setData(new ResponseData());
        }
        List<EntUser> usr = response.getData().getEntUser();
        List<EntUser> zusr = new ArrayList<>();
        // 解析手机号并查询
        String[] phones = {"17855954111"};
        ArrayList<String> reqPhones = ListUtil.toList(batchPhone.split(","));
        for (String phone : phones) {
            EntUser user =  createSampleUser(phone,"1");
            zusr.add(user);
        }
        EntUser user = createSampleUser("15211111133","3");
        zusr.add(user);
        EntUser user2 = createSampleUser("15212425222","3");
        zusr.add(user2);
        List<EntUser> removes = zusr.stream().filter(e -> reqPhones.contains(e.getMobilePhone())).collect(Collectors.toList());
        usr.addAll(removes);
        return response;
    }

    private EntUser createSampleUser(String phone, String isValid) {
        EntUser user = new EntUser();
        String randomId = String.valueOf((int)(Math.random() * 90000) + 10000);
        String[] names = {"张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"};
        String[] domains = {"cmic.chinamobile.com", "aspirecn.com", "139.com", "163.com"};
        String[] depts = {"系统工程部", "产品研发部", "市场营销部", "人力资源部", "财务部"};
        String randomName = names[(int)(Math.random() * names.length)];
        
        user.setCompanyEmail(randomName.toLowerCase() + "@" + domains[(int)(Math.random() * domains.length)]);
        user.setDepartMentId(randomId);
        user.setDepartMentName(depts[(int)(Math.random() * depts.length)]);
        user.setEmail(phone + "@139.com");
        user.setEmpNo("EMP" + randomId);
        user.setIsValid(isValid);
        user.setMobilePhone(phone);
        user.setOrgFullName("中移互联网有限公司\\" + user.getDepartMentName());
        user.setOrgId(randomId);
        user.setOrgName(user.getDepartMentName());
        user.setPortalUserId(randomName.toLowerCase());
        user.setPortalUserName(randomName);
        user.setPosition(String.valueOf((int)(Math.random() * 3) + 1));
        user.setSex(String.valueOf((int)(Math.random() * 2) + 1));
        user.setUserCategory(String.valueOf((int)(Math.random() * 2) + 1));
        user.setUserId(randomId);
        return user;
    }

}

3、客户端实现

客户端对服务端接口调用即可:


import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 用于创建和配置一个Web Service客户端代理,以便调用远程的Web Service服务。
 */
@Configuration
public class WebServiceConfig {

    @Bean(name = "orgAndUserServiceProxy")
    public OrgAndUserService  orgAndUserServiceClient() {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(OrgAndUserService .class);
        factory.setAddress("http://localhost:8080/services/orgAndUserService");

        // 创建客户端
        OrgAndUserService  client = (OrgAndUserService ) factory.create();

        // 配置客户端超时时间
        Client proxy = org.apache.cxf.frontend.ClientProxy.getClient(client);
        HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
        HTTPClientPolicy policy = new HTTPClientPolicy();
        policy.setConnectionTimeout(30000); // 连接超时 30 秒
        policy.setReceiveTimeout(30000);    // 接收超时 30 秒
        conduit.setClient(policy);
        return client;
    }


}

import com.oak.springbootredis.domain.ObjectFactory;
import com.oak.springbootredis.domain.resp.QueryUserResponse;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

/**
 * 定义Web Service服务契约  即要访问的接口协议
 */
@WebService(targetNamespace = "http://webservice.cfms.richinfo.cn/", name = "orgAndUserService")
@XmlSeeAlso({ObjectFactory.class})
public interface OrgAndUserService    {

    @WebMethod(operationName = "queryEntUserByBatchPhone")
    @RequestWrapper(localName = "queryEntUserByBatchPhone", targetNamespace = "http://webservice.cfms.richinfo.cn/", className = "com.oak.springbootredis.domain.req.QueryEntUserByBatchPhone")
    @ResponseWrapper(localName = "queryEntUserByBatchPhoneResponse", targetNamespace = "http://webservice.cfms.richinfo.cn/", className = "com.oak.springbootredis.domain.resp.QueryEntUserByBatchPhoneResponse")
    @WebResult(name = "return", targetNamespace = "")
        // 修正返回类型的大小写,与实际类名一致
    QueryUserResponse queryEntUserByBatchPhone(
            @WebParam(name = "batchPhone", targetNamespace = "")
            String batchPhone
    );
}

import com.oak.springbootredis.domain.resp.QueryUserResponse;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * WebService 客户端
 */
@Service
public class OrgAndUserServiceClient {

    @Value("${service.orgAndUser.appId:25816083}")
    private String appId;
    @Value("${service.orgAndUser.appSecret:c0610ba01b3a45d793aa42afef6b71a}")
    private String appSecret;
    @Value("${service.orgAndUser.token:CE000000175210792112122e6190bf89e4cd18861c31accf4cac}")
    private String token;


    @Autowired
    @Qualifier("orgAndUserServiceProxy") // 指定 Bean 名称
    private OrgAndUserService  userService;

    public QueryUserResponse queryEntUserByBatchPhone(String batchPhone) {
        return queryEntUserByBatchPhone(batchPhone, appId, appSecret, token,"queryEntUserByBatchPhone","fsere3","1.3.5");
    }
    public QueryUserResponse queryEntUserByBatchPhone(String batchPhone,
                                                      String appId,
                                                      String appSecret,
                                                      String token,
                                                      String functionId,
                                                      String signature,
                                                      String version) {
        // 获取 CXF 客户端
        Client client = ClientProxy.getClient(userService);
        // 清除之前的拦截器
        client.getOutInterceptors().clear();
        // 添加自定义消息头拦截器
        client.getOutInterceptors().add(new SoapHeaderInterceptor(
                appId, appSecret, token, functionId, signature, version
        ));
        // 调用 WebService 方法
        return userService.queryEntUserByBatchPhone(batchPhone);
    }
}

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;
import java.util.Date;

/**
 * 请求参数封装
 */
public class SoapHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    private final String appId;
    private final String appSecret;
    private final String token;
    private final String functionId;
    private final String signature;
    private final String version;

    public SoapHeaderInterceptor(String appId, String appSecret, String token,
                                 String functionId, String signature, String version) {
        super(Phase.PREPARE_SEND);
        this.appId = appId;
        this.appSecret = appSecret;
        this.token = token;
        this.functionId = functionId;
        this.signature = signature;
        this.version = version;
    }

    @Override
    public void handleMessage(SoapMessage message) throws Fault {
        Document doc = DOMUtils.createDocument();

        // 创建 msghead 元素
        Element msghead = doc.createElement("msghead");

        // 添加消息头字段
        addElement(doc, msghead, "appId", appId);
        addElement(doc, msghead, "appSecret", appSecret);
        addElement(doc, msghead, "token", token);
        addElement(doc, msghead, "reqTimestamp", String.valueOf(new Date().getTime() / 1000));
        addElement(doc, msghead, "functionId", functionId);
        addElement(doc, msghead, "signature", signature);
        addElement(doc, msghead, "version", version);

        // 将消息头添加到 SOAP 消息中
        message.getHeaders().add(new Header(new QName("msghead"), msghead));
    }

    private void addElement(Document doc, Element parent, String name, String value) {
        Element element = doc.createElement(name);
        element.setTextContent(value);
        parent.appendChild(element);
    }
}

4、报文实体类映射

根据报文结构,编写返回实体类字段,若字段少了或者错了 都会导致接口报错。

结果报文结果:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns2:queryEntUserByBatchPhoneResponse xmlns:ns2="http://webservice.cfms.richinfo.cn/">
            <return>
                <code>0</code>
                <data>
                    <entUser>
                        <companyEmail>钱七@139.com</companyEmail>
                        <departMentId>16512</departMentId>
                        <departMentName>系统工程部</departMentName>
                        <empNo>EMP16512</empNo>
                        <email>17855954682@139.com</email>
                        <isValid>1</isValid>
                        <mobilePhone>17855954682</mobilePhone>
                        <orgFullName>中移互联网有限公司\系统工程部</orgFullName>
                        <orgId>16512</orgId>
                        <orgName>系统工程部</orgName>
                        <portalUserId>钱七</portalUserId>
                        <portalUserName>钱七</portalUserName>
                        <position>3</position>
                        <sex>2</sex>
                        <userCategory>2</userCategory>
                        <userId>16512</userId>
                    </entUser>
                </data>
                <msg>根据批量手机号查询实体(自有或合作伙伴)人员信息成功</msg>
            </return>
        </ns2:queryEntUserByBatchPhoneResponse>
    </soap:Body>
</soap:Envelope>

实体类映射:


import lombok.Data;

import javax.xml.bind.annotation.*;

@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "return", propOrder = {
        "code",
        "data",
        "msg"
})
@XmlRootElement(name = "return")
public class QueryUserResponse {
    @XmlElement(name = "code")
    private String code;

    @XmlElement(name = "data")
    private ResponseData data;

    @XmlElement(name = "msg")
    private String msg;

}





import lombok.Data;

import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;

@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class ResponseData {
    @XmlElement(name = "entUser")
    public List<EntUser> entUser = new ArrayList<>();

}




import lombok.Data;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class EntUser {
    @XmlElement(name = "companyEmail")
    private String companyEmail;

    @XmlElement(name = "departMentId")
    private String departMentId;

    @XmlElement(name = "departMentName")
    private String departMentName;

    @XmlElement(name = "empNo")
    private String empNo;

    @XmlElement(name = "email")
    private String email;

    @XmlElement(name = "isValid")
    private String isValid;

    @XmlElement(name = "mobilePhone")
    private String mobilePhone;

    @XmlElement(name = "orgFullName")
    private String orgFullName;

    @XmlElement(name = "orgId")
    private String orgId;

    @XmlElement(name = "orgName")
    private String orgName;

    @XmlElement(name = "portalUserId")
    private String portalUserId;

    @XmlElement(name = "portalUserName")
    private String portalUserName;

    @XmlElement(name = "position")
    private String position;

    @XmlElement(name = "sex")
    private String sex;

    @XmlElement(name = "userCategory")
    private String userCategory;

    @XmlElement(name = "userId")
    private String userId;


}


5、测试

请求

curl --location 'http://10.10.118.124:8080/services/orgAndUserService' \
--header 'Content-Type: text/xml' \
--data '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header>
        <msghead>
            <appId>25816083</appId>
            <appSecret>c0610ba01b3a45d793aa42afef6b71a</appSecret>
            <token>CE000000175210792112122e6190bf89e4cd18861c31accf4cac</token>
            <reqTimestamp>1422343231</reqTimestamp>
            <functionId>queryEntUserByBatchPhone</functionId>
            <signature>fsere3</signature>
            <version>1.3.5</version>
        </msghead>
    </soap:Header>
    <soap:Body>
        <ns2:queryEntUserByBatchPhone
            xmlns:ns2="http://webservice.cfms.richinfo.cn/">
            <batchPhone>17855954111</batchPhone>
        </ns2:queryEntUserByBatchPhone>
    </soap:Body>
</soap:Envelope>'

返回

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns2:queryEntUserByBatchPhoneResponse xmlns:ns2="http://webservice.cfms.richinfo.cn/">
            <return>
                <code>0</code>
                <data>
                    <entUser>
                        <companyEmail>钱七@139.com</companyEmail>
                        <departMentId>16512</departMentId>
                        <departMentName>系统工程部</departMentName>
                        <empNo>EMP16512</empNo>
                        <email>123@139.com</email>
                        <isValid>1</isValid>
                        <mobilePhone>17855954111</mobilePhone>
                        <orgFullName>中移互公司\系统工程部</orgFullName>
                        <orgId>16512</orgId>
                        <orgName>系统工程部</orgName>
                        <portalUserId>钱七</portalUserId>
                        <portalUserName>钱七</portalUserName>
                        <position>3</position>
                        <sex>2</sex>
                        <userCategory>2</userCategory>
                        <userId>16512</userId>
                    </entUser>
                </data>
                <msg>根据批量手机号查询实体(自有或合作伙伴)人员信息成功</msg>
            </return>
        </ns2:queryEntUserByBatchPhoneResponse>
    </soap:Body>
</soap:Envelope>

6、源码

        源码地址:https://gitee.com/thin-rain/my-springboot/tree/redis/ 

        注释:源码中查看截图的部分即可

### 集成 Web Service 客户端到 Spring Boot 项目 在 Spring Boot集成 Web Service 客户端可以通过多种方式实现,其中最常见的是使用 JAX-WS 或 Apache CXF 来调用 SOAP RESTful 的 Web Services。以下是通过 JAX-WS 实现的一个简单例子: #### 使用 JAX-WS 调用 SOAP Web Service 1. **添加依赖项** 在 `pom.xml` 文件中引入必要的 Maven 依赖项来支持 JAX-WS。 ```xml <dependency> <groupId>javax.xml.ws</groupId> <artifactId>jaxws-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>com.sun.xml.ws</groupId> <artifactId>rt</artifactId> <version>2.3.1</version> </dependency> ``` 2. **生成客户端代码** 假设有一个 WSDL 地址指向目标服务,则可以利用 `wsimport` 工具自动生成 Java 类文件。 ```bash wsimport -keep -s src/main/java http://example.com/service?wsdl ``` 此命令会解析指定的 WSDL 并生成相应的类结构以便于后续操作[^1]。 3. **编写配置服务调用逻辑** 创建一个 Bean 来封装远程方法调用过程。 ```java import org.springframework.stereotype.Service; import javax.xml.namespace.QName; import javax.xml.ws.Service; import java.net.URL; @Service public class SoapClient { private final String endpointUrl = "http://example.com/service"; private final String namespaceUri = "http://service.example.com/"; private final String serviceName = "ExampleService"; public String callRemoteMethod() throws Exception { URL url = new URL(endpointUrl); QName qname = new QName(namespaceUri, serviceName); Service service = Service.create(url, qname); ExamplePortType port = service.getPort(ExamplePortType.class); // 替换为实际接口名 return port.someOperation("test"); // 替换为目标方法及其参数 } } ``` 4. **测试功能** 构建单元测试验证整个流程是否正常工作。 ```java import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class SoapClientTest { @Autowired private SoapClient soapClient; @Test void testCallRemoteMethod() throws Exception { System.out.println(soapClient.callRemoteMethod()); } } ``` 对于基于 REST 的 Web Services 可以考虑采用 Feign 或 RestTemplate 这样的工具简化开发体验[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值