分布式微服务架构之SpringBoot整合篇

一,springBoot整合mybatis,pageHelper,druid,junit4

1.首先创建springboot项目并导入依赖

    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.2.6.RELEASE</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springboot</artifactId>
    <dependencies>
        <!--  web模块启动器      -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--   lombok插件     -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <!--    mybatis    -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <!--    mysql    -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>
        <!--    druid    -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.14</version>
        </dependency>
        <!--    test    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--    junit    -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <!--    pagehelper     -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
    </dependencies>

2.编写配置文件

#springBoot整合数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql:///cloud0623
spring.datasource.username=root
spring.datasource.password=root

#springBoot整合mybatis
#配置mybatis日志级别
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#配置别名的包
mybatis.type-aliases-package=com.yhd.domain
#指定mapper映射文件的位置
mybatis.mapper-locations=classpath:/mapper/*.xml

#springboot整合pageHelper
pagehelper.helper-dialect=mysql
pagehelper.params=count=countSql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true

3.编写主启动类

/**
 * @author yhd
 * @createtime 2020/10/5 18:18
 */
//标识在一个主程序上,表示这是一个springboot应用程序的启动器,
// 也是整个应用程序的入口
@SpringBootApplication
//开启声明式事务
@EnableTransactionManagement
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);

    }
}

4.编写mapper接口以及映射文件

/**
 * @author yhd
 * @createtime 2020/10/6 10:59
 */
@Mapper
public interface UserMapper {

    public List<User> findAll();
}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yhd.mapper.UserMapper">

    <resultMap id="baseUserMap" type="com.yhd.domain.User" autoMapping="true">
        <id column="id" property="id"></id>
    </resultMap>
    <select id="findAll" resultMap="baseUserMap">
        select * from t_user;
    </select>
</mapper>

5.编写服务层

/**
 * @author yhd
 * @createtime 2020/10/6 10:53
 */
@Service
public class HelloService {

    @Autowired
    private UserMapper userMapper;

    public List<User> findAll(int pageNum,int pageSize){
    	//整合pagehelper分页插件
        PageHelper.startPage(pageNum,pageSize);
        return userMapper.findAll();
    }
}

6.编写控制器

/**
 * @author yhd
 * @createtime 2020/10/6 11:25
 */
@Controller
public class HelloController {

    @Autowired
    private HelloService helloService;

    @GetMapping("findAll/{pageNum}/{pageSize}")
    public String findAll(Integer pageNum, Integer pageSize, Model model){
        List<User> userList = helloService.findAll(pageNum, pageSize);
        //整合pagehelper分页插件
        PageInfo<User> pageInfo = new PageInfo<>(userList);
        model.addAttribute("pageInfo",pageInfo);
        return "success";
    }
}

7.单元测试

/**
 * @author yhd
 * @createtime 2020/10/6 11:09
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class TestA {

    @Autowired
    private HelloService helloService;
    @Test
    public void test1(){
        helloService.findAll().forEach(System.out::println);
    }
}

8.配置druid连接池监控界面

加入配置类

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yhd
 * @createtime 2020/10/6 11:38
 * 德鲁伊连接池监控配置
 */
@SpringBootConfiguration
public class DruidConfig {

    @Value("${druid.username}")
    private String username;
    @Value("${druid.password}")
    private String password;
    //1、配置一个管理后台的Servlet
    @Bean
    public ServletRegistrationBean statViewServlet() {
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");

        Map<String, String> initParams = new HashMap<>();
        //设置登陆的用户名
        initParams.put("loginUsername", username);
        //设置登陆的密码
        initParams.put("loginPassword", password);
        // 默认就是允许所有访问
        initParams.put("allow", "");

        bean.setInitParameters(initParams);
        return bean;
    }
    //2、配置一个web监控的filter
    @Bean
    public FilterRegistrationBean webStatFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        Map<String, String> initParams = new HashMap<>();
        //设置忽略路径
        initParams.put("exclusions", "*.js,*.css,/druid/*");

        bean.setInitParameters(initParams);
        //设置过滤器过滤路径
        bean.setUrlPatterns(Arrays.asList("/*"));

        return bean;
    }
}

配置文件

#德鲁伊连接池监控
#开启德鲁伊监控
spring.datasource.druid.filters=stat
druid.username=yhd
druid.password=yhd

