Java Servlet 分页

Java servlet 分页教程展示了如何使用 Java servlet 进行分页。在示例中,Bootstrap 用于 UI。

分页

分页是将内容分成多个页面的过程。用户有一个导航界面,用于通过特定页面链接访问这些页面。导航通常包括上一个/下一个和第一个/最后一个链接。当数据库中有大量数据或一页中有很多评论要显示时,使用分页。

Java Servlet程序

Servlet是一个 Java 类,它响应特定类型的网络请求——最常见的是 HTTP 请求。Java servlet 用于创建 Web 应用程序。它们在 Tomcat 或 Jetty 等 servlet 容器中运行。现代 Java Web 开发使用构建在 servlet 之上的框架。

Bootstrap

Bootstrap 是来自 Twitter 的 UI 库,用于创建响应式、移动优先的 Web 应用程序。

Java Servlet 分页示例

在以下 Web 应用程序中,我们从 MySQL 数据库加载数据并将其显示在表格中。有一个导航系统可以检查数据库表中的所有数据。在数据显示在表格中之前,用户可以选择表格将显示多少行。Web 应用程序部署在 Jetty 服务器上。

注意:为了使应用程序更易于访问,一些功能(包括数据验证或数据库连接池)已被省略。

除了从数据库表中获取数据外,我们还需要知道数据库表中的所有行数、每页的记录数以及要在导航中显示的页数。数据库中所有行的数量由一条 SQL 语句计算出来。每页的记录数由用户在 HTML 表单中选择。最后,根据其他两个值计算分页中的页数。

country_mysql.sql
CREATE TABLE countries(id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255), population INT);

INSERT INTO countries(name, population) VALUES('China', 1382050000);
INSERT INTO countries(name, population) VALUES('India', 1313210000);
INSERT INTO countries(name, population) VALUES('USA', 324666000);
INSERT INTO countries(name, population) VALUES('Indonesia', 260581000);
INSERT INTO countries(name, population) VALUES('Brazil', 207221000);
INSERT INTO countries(name, population) VALUES('Pakistan', 196626000);
INSERT INTO countries(name, population) VALUES('Nigeria', 186988000);
INSERT INTO countries(name, population) VALUES('Bangladesh', 162099000);
INSERT INTO countries(name, population) VALUES('Nigeria', 186988000);
INSERT INTO countries(name, population) VALUES('Russia', 146838000);
INSERT INTO countries(name, population) VALUES('Japan', 126830000);
INSERT INTO countries(name, population) VALUES('Mexico', 122273000);
INSERT INTO countries(name, population) VALUES('Philippines', 103738000);
INSERT INTO countries(name, population) VALUES('Ethiopia', 101853000);
INSERT INTO countries(name, population) VALUES('Vietnam', 92700000);
INSERT INTO countries(name, population) VALUES('Egypt', 92641000);
INSERT INTO countries(name, population) VALUES('Germany', 82800000);
INSERT INTO countries(name, population) VALUES('the Congo', 82243000);
INSERT INTO countries(name, population) VALUES('Iran', 82800000);
INSERT INTO countries(name, population) VALUES('Turkey', 79814000);
INSERT INTO countries(name, population) VALUES('Thailand', 68147000);
INSERT INTO countries(name, population) VALUES('France', 66984000);
INSERT INTO countries(name, population) VALUES('United Kingdom', 60589000);
INSERT INTO countries(name, population) VALUES('South Africa', 55908000);
INSERT INTO countries(name, population) VALUES('Myanmar', 51446000);
INSERT INTO countries(name, population) VALUES('South Korea', 68147000);
INSERT INTO countries(name, population) VALUES('Colombia', 49129000);
INSERT INTO countries(name, population) VALUES('Kenya', 47251000);
INSERT INTO countries(name, population) VALUES('Spain', 46812000);
INSERT INTO countries(name, population) VALUES('Argentina', 43850000);
INSERT INTO countries(name, population) VALUES('Ukraine', 42603000);
INSERT INTO countries(name, population) VALUES('Sudan', 41176000);
INSERT INTO countries(name, population) VALUES('Algeria', 40400000);
INSERT INTO countries(name, population) VALUES('Poland', 38439000);

