通用分页-后台

目录

一、介绍

1.通用分页是什么

2.为什么要学

3.怎么用

二、不使用通用

1.增加数据表及数据

1.1创建表

1.2增加数据

2.mysql连接类

2.1辅助文件

 2.2连接类

3.工具(帮助)类

3.1帮助类

3.2工具类

4.实体类

5.数据访问层

6.测试结果

三、JUnit4

3.1什么?

3.2引入

3.3使用

四、使用通用

4.1 BaseDao类

4.2 BookDao

4.3 测试结果

对我们带来什么


一、介绍

1.通用分页是什么

JavaEE通用分页,即将数据分页展示的一种通用方式。在JavaEE开发中,通常会涉及到数据展示的需求,例如查询数据库中的数据并展示到网页中。但是,当数据量很大时,一次性展示所有数据会影响页面的加载速度和性能,因此需要将数据分页展示。通用分页是指通过一定的规则将数据按页码进行划分,并且提供对每一页数据的访问方式,从而实现数据的分页展示。

在JavaEE中,常用的分页方式是在数据查询时,在SQL语句中使用limit关键字进行限制。具体实现方式是通过计算总记录数和每页展示的记录数,将需要的记录分割成若干页,并提供访问对应页码数据的方法。此外,也可以使用JavaEE框架中提供的分页工具类,如Spring分页插件,方便快速地实现通用分页功能。

2.为什么要学

学习JavaEE中通用分页功能是非常有必要的,因为在实际的Web应用程序开发中,经常需要处理大量数据。在这种情况下,一次从数据源中检索所有记录的操作会导致长时间的等待,浪费大量的时间和资源。此外,如果数据量较大,还可能会造成单次查询异常或内存溢出等问题。

因此,在JavaEE中实现通用分页功能是一个非常普遍的解决方案,这将大大提高Web应用程序的性能和体验。通用分页也可以帮助我们更好地处理业务求,因为用户经常需要在多个页面之间跳转,同时保持分页状态。掌握通用分页功能,可以使我们更加熟练和高效地编写代码,提高我们作为JavaEE开发人员的技能水平。

3.怎么用

在MySQL中使用JavaEE中通用分页功能,通常需要以下步骤:

1.按照要求编写 SQL 语句,在 SQL 语句的末尾增加 LIMIT 关键字,用于限制查询结果的范围。例如,使用 LIMIT 子句限制查询结果从第 1 行开始,取出100条数据的 SQL 语句如下:

SELECT * FROM 表名 WHERE 条件 LIMIT 0,100;

其中,0 表示查询结果的起始行数,100 表示查询结果的数量。

2.在 JavaEE 的业务逻辑层中使用查询语句查询数据,并且获取分页参数(如当前页码、每页数据量等),计算当前数据查询需要使用的 LIMIT 语句的两个参数(即上面步骤中的起始行数和每页数量)。

3.将得到的起始行数和每页数量拼接到 SQL 语句中,形成可以直接使用的 SQL 语句。可以利用占位符,将分页参数插入到 SQL 语句中,以防止 SQL 注入等问题。

4.使用 JDBC 等数据访问框架执行带有 LIMIT 子句的 SQL 语句获取对应的分页数据,将其封装成 Java 对象。

5.在业务逻辑层中,根据查询结果和分页参数,封装一个分页对象,将查询结果和分页对象一起返回到展示层,供前端页面进行展示。

6.前端展示分页数据通常需要使用 JavaScript 等前端技术,根据获取到的分页对象数据,在页面上生成分页控制器,然后将查询到的数据进行展示。

以上就是在 MySQL 数据库中使用 JavaEE 中通用分页功能的基本流程,同样需要注意业务需求和框架的差异,处理方式也会有所不同。为避免一些潜在的问题和安全隐患,应该注意合理设计 SQL 语句、使用有效的数据访问框架以及数据分页的相关参数,以提高对分页查询的使用体验和安全性。