启动项目,访问localhost:8080/druid/

二,springBoot整合springDataJPA

1.创建项目并导入依赖

    <dependencies>
        <!--  web模块启动器      -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--   lombok插件     -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <!--    jpa    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--    mysql    -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>
        <!--    druid    -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.14</version>
        </dependency>
        <!--    test    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--    junit    -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.编写配置文件

#springBoot整合数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql:///cloud0623?useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root

#springBoot整合jpa
spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
#配置自动建表:update:没有表新建,有表更新操作,控制台显示建表语句
spring.jpa.hibernate.ddl-auto=update


#德鲁伊连接池监控
#开启德鲁伊监控
spring.datasource.druid.filters=stat
druid.username=yhd
druid.password=yhd

3.主启动类

/**
 * @author yhd
 * @createtime 2020/10/5 18:18
 */
//标识在一个主程序上,表示这是一个springboot应用程序的启动器,
// 也是整个应用程序的入口
@SpringBootApplication
//开启声明式事务
@EnableTransactionManagement
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);

    }
}

4.实体类

import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;

/**
 * @author yhd
 * @createtime 2020/10/6 10:55
 */
@Data
@Entity
@Table(name="t_user")
public class User implements Serializable {

    private static final long serialVersionUID = 6265645990934511846L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name ="id")
    private Long id;
    @Column(name = "name")
    private String name;
    @Column(name = "age")
    private int age;
}

5.mapper

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;


import java.util.List;

/**
 * @author yhd
 * @createtime 2020/10/6 10:59
 */
public interface UserMapper extends JpaRepository<User,Long>, JpaSpecificationExecutor<UserMapper> {
    //use jpql sql to query
    @Query(value="from User ")
    //update delete  method must use it  ,jpql not support insert
    //@Modifying
    public List<User> findAll();

    @Modifying
    @Query(value="update User set name = :#{#user.name},age = :#{#user.age} where id=:#{#user.id}")
    public void myUpdate(@Param("user") User user);

    //query with native sql
    @Query(value="delete from t_user where id = :#{#id}",nativeQuery=true)
    public void myDelete(@Param("id") Long id);
}

6.测试

import com.yhd.service.HelloService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author yhd
 * @createtime 2020/10/6 11:09
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class TestA {

    @Autowired
    private HelloService helloService;
    @Test
    public void test1(){
        helloService.findAll().forEach(System.out::println);
    }
}

三,springBoot整合redis

1.创建项目,导入依赖

    <dependencies>
        <!--  web模块启动器      -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--   lombok插件     -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <!--   redis     -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
    </dependencies>

2.配置文件

#springBoot整合redis
#端口
spring.redis.port=6379
#host
spring.redis.host=localhost
#连接的数据库
spring.redis.database=0
#数据库密码
spring.redis.password=
#超时时间
spring.redis.timeout=1000000
#最大连接数
spring.redis.lettuce.pool.max-active=20
#最大阻塞等待时间 负数表示没有限制
spring.redis.lettuce.pool.max-wait=-1
#最大空闲连接数
spring.redis.lettuce.pool.max-idle=5
#最小空闲连接数
spring.redis.lettuce.pool.min-idle=0

3.使用

/**
 * @author yhd
 * @createtime 2020/10/6 14:01
 */
@Service
public class PersonService {

    @Autowired
    private PersonMapper mapper;
    @Autowired
    private RedisTemplate redisTemplate;
    //    @Autowired
    //    private StringRedisTemplate stringRedisTemplate;
    public List<Person> findAll() {
        // redis的key
        String key = "allperson";
        // 先查询redis中是否有数据,如果有直接返回redis的数据
        List<Person> persons = (List<Person>) redisTemplate.boundValueOps(key).get();
        if (persons!=null) {
            return persons;
        }

        // 如果没有,查询数据库
        persons = mapper.findAll();
        // 将数据库数据存入到redis中
        if (persons != null && persons.size()>0) {
            redisTemplate.boundValueOps(key).set(persons);
        }
        return persons;
    }
}

四,springBoot整合定时任务

1.导入依赖

        <!--   定时任务     -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

2.主启动类

/**
 * @author yhd
 * @createtime 2020/10/5 18:18
 */
@SpringBootApplication
//开启定时任务注解
@EnableScheduling
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);

    }
}

3.定时任务