此 SQL 脚本countries在 MySQL 中创建表。

pom.xml
src
├── main
│   ├── java
│   │   └── com
│   │       └── zetcode
│   │           ├── model
│   │           │   └── Country.java
│   │           ├── service
│   │           │   ├── CountryService.java
│   │           │   └── ICountryService.java
│   │           └── web
│   │               └── ReadCountries.java
│   ├── resources
│   └── webapp
│       ├── index.html
│       └── listCountries.jsp
└── test
    └── java

这是项目结构。

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>PaginationEx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.0</version>
            </plugin>

            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.30.v20200611</version>
            </plugin>
        </plugins>
    </build>

</project>

这是 Maven POM 文件。该javax.servlet-api工件用于 servlet。该spring-jdbc依赖项用于 JdbcTemplate 库,它简化了 Java 中的数据库编程。这mysql-connector-java 是Java语言的MySQL驱动程序。该jstl依赖项为 JSP 页面提供了一些附加功能。

maven-war-plugin负责收集 Web 应用程序的所有工件依赖项、类和资源,并将它们打包到 Web 应用程序存档 (WAR) 中 。这jetty-maven-plugin是一个有用的 Maven 插件,用于快速开发和测试。它创建一个 Web 应用程序,启动一个 Jetty Web 服务器,并在服务器上部署该应用程序。

com/zetcode/model/Country.java
package com.zetcode.model;

import java.util.Objects;

public class Country {

    private String name;
    private int population;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Country country = (Country) o;
        return population == country.population
                && Objects.equals(name, country.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, population);
    }
}

bean 保存数据库表中 的Country一行 。countries

com/zetcode/web/ReadCountries.java
package com.zetcode.web;

import com.zetcode.model.Country;
import com.zetcode.service.CountryService;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "ReadCountries", urlPatterns = {"/ReadCountries"})
public class ReadCountries extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");

        int currentPage = Integer.parseInt(request.getParameter("currentPage"));
        int recordsPerPage = Integer.parseInt(request.getParameter("recordsPerPage"));

        CountryService countryService = new CountryService();

        List<Country> countries = countryService.findCountries(currentPage,
                recordsPerPage);

        request.setAttribute("countries", countries);

        int rows = countryService.getNumberOfRows();

        int nOfPages = rows / recordsPerPage;

        if (nOfPages % recordsPerPage > 0) {

            nOfPages++;
        }

        request.setAttribute("noOfPages", nOfPages);
        request.setAttribute("currentPage", currentPage);
        request.setAttribute("recordsPerPage", recordsPerPage);

        RequestDispatcher dispatcher = request.getRequestDispatcher("listCountries.jsp");
        dispatcher.forward(request, response);
    }
}

ReadCountriesservlet 确定将从请求属性中检索多少数据并从数据库表中读取指定数量的行 。

@WebServlet(name = "ReadCountries", urlPatterns = {"/ReadCountries"})

Java 类是用@WebServlet注解修饰的。它映射到ReadCountriesURL 模式。

response.setContentType("text/html;charset=UTF-8");

servlet 将以 HTML 格式输出数据,并且数据的编码设置为 UTF-8。

int currentPage = Integer.parseInt(request.getParameter("currentPage"));
int recordsPerPage = Integer.parseInt(request.getParameter("recordsPerPage"));

从请求中我们得到两个重要的值:当前页面和每页的记录数。(跳过对值的验证。)

var countryService = new CountryService();

List<Country> countries = countryService.findCountries(currentPage,
        recordsPerPage);

request.setAttribute("countries", countries);

CountryService是用于连接数据库和读取数据的服务类。检索国家列表并将其设置为请求的属性。稍后将由目标 JSP 页面使用。

int rows = countryService.getNumberOfRows();

int nOfPages = rows / recordsPerPage;