二、不使用通用

JavaWeb分页功能的主要流程如下:

1. 用户请求分页:通常是通过前端页面向后端发起一个HTTP/GET请求,将分页相关参数(当前页码、每页展示数量等)以请求参数的形式传递给后端。

2. 查询总记录数:根据用户请求,后端通过SQL语句查询数据库,获取需要展示的总记录数。这个操作通常是用COUNT函数实现,可以提高查询效率。

3. 计算分页信息:后端根据总记录数和用户请求,计算出展示的总页数和当前页码,同时计算出查询数据的起始位置和截止位置。

4. 查询当前页数据:后端再次根据用户请求,通过SQL语句查询数据库,获取当前页需要展示的数据。查询语句加上LIMIT关键字,根据计算出的数据范围进行分页查询。

5. 返回分页数据:后端将查询出的数据和分页相关信息打包返回给前端,通常是以JSON格式返回,前端通过解析JSON数据并展示到页面上。

6. 前端分页展示:前端负责将后端返回的数据进行渲染展示,同时渲染出分页控制器。用户可以通过控制器切换页码和设定每页展示的数量。

7. 重新发起分页请求:如果用户对分页控制器进行了操作,前端将重新发起分页请求,并将分页相关参数再次传递给后端进行查询。

以上就是JavaWeb分页功能的基本流程。分页作为一个基础而常用的功能,在实际应用中经常会出现,因此掌握分页技术是比较有价值的一项技能。

1.增加数据表及数据

1.1创建表

如果要在 MySQL 中增加一个数据表,并设置属性 bid、bname、price,可以使用以下 SQL 语句:

CREATE TABLE t_mvc_book(
  bid INT PRIMARY KEY AUTO_INCREMENT,
  bname VARCHAR(100),
  price FLOAT
);

其中,t_mvc_book是数据表名,bidbnameprice 分别是列名,INTVARCHARFLOAT 分别是数据类型,PRIMARY KEY 表示设置主键,AUTO_INCREMENT 表示主键自动递增。这样就创建好了一个名为 books 的数据表,有三个列,分别是 bid,bname 和 price。

1.2增加数据

如果需要向 books 表中插入数据,可以使用 INSERT INTO 语句,语法如下:

INSERT INTO t_mvc_book(bname, price) VALUES ('斗破苍穹', 78.00);

以上语句会向 t_mvc_book表中插入一条新纪录,包含 bname 和 price 两个属性,其中 bname 属性对应的值为 ‘斗破苍穹’,price 属性对应的值为 78.00。如果还需要向表中插入更多的数据记录,只需要在语句选择的列中添加对应记录的值即可。

需要注意的是,数据表属性的命名规范、数据类型的选择、主键、外键等的设置,以及插入数据时的数据格式、字符编码等都是需要考虑的问题,需要根据具体业务需求进行设置和调整,以提高数据表的可维护性和使用的效率

2.mysql连接类

2.1辅助文件
#mysql
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_ssm?useUnicode=true&characterEncoding=UTF-8&useSSL=false
user=root
pwd=123456
 2.2连接类
package com.CloudJun.utils;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * @author Cloud.Jun
 * @com.CloudJun.utils
 * @DBAccess(说明):提供了一组获得或关闭数据库对象的方法
 */
public class DBAccess {
	private static String driver;
	private static String url;
	private static String user;
	private static String password;