/**
 * @author yhd
 * @createtime 2020/10/6 14:12
 */
@Component
public class Crond {

    /**
     *            @Scheduled:定时规则
     *             cron:项目启动后每5秒执行一次
     *
     *             fixedDelay:距离上一次定时任务执行完毕后N毫秒再执行,
     *             执行A任务花了5秒,比如参数是3000,A任务执行完成之后,在过3秒执行
     *
     *             fixedRate:执行周期,执行频率
     *             定时任务执行开始,在过N毫秒后执行,
     *             执行A任务花了2秒,比如参数是3000,A任务执行完成之后,在过1秒后执行,
     *             执行A任务花了15秒,比如参数是3000,A任务执行完成之后,立即执行。
     */
    @Scheduled(fixedDelay = 3000)
    public void myTask() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(simpleDateFormat.format(new Date()));
    }

}

4.Cron表达式详解

Cron表达式详解
	1.基本格式
		用空格分开的7个部分,按顺序依次为 
		①秒:0~59
		②分钟:0~59
		③小时:0~23
		④日期:1~31,但是需要考虑月的实际天数 day-of-month
		⑤月:1~12
		⑥星期:1~7(1为星期日)或SUN,MON,TUE,WED,THU,FRI,SAT day-of-week
		⑦年份:1970~2099可选
	2.设置方式
		①指定具体值:5
		②连续区间:9-12
		③有间隔的区间:8-18/4
			斜杠后面为间隔跨度
		④具体值的列表:1,3,5
		⑤通配符
			[1]*:表示在取值范围内的所有时间点都执行调度任务
				例如:用*指定秒,表示每秒都执行任务;用*指定星期表示一周内的每一天都执行任务
			[2]/:用于表示时间间隔
				例如:用*/5指定秒,表示每隔5秒执行一次任务
			[3]?:仅被用于day-of-month字段或day-of-week字段,表示不指定值。由于某个月的几号和星期几很难统一成同一天。所以为了避免冲突,day-of-month或day-of-week中的其中一个设置了具体的值(注意:*也是具体值,因为*表示取值范围内所有值)后,另一个就必须设置为问号
			[4]L:仅被用于day-of-month字段或day-of-week字段,表示一个月或一个星期的最后一天,是单词Last的缩写。如果L前面有数字则表示不同含义。例如:“6L”表示这个月的倒数第6天,“FRIL”表示这个月的最一个星期五。注意:在使用“L”参数时,不要指定列表或范围,这会导致问题。
			[5]W("weekday"):只能用在day-of-month字段。用来描叙最接近指定天的工作日:周一到周五。例如:在day-of-month字段用“15W”指“最接近这个月第15天的工作日”,即如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第16天即周一触发;如果这个月第15天是周二,那么就在触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在day-of-month指明一天,不能是一个范围或列表。也可以用“LW”来指定这个月的最后一个工作日。 
			[6]#:只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用"6#3"指这个月第3个周五(6指周五,3指第3个)。如果指定的日期不存在,触发器就不会触发。 
			[7]C:指和calendar联系后计算过的值。例:在day-of-month字段用“5C”指在这个月第5天或之后包括calendar的第一天;在day-of-week字段用“1C”指在这周日或之后包括calendar的第一天。
	3.示例
		表达式											说明
		=======================================================
		秒	分		时		日	月	星期	年		
		-------------------------------------------------------
		0 	0		12		*	*	?					每天中午12点触发 
		0	15		10		?	*	*					每天上午10:15触发 
		0	15		10		*	*	?					每天上午10:15触发 
		0	15		10		*	*	?		*			每天上午10:15触发
		0	15		10		*	*	?		2005		2005年的每天上午10:15触发 
		0	*		14		*	*	?					在每天下午2点到下午2:59期间的每1分钟触发
		0	0/5		14		*	*	?					在每天下午2点到下午2:55期间的每5分钟触发 
		0	0/5		14,18	*	*	?					在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 
		0	0-5		14		*	*	?					在每天下午2点到下午2:05期间的每1分钟触发 
		0	10,44	14		?	3	WED					每年四月的星期三的下午2:10和2:44触发 
		0	15		10		?	*	MON-FRI				周一至周五的上午10:15触发
		0	15		10		15	*	?					每月15日上午10:15触发 
		0	15		10		L	*	?					每月最后一日的上午10:15触发 
		0	15		10		?	*	6L					每月的最后一个星期五上午10:15触发 
		0	15		10		?	*	6L		2002-2005	2002年至2005年的每月的最后一个星期五上午10:15触发 
		0	15		10		?	*	6#3					每月的第三个星期五上午10:15触发