if (nOfPages % recordsPerPage > 0) {
    nOfPages++;
}

getNumberOfRows我们使用service 方法 从数据库表中获取所有行的数量 。我们计算导航中的页面数。

request.setAttribute("noOfPages", nOfPages);
request.setAttribute("currentPage", currentPage);
request.setAttribute("recordsPerPage", recordsPerPage);

页数、当前页数和每页记录数是我们构建分页所需的值。

var dispatcher = request.getRequestDispatcher("listCountries.jsp");
dispatcher.forward(request, response);

处理被转发到listCountries.jsp页面。

com/zetcode/service/ICountryService.java
package com.zetcode.service;

import com.zetcode.model.Country;
import java.util.List;

public interface ICountryService {

    List<Country> findCountries(int currentPage, int numOfRecords);

    Integer getNumberOfRows();
}

ICountryService包含两种合约方法 :findCountries 和getNumberOfRows.

com/zetcode/service/CountryService.java
package com.zetcode.service;

import com.zetcode.model.Country;
import java.sql.SQLException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

public class CountryService implements ICountryService {

    @Override
    public List<Country> findCountries(int currentPage, int recordsPerPage) {

        List<Country> countries = null;

        int start = currentPage * recordsPerPage - recordsPerPage;

        try {
            String sql = "SELECT * FROM countries LIMIT ?, ?";

            SimpleDriverDataSource ds = new SimpleDriverDataSource();
            ds.setDriver(new com.mysql.jdbc.Driver());
            ds.setUrl("jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC");
            ds.setUsername("root");
            ds.setPassword("root");

            JdbcTemplate jtm = new JdbcTemplate(ds);
            countries = jtm.query(sql, new Object[]{start, recordsPerPage},
                    new BeanPropertyRowMapper<>(Country.class));

        } catch (SQLException ex) {
            Logger.getLogger(CountryService.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return countries;
    }

    @Override
    public Integer getNumberOfRows() {

        Integer numOfRows = 0;

        try {
            String sql = "SELECT COUNT(id) FROM countries";

            SimpleDriverDataSource ds = new SimpleDriverDataSource();
            ds.setDriver(new com.mysql.jdbc.Driver());
            ds.setUrl("jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC");
            ds.setUsername("root");
            ds.setPassword("root");

            JdbcTemplate jtm = new JdbcTemplate(ds);
            numOfRows = jtm.queryForObject(sql, Integer.class);

        } catch (SQLException ex) {
            Logger.getLogger(CountryService.class.getName()).log(Level.SEVERE,
                    null, ex);
        }

        return numOfRows;
    }
}

包含两种合约方法的CountryService实现。

String sql = "SELECT * FROM countries LIMIT ?, ?";

SQL LIMIT 子句用于获取当前页面的行数。

var jtm = new JdbcTemplate(ds);
countries = jtm.query(sql, new Object[] {start, recordsPerPage},
        new BeanPropertyRowMapper(Country.class));

JdbcTemplate用于执行 SQL 语句。在. Country_BeanPropertyRowMapper

String sql = "SELECT COUNT(id) FROM countries";

使用这个 SQL 语句,我们从数据库表中获取行数。

webapp/index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Home page</title>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
              integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
              crossorigin="anonymous">
    </head>

    <body>

        <main class="m-3">

            <h1>Show countries</h1>

            <form action="ReadCountries">

                <input type="hidden" name="currentPage" value="1">

                <div class="form-group col-md-4">

                    <label for="records">Select records per page:</label>

                    <select class="form-control" id="records" name="recordsPerPage">
                        <option value="5">5</option>
                        <option value="10" selected>10</option>
                        <option value="15">15</option>
                    </select>

                </div>

                <button type="submit" class="btn btn-primary">Submit</button>

            </form>
        </main>

    </body>
</html>

这是主页。select它包含一个 HTML 表单,用于选择带有标签的每页记录数。该表单使用来自 Bootstrap 库的样式类。提交表单后,处理被发送到ReadCountriesservlet。

<input type="hidden" name="currentPage" value="1">

该表单包含一个隐藏input标签,该标签将currentPage 参数设置为 1。

<select class="form-control" id="records" name="recordsPerPage">
    <option value="5">5</option>
    <option value="10" selected>10</option>
    <option value="15">15</option>
</select>

select标签允许每页选择 5、10 或 15 条记录 。

<button type="submit" class="btn btn-primary">Submit</button>

提交按钮执行表单。

webapp/listCountries.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Countries</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
              integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
              crossorigin="anonymous">
    </head>

    <body>

        <main class="m-3">
            <div class="row col-md-6">
                <table class="table table-striped table-bordered table-sm">
                    <tr>
                        <th>Name</th>
                        <th>Population</th>
                    </tr>

                    <c:forEach items="${countries}" var="country">
                        <tr>
                            <td>${country.getName()}</td>
                            <td>${country.getPopulation()}</td>
                        </tr>
                    </c:forEach>
                </table>
            </div>

            <nav aria-label="Navigation for countries">
                <ul class="pagination">
                    <c:if test="${currentPage != 1}">
                        <li class="page-item"><a class="page-link"
                                                 href="ReadCountries?recordsPerPage=${recordsPerPage}&currentPage=${currentPage-1}">Previous</a>
                        </li>
                    </c:if>

                    <c:forEach begin="1" end="${noOfPages}" var="i">
                        <c:choose>
                            <c:when test="${currentPage eq i}">
                                <li class="page-item active"><a class="page-link">
                                        ${i} <span class="sr-only">(current)</span></a>
                                </li>
                            </c:when>
                            <c:otherwise>
                                <li class="page-item"><a class="page-link"
                                                         href="ReadCountries?recordsPerPage=${recordsPerPage}&currentPage=${i}">${i}</a>
                                </li>
                            </c:otherwise>
                        </c:choose>
                    </c:forEach>

                    <c:if test="${currentPage lt noOfPages}">
                        <li class="page-item"><a class="page-link"
                                                 href="ReadCountries?recordsPerPage=${recordsPerPage}&currentPage=${currentPage+1}">Next</a>
                        </li>
                    </c:if>
                </ul>
            </nav>
        </main>

    </body>
</html>

显示表格中的listCountries.jsp数据和分页系统。Bootstrap 用于使 UI 响应良好并看起来不错。

<table class="table table-striped table-bordered table-sm">

tabletable-striped,都是 Bootstrap 类 table-bordered。 table-sm

<c:forEach items="${countries}" var="country">
    <tr>
        <td>${country.getName()}</td>
        <td>${country.getPopulation()}</td>
    </tr>
</c:forEach>

使用 JSTL 的forEach标签,我们显示当前页面的所有数据。

<c:if test="${currentPage != 1}">
    <li class="page-item"><a class="page-link"
        href="ReadCountries?recordsPerPage=${recordsPerPage}&currentPage=${currentPage-1}">Previous</a>
    </li>
</c:if>

使用c:if标签,我们只在有一个时显示上一个链接。在链接中,我们将recordsPerPagecurrentPage值传递给请求对象。

<c:forEach begin="1" end="${noOfPages}" var="i">
    <c:choose>
        <c:when test="${currentPage eq i}">
            <li class="page-item active"><a class="page-link">
                    ${i} <span class="sr-only">(current)</span></a>
            </li>
        </c:when>
        <c:otherwise>
            <li class="page-item"><a class="page-link"
                href="ReadCountries?recordsPerPage=${recordsPerPage}&currentPage=${i}">${i}</a>
            </li>
        </c:otherwise>
    </c:choose>
</c:forEach>

使用forEach标签,我们显示所有页面链接。

$ mvn jetty:run

我们运行 Jetty 服务器并导航到localhost:8080.

图:Java Servlet 分页

该示例显示了一个填充有数据的表格和分页系统。当前选择的页面被突出显示。

在本教程中,我们展示了如何使用 Java Servlet 在 Web 应用程序中创建分页系统。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单从表现层来说分页不是一个复杂的工作,稍微理一下思路,处于不同competence level的同学应该都能自己搞出来。 以上面的文章列表分页为例,我觉得分页有两点重要的, 一是:分页我们必须首先自己搞清楚,文章总数、每页显示文章数(页大小)、页数 二是:如何做好页脚的分页导航条 实际应用中,文章总数这个值我们从数据库可以得到;每页显示的文章数即分页的页大小可以自己定义;页数我们可以通过下面的个表达式简单得出。 假设: int pageSize = 10; //分页大小 int totalPosts = PagingDAO.entryList.size(); //总文章数 int totalPages = totalPosts/pageSize + ((totalPosts%pageSize)>0?1:0); //计算得出的总页数 每页的文章怎么取出来? 知道分页的大小之后,我们生成了页好的选取下拉框,每次选择第几页的时候,都会向Servlet传递当前选择页号的参数,这样Servlet调用后面的DAO相应的方法,取得文章列表信息,再回传到JSP以供显示。 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> page Size : ${pageSize} <br /> Total Posts: ${totalPosts} <br /> Total Pages: ${totalPages} <br /> Current Page: ${pageNumber} <hr /> <table> <thead> <tr align="center"> <td width="10%">Article ID</td> <td width="70%">Article Title</td> <td colspan="3">Actions</td> </tr> </thead> <tbody> <c:forEach items="${entryList}" var="entry"> <tr align="center"> <td>${entry.entryID}</td> <td>${entry.title}</td> <td><a href="viewEntry?entryID=${entry.entryID}">View</a></td> <td><a href="editEntry?entryID=${entry.entryID}">Edit</a></td> <td><a href="deleteEntry?entryID=${entry.entryID}">Delete</a></td> </tr> </c:forEach> </tbody> <tfoot> <tr align="center"> <td colspan="5"> <jsp:include page="paging_footer.jsp"></jsp:include> </td> </tr> </tfoot> </table> <hr/>
以下是使用Servlet实现分页删除的示例代码,该代码使用MySQL数据库和JSP页面: JSP页面(list.jsp): ```jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>用户列表</title> </head> <body> <h1>用户列表</h1> <table> <tr> <th>ID</th> <th>姓名</th> <th>年龄</th> <th>操作</th> </tr> <c:forEach items="${users}" var="user"> <tr> <td>${user.id}</td> <td>${user.name}</td> <td>${user.age}</td> <td> <form method="post" action="delete"> <input type="hidden" name="id" value="${user.id}"> <input type="submit" value="删除"> </form> </td> </tr> </c:forEach> </table> <div> <c:if test="${page > 1}"> <a href="?page=${page - 1}"><上一页</a> </c:if> <c:if test="${page < totalPage}"> <a href="?page=${page + 1}">下一页></a> </c:if> </div> </body> </html> ``` Servlet代码(ListServlet.java): ```java import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/list") public class ListServlet extends HttpServlet { private static final long serialVersionUID = 1L; private UserDao userDao = new UserDaoImpl(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int page; try { page = Integer.parseInt(request.getParameter("page")); } catch (NumberFormatException e) { page = 1; } int pageSize = 10; int offset = (page - 1) * pageSize; int totalRecords = userDao.countAll(); int totalPage = (int) Math.ceil((double) totalRecords / pageSize); List<User> users = userDao.findAll(offset, pageSize); request.setAttribute("users", users); request.setAttribute("page", page); request.setAttribute("totalPage", totalPage); request.getRequestDispatcher("list.jsp").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int id = Integer.parseInt(request.getParameter("id")); userDao.delete(id); response.sendRedirect("list"); } } ``` 在上述代码中,我们首先获取当前页码并计算偏移量和总记录数。然后,我们查询当前页的记录并将它们存储在请求属性中。接下来,我们将页码和总页数也存储在请求属性中,并将请求转发到JSP页面进行显示。最后,我们处理删除操作,并将用户重定向到用户列表页面。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值