	static {// 静态块执行一次,加载 驱动一次
		try {
			InputStream is = DBAccess.class
					.getResourceAsStream("config.properties");

			Properties properties = new Properties();
			properties.load(is);

			driver = properties.getProperty("driver");
			url = properties.getProperty("url");
			user = properties.getProperty("user");
			password = properties.getProperty("pwd");

			Class.forName(driver);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获得数据连接对象
	 * 
	 * @return
	 */
	public static Connection getConnection() {
		try {
			Connection conn = DriverManager.getConnection(url, user, password);
			return conn;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	public static void close(ResultSet rs) {
		if (null != rs) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}

	public static void close(Statement stmt) {
		if (null != stmt) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}

	public static void close(Connection conn) {
		if (null != conn) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}

	public static void close(Connection conn, Statement stmt, ResultSet rs) {
		close(rs);
		close(stmt);
		close(conn);
	}

	public static boolean isOracle() {
		return "oracle.jdbc.driver.OracleDriver".equals(driver);
	}

	public static boolean isSQLServer() {
		return "com.microsoft.sqlserver.jdbc.SQLServerDriver".equals(driver);
	}
	
	public static boolean isMysql() {
		return "com.mysql.cj.jdbc.Driver".equals(driver);
	}

	public static void main(String[] args) {
		Connection conn = DBAccess.getConnection();
		System.out.println(conn);
		DBAccess.close(conn);
		System.out.println("isOracle:" + isOracle());
		System.out.println("isSQLServer:" + isSQLServer());
		System.out.println("isMysql:" + isMysql());
		System.out.println("数据库连接(关闭)成功");
	}
}

3.工具(帮助)类

3.1帮助类

StringUtils类

package com.CloudJun.utils;
/**
 * @author Cloud.Jun
 * @com.CloudJun.utils
 * @StringUtils(说明):帮助类
 */
public class StringUtils {
	
	// 私有的构造方法,保护此类不能在外部实例化
	private StringUtils() {
		
	}

	/**
	 * 如果字符串等于null或去空格后等于"",则返回true,否则返回false
	 * @param s
	 * @return
	 */
	public static boolean isBlank(String s) {
		boolean b = false;
		if (null == s || s.trim().equals("")) {
			b = true;
		}
		return b;
	}
	
	/**
	 * 如果字符串不等于null或去空格后不等于"",则返回true,否则返回false
	 * 
	 * @param s
	 * @return
	 */
	public static boolean isNotBlank(String s) {
		return !isBlank(s);
	}

}
3.2工具类

PageBean类

package com.CloudJun.utils;

/**
 * @author Cloud.Jun
 * @com.CloudJun.utils
 * @PageBean(说明):分页工具类
 */
public class PageBean {

	private int page = 1;// 页码

	private int rows = 10;// 页大小

	private int total = 0;// 总记录数

	private boolean pagination = true;// 是否分页

	public PageBean() {
		super();
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public int getRows() {
		return rows;
	}

	public void setRows(int rows) {
		this.rows = rows;
	}

	public int getTotal() {
		return total;
	}

	public void setTotal(int total) {
		this.total = total;
	}

	public void setTotal(String total) {
		this.total = Integer.parseInt(total);
	}

	public boolean isPagination() {
		return pagination;
	}

	public void setPagination(boolean pagination) {
		this.pagination = pagination;
	}

	/**
	 * 获得起始记录的下标
	 * 
	 * @return
	 */
	public int getStartIndex() {
		return (this.page - 1) * this.rows;
	}

	@Override
	public String toString() {
		return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
	}

}

4.实体类

Book类

package com.CloudJun.entity;

/**
 * @author Cloud.Jun
 * @com.CloudJun.entity
 * @Book(说明):书(实体类)
 */
public class Book {
	private int bid;
	private String bname;
	private float price;

	@Override
	public String toString() {
		return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]";
	}

	public int getBid() {
		return bid;
	}

	public void setBid(int bid) {
		this.bid = bid;
	}

	public String getBname() {
		return bname;
	}

	public void setBname(String bname) {
		this.bname = bname;
	}

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

	public Book(int bid, String bname, float price) {
		super();
		this.bid = bid;
		this.bname = bname;
		this.price = price;
	}

	public Book() {
		super();
	}
	
	
	
	
}

5.数据访问层

package com.CloudJun.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.CloudJun.entity.Book;
import com.CloudJun.utils.DBAccess;
import com.CloudJun.utils.PageBean;
import com.CloudJun.utils.StringUtils;

/**
 * @author Cloud.Jun
 * @com.CloudJun.dao
 * @BookDao(说明):Book的模糊查询方法类
 */
public class BookDao {

	public List<Book> getlist(Book b, PageBean pb) throws Exception {
		// 实例化集合为容器,装载返回接收的数据
		List<Book> list = new ArrayList<Book>();
		// 进行mysql数据库连接
		Connection conn = DBAccess.getConnection();
		// 定义sql语句
		String sql = "select * from t_mvc_book where 1=1 ";
		// 当关键词不为空的时候,拼接模糊查询的sql语句
		String bname = b.getBname();
		if (StringUtils.isNotBlank(bname)) {
			sql += "  and bname like '%" + bname + "%'";
		}
		// 执行sql语句
		PreparedStatement pr = conn.prepareStatement(sql);
		// 返回所执行后的结果
		ResultSet rs = pr.executeQuery();
		while (rs.next()) {
			// 将结果集加入实体
			Book book = new Book(rs.getInt(1), rs.getString(2), rs.getFloat(3));
			// 将实体加入list集合
			list.add(book);
		}
		if (list != null) {
			DBAccess.close(conn, pr, rs);
		}
		return list;// 最后返回容器(集合)
	}

	@Test
	public void Text() throws Exception {
		Book book = new Book();
		book.setBname("圣墟");
		PageBean pb = new PageBean();
		List<Book> list = new BookDao().getlist(book, pb);
		for (Book bo : list) {
			System.out.println(bo);
		}
	}

}

6.测试结果

以下测试结果由本人自己加入了数据

 

三、JUnit4

3.1什么?

JUnit 是一个用于测试 Java 代码的测试框架,JUnit4 是 JUnit 框架的一个重要版本。JUnit4 是一个开源框架,可以帮助程序员进行单元测试,在程序的开发阶段可以在系统没有完成前发现问题,从而缩小了错误的范围,更好地实现了敏捷开发的目标。

JUnit4 提供了大量的注解、API 等功能,使用起来比较方便。JUnit4 的主要特点包括:

1. 基于注解:JUnit4 主要使用注解来标识测试方法和测试类,使用起来比较简单。

2. 易于使用:JUnit4 设计简洁,可以帮助用户快速编写和运行测试用例。

3. 灵活性:JUnit4 具有比较高的灵活性,可以完成多种测试任务,包括单元测试、集成测试和功能测试等。

4. 多用途性:JUnit4 不仅可以用于 Java 项目,还可以用于其他语言的测试中。

5. 多平台支持:JUnit4 可以运行在多个平台(如 Windows、Linux、Mac OS X 等)上,可以为不同的项目提供测试支持。

6. 不需要持久化:JUnit4 测试用例运行在内存中,并不需要数据库或文件操作等持久化操作。

熟练掌握使用 JUnit4 进行单元测试可以极大的提高程序开发和测试效率,不仅可以减少软件开发所需时间、增加交付速度,更可以提升软件的稳定性和可靠性。

3.2引入

在 Eclipse 中引入 JUnit4 项目,可以按照以下步骤进行:

  1. 下载 JUnit4:从 JUnit 官方网站或 Maven 仓库中下载 JUnit4 相应的 jar 包,或者通过 Maven 或 Gradle 等项目构建工具引入。

  2. 导入 JUnit4 文件:在 Eclipse 中,点击 File -> Import,选择 General -> Existing Projects into Workspace,然后选择下载的 JUnit4 jar 包所在的目录,导入到项目中。

  3. 将 JUnit4 加入到项目中的 Build Path:在 Eclipse 中,选择 Project -> Properties,然后在左侧导航栏中点击 Java Build Path,选择 Libraries 选项卡,点击右侧 Add Library 按钮,选择 JUnit4,然后点击 Finish 完成添加。

  4. 编写测试用例:在创建的测试类中编写测试方法,并使用 JUnit4 提供的注解标注测试方法,如使用 @Test 在测试类中指定测试方法。 

  5. 主要如图操作:

选中要导入的项目名称右键

 

 

 之后Finish到底即可

3.3使用

将要测试的方法打上@Test之后选中方法名右键测试即可,如图:

 

四、使用通用

需要进行通用先建一个类叫BaseDao类该类由通用分页的方法功能,在进行修改BookDao类,在该类里面进行测试

4.1 BaseDao类

package com.CloudJun.dao;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import com.CloudJun.utils.DBAccess;
import com.CloudJun.utils.PageBean;
/**
 * @author Cloud.Jun
 * @com.CloudJun.dao
 * @BaseDao(说明):通用的分页方法功能类
 */
public class BaseDao<T> {

	public  List<T> executeQuery(String sql,Class c,PageBean pb) throws Exception{
		//实例化集合为容器,装载返回接收的数据
		List<T> list = new ArrayList<T>();
		//定义连接对象
		Connection conn = null;
		//执行对象
		PreparedStatement pr = null;
		//结果集对象
		ResultSet rs = null;
		//判断是否分页,为null或者为""都是不进行分页
		if(pb.isPagination() && pb!=null) {
			//获取查询总数量(数据)后的sql语句
			String count= getCount(sql);
			//进行mysql数据库连接
			conn=DBAccess.getConnection();
			//执行sql语句
			pr= conn.prepareStatement(count);
			//返回所执行后的结果集
			rs=pr.executeQuery();
			//将总记录数赋值给分页工具类
			if(rs.next()) {
				pb.setTotal(rs.getObject("n").toString());
			}
			//初始下标,从哪里开始(从第几条数据开始)
			String pagesize=getPagesize(sql,pb);
			//进行mysql数据库连接
			conn=DBAccess.getConnection();
			//执行sql语句
			pr= conn.prepareStatement(pagesize);
			//返回所执行后的结果集
			rs=pr.executeQuery();
			
		}else {
			//进行mysql数据库连接
			conn=DBAccess.getConnection();
			//执行sql语句
			pr = conn.prepareStatement(sql);
			//返回所执行后的结果
			rs = pr.executeQuery();
		}
		//循环集合集
		while(rs.next()) {
			//进行反射(通过类名获取实例对象)
			T t = (T) c.newInstance();
			//返回该类中所有的变量(属性),不包括继承的成员变量和静态变量。
			Field[] fields = c.getDeclaredFields();
			//循环所有变量(属性)
			for (Field field : fields) {
				//打开变量的私有权限
				field.setAccessible(true);
				//设置属性值(获取该对象[t]的属性,根据field.getName()的方法获取该对象属性名称后进行属性值赋值)
				field.set(t, rs.getObject(field.getName()));
			}
			//增加进容器(集合)
			list.add(t);
		}
		return list;//最后返回容器(集合)
	}

	
	
	/**
	 * 方法功能:计算分页显示多少条数据
	 * @param sql 根据传过来的sql语句再进行条件查询
	 * @param pb 分页工具类
	 * @return
	 */
	public String getPagesize(String sql, PageBean pb) {
		return sql + " LIMIT "+pb.getStartIndex()+","+pb.getRows();
	}

	/**
	 * @param sql 查询传过来的sql语句再进行查询总数据条数(总记录)
	 * @return 查询总数量的sql语句
	 */
	public String getCount(String sql) {
		return "SELECT COUNT(1) as n from("+sql+") t";
	}

	
	
	
}

4.2 BookDao

package com.CloudJun.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.CloudJun.entity.Book;
import com.CloudJun.utils.DBAccess;
import com.CloudJun.utils.PageBean;
import com.CloudJun.utils.StringUtils;

/**
 * @author Cloud.Jun
 * @com.CloudJun.dao
 * @BookDao(说明):Book的模糊查询方法类
 */
public class BookDao extends BaseDao<Book>{

	public List<Book> getlist(Book b, PageBean pb) throws Exception {
		// 实例化集合为容器,装载返回接收的数据
		List<Book> list = new ArrayList<Book>();
		// 进行mysql数据库连接
		Connection conn = DBAccess.getConnection();
		// 定义sql语句
		String sql = "select * from t_mvc_book where 1=1 ";
		// 当关键词不为空的时候,拼接模糊查询的sql语句
		String bname = b.getBname();
		if (StringUtils.isNotBlank(bname)) {
			sql += "  and bname like '%" + bname + "%'";
		}
		// 执行sql语句
		PreparedStatement pr = conn.prepareStatement(sql);
		// 返回所执行后的结果
		ResultSet rs = pr.executeQuery();
		while (rs.next()) {
			// 将结果集加入实体
			Book book = new Book(rs.getInt(1), rs.getString(2), rs.getFloat(3));
			// 将实体加入list集合
			list.add(book);
		}
		if (list != null) {
			DBAccess.close(conn, pr, rs);
		}
		return list;// 最后返回容器(集合)
	}

	@Test
	public void Text() throws Exception {
		Book book = new Book();
		book.setBname("圣墟");
		PageBean pb = new PageBean();
		List<Book> list = new BookDao().getlist(book, pb);
		for (Book bo : list) {
			System.out.println(bo);
		}
	}

	public List<Book> BaseDaoText(Book book,PageBean pb) throws Exception {
		// 定义sql语句
		String sql = "select * from t_mvc_book where 1=1 ";
		// 当关键词不为空的时候,拼接模糊查询的sql语句
		String bname = book.getBname();
		if (StringUtils.isNotBlank(bname)) {
			sql += "  and bname like '%" + bname + "%'";
		}
		return  executeQuery(sql, book.getClass(), pb);
	}
	
	@Test
	public void Text2() throws Exception {
		Book book = new Book();
		book.setBname("圣墟");
		PageBean pb = new PageBean();
		//测试是否分页
//		pb.setPagination(false);
		//测试显示在页面多少条
//		pb.setRows(20);
		//测试初始页码
//		pb.setPage(2);
		List<Book> list = new BookDao().BaseDaoText(book, pb);
		for (Book bo : list) {
			System.out.println(bo);
		}
	} 

}

4.3 测试结果

1.测试页面只显示20条

 

2.测试初始页面为第2页

3.不进行分页

 

对我们带来什么

JavaEE(Java Enterprise Edition) 通用分页可以帮助我们在开发 JavaEE 项目时更方便地实现数据分页效果,从而提高了用户的体验和系统的性能。通用分页的好处有以下几点:

1. 提高数据的查询效率:随着我们的数据量增加,查询数据的耗时也会越来越长。使用分页后,每次只查询一页的数据,减少了一次查询的数据量,从而减少了查询的耗时,使数据分页的效果更加明显。

2. 提升用户体验:通过数据分页,可以使用户可以更方便快捷地浏览到数据,更好地满足用户的需求,提升用户的体验。

3. 减少服务器压力:在没有使用分页的情况下,每次查询都是全部数据,在数据量大的情况下,我们的服务器压力非常巨大,而使用数据分页后,每次查询只是需要查询一页的数据,减少了服务器的压力,同时也降低了数据传输的开销。

4. 方便管理和维护:使用通用分页,我们可以通过简单的代码对分页进行控制和管理,方便了代码的维护和修改。

5. 提升应用程序性能:在许多情况下,数据分页可以在应用程序中提高性能和响应时间,从而增强了应用程序的性能。

综上所述,JavaEE的通用分页对于JavaEE开发者而言是非常有价值的,它可以从多个方面提高开发效率,优化用户体验,提升系统性能,并降低服务器的负荷,大大提高了软件的开发和使用效率。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值