五,springBoot整合es

1.添加依赖

        <!--   es     -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            <version>2.2.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.data</groupId>
                    <artifactId>spring-data-elasticsearch</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.2.6.RELEASE</version>
        </dependency>

2.配置文件

#springBoot整合es
#连接超时时间
spring.elasticsearch.rest.connection-timeout=
#read的超时时间
spring.elasticsearch.rest.read-timeout=
#host+port
spring.elasticsearch.rest.uris=
#开启es仓库的使用 == @EnableElasticsearchRepositories
spring.data.elasticsearch.repositories.enabled=true

3.实体类

//文档对象,索引信息,文档类型
@Document(indexName ="my_db",type = "t_user")
public class User implements Serializable {

    @Id
    @Field(store = true,type = FieldType.Keyword,index = false)
    private Integer id;
    @Field(store = true,type = FieldType.Text,analyzer = "ik_max_word")
    private String name;
    @Field(store = true,type = FieldType.Integer)
    private Integer age;
    @Field(store = true,type = FieldType.Text,analyzer ="ik_max_word" )
    private String desc;
    }

4.Repository

/**
 * @author yinhuidong
 * @createTime 2020-06-05-23:23
 */
public interface UserRepository extends ElasticsearchRepository<User,Integer> {


}

5.service

/**
 * @author yinhuidong
 * @createTime 2020-08-03-23:24
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Override
    public void save(User user) {
        userRepository.save(user);
    }

    @Override
    public void create() {
        elasticsearchRestTemplate.createIndex(User.class);
        elasticsearchRestTemplate.putMapping(User.class);
    }

    @Override
    public User select(Integer id) {
        return userRepository.findById(1).get();
    }
}

六,springBoot整合Spring AMQP

Spring-amqp是对AMQP协议的抽象实现,而spring-rabbit是对协议的具体实现,也是目前的唯一实现。底层使用的就是RabbitMQ

1.导入依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2.配置文件

spring:
  rabbitmq:
    host: 121.199.31.160
    username: root
    password: root
    virtual-host: /shopping
    port: 5672

3.监听者

/**
 * ·    @Componet:类上的注解,注册到Spring容器
 *
 * ·    @RabbitListener:方法上的注解,声明这个方法是一个消费者方法,需要指定下面的属性:
 *
 * ​			o  bindings:指定绑定关系,可以有多个。值是@QueueBinding的数组。@QueueBinding包含下面属性:
 *
 * ​			o  value:这个消费者关联的队列。值是@Queue,代表一个队列
 *
 * ​			o  exchange:队列所绑定的交换机,值是@Exchange类型
 *
 * ​			o  key:队列和交换机绑定的RoutingKey
 *
 * ​			durable = "true" 代表持久化
 *
 * ​			ignoreDeclarationExceptions = "true", 异常情况是否忽略
 *
 * 类似listen这样的方法在一个类中可以写多个,就代表多个消费者。
 */
@Component
public class Listener {

    @RabbitListener(bindings = @QueueBinding(
        //value:队列名
            value = @Queue(value = "spring.test.queue", durable = "true"),
            exchange = @Exchange(
                //交换机名
                    value = "spring.test.exchange",
                    ignoreDeclarationExceptions = "true",
                    type = ExchangeTypes.TOPIC
            ),
            key = {"#.#"}))
    public void listen(String msg){
        System.out.println("接收到消息:" + msg);
    }
}

4.AmqpTemplate

Spring为AMQP提供了统一的消息处理模板:AmqpTemplate,非常方便的发送消息,其发送方法:
在这里插入图片描述
红框圈起来的是比较常用的3个方法,分别是:

o 指定消息

o 指定RoutingKey和消息,会向默认的交换机发送消息

o 指定交换机、RoutingKey和消息体

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class MqDemo {

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Test
    public void testSend() throws InterruptedException {
        String msg = "hello, Spring boot amqp";
        this.amqpTemplate.convertAndSend("spring.test.exchange", "a.b", msg);
        // 等待10秒后再结束
        Thread.sleep(10000);
    }
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值