jQuery DataTables and J2EE web application integration

本文介绍如何使用 jQuery DataTables 插件在 Java Web 应用中实现具备分页、排序和过滤功能的表格。该插件能显著提升表格组件的功能性和用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

This article explains how you can easily implement fully functional tables with pagination, sorting, and filtering in a Java web application. All the required presentation logic is placed in the jQuery plug-in, and the only thing that needs to be implemented is the server side code that provides at

Introduction

While you are implementing tables in Java web applications, probably you are adding several additional features to the table. Pagination is a quite common requirement that is added to the tables with larger number of data; ordering table data by the column is also a frequent requirement. There are a lot of other requirements that are occasionally added to the tables such as filtering by keyword, changing the number of rows that will be shown per page, etc. There are lot of plug-ins that enable all these functionalities - one of them is the jQuery DataTables plug-in that is explained in this article.

The jQuery DataTables plug-in is an excellent client-side component that can be used to create rich-functional tables in a web browser. This plug-in adds a lot of functionalities to plain HTML tables that are placed in web pages, such as filtering, paging, sorting, changing page length, etc. Although, by default it is pure client side, it might be configured to use data from the server via AJAX calls in order to improve performance. However, to integrateDataTables with server-sidecode, the developer must know the protocols and parameters that are sent by DataTables and how to use them on the server side.

This article shows how the jQuery DataTables plug-in can be integrated into Java web applications. It contains step by step examples that show how theDataTables plug-in interacts with server-side components. There are a lot of server-side frameworks in Java such as standardservlets, JSP, JSF, Spring, Struts, etc., and this article will not cover them all. In this article, I will focus on plainservlets to demonstrate how you can create high performance AJAX-based data tables with standard Javaservlets.

Background

The goal of this article is to show how you can implement fully functional, high performance tables using thejQuery DataTables plug-in. This is a JavaScript plug-in implemented using thejQuery library that handles all the necessary interaction with the user on the client-side.

jQuery DataTables is a powerful JavaScript plug-in that automatically adds several functionalities such as dropdown for selecting how much items should be shown per page, text box for filtering results, sorting functionality attached to table headers, and pagination on the bottom of the table. No server-sidecode is required for this as all the functionality is implemented as a set of JavaScript handlers that use data found in HTML. The following figure shows how a plain HTML table looks after applying the DataTables plug-in:

The DataTables plug-in adds a "Show XXX entries" dropdown above the table, enabling the user to choose whether he wants to see 10, 25, 50, or 100 records per page and a search text box that enables the user to filter by keyword records that should be shown in the table. This plug-in also adds sorting functionality that enables the user to sort results by clicking on the column header. Below the table, there is pagination that enables the user to navigate through the pages and text that automatically displays which records are currently displayed. All these functionalities are added by default, and all you need is a single line ofcode:

$('table#myTable').dataTable(); 

In this example, an HTML table with ID "myTable" is found in the DOM of the web page in the browser and the DataTables plug-in is applied in order to add the widgets shown in the previous figure.

In the default mode, there is minimal code required in the Java web application - the web server can generate a plain HTML table in standard format. The client-side JavaScript component will use whatever gets generated and add client-side functionalities. In this client-side mode, DataTables takes all the table rows from the<tbody></tbody> section and performs filtering, paging, and sorting directly on these elements as in in-memory objects. This is the fastest way to use DataTables, but it requires that the server returns all data in a single call, loads all these rows as in-memory JavaScript objects, and render them dynamically in DOM. This might cause performance issues with server call and memory usage on the client. However, this minimizes the number of requests sent to the server because once the table is loaded, the server is not used at all.

On the other hand, it is possible to implement client-server interaction by configuring DataTables to query the server via AJAX calls in order to fetch the required data. In this case, the plug-in will call the server side page, post information about the required data, take the response from the server, and refresh the table. On the DataTables site, there is an example of server-side configuration where thejQuery DataTables plug-in sends requests to a PHP page and gets data that should be shown in the current view. The server response is formatted as aJSON object, parsed on the client side, and displayed in the table body. The following figure shows a trace of the calls sent to the server (captured using the Firebug add-in for Firefox):

jquery-java-xhr.png

In this case, each event (changing the number of items that should be displayed per page, entering keyword in search filter, sorting, pressing pagination button, etc.) triggers the DataTables plug-in to send information about the current page, the search filter, and the sort column to the server page. As shown in the request, the server page returnsJSON as a result and DataTables uses that data array when displaying the current table page. In this mode, instead of taking the complete page at once, several smaller requests are sent whenever new information is required, and minimal amount of data is returned from the server. DataTables, in this example, calls the/CompanyAjaxDataSource URL and sends information about the user action. A full example of the server-side configuration of thejQuery DataTable plug-in can be found here. A major problem with the server-side mode is the implementation of server-side logic that accepts parameters from the client-side component, performs action, and returns data as expected.

This article explains how to configure jQuery DataTables and implement server-side logic with a Javaservlet both in client-side and server-side mode. In your application, you can choose which of these two modes suites you best.

Using the code

This sample shows how you can generate a table of companies and add the jQuery DataTables plug-in to the HTML table. The code is logically organized in the MVC structure:

  1. Model represents classes that contain data and that will be shown in the browser.
  2. Controller is the logic of the application and represent servlets that handle web requests and utility functions.
  3. View are pages that are used to show data to the client - in this example, a JSP and a plain HTML page are used as views.

There is also one utility package containing classes transforming Java objects intoJSON (this is required because thejQuery DataTables plug-in communicates with server-sidecode via JSON objects).

The Model is a Company class that contains the following properties:

  1. Name of the company
  2. Address of the company
  3. Town of the company

In this example, a database or any other datasource is not used, so I have used a class calledDataRepository that contains a hardcoded list of companies. This class returns the companies that will be shown, using the following call:

DataRepository.GetCompanies(); 

In the following sections are presented two major cases of usage of DataTables in Java web applications.

Server-side generated table

As mentioned above, the jQuery DataTables plug-in can be applied on a static HTML structure in the browser. In that case, you will need to generate HTMLcode for the table on the server-side. In this example, I have generated a table structure using a JSP page shown in the listing below:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"
    import="jquery.datatables.model.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>Applying jQuery DataTables plugin in the Java Server application</title>
        <link href="media/dataTables/demo_page.css" rel="stylesheet" type="text/css" />
        <link href="media/dataTables/demo_table.css" rel="stylesheet" type="text/css" />
        <link href="media/dataTables/demo_table_jui.css" rel="stylesheet" type="text/css" />
        <link href="media/themes/base/jquery-ui.css" rel="stylesheet" 
           type="text/css" media="all" />
        <link href="media/themes/smoothness/jquery-ui-1.7.2.custom.css" 
           rel="stylesheet" type="text/css" media="all" />
        <script src="scripts/jquery-1.4.4.min.js"
           type="text/javascript"></script>
        <script src="scripts/jquery.dataTables.min.js" 
           type="text/javascript"></script>
        <script type="text/javascript">
        $(document).ready(function () {
            $("#companies").dataTable({
                "sPaginationType": "full_numbers",
                "bJQueryUI": true
            });
        });
        </script>
    </head>
    <body id="dt_example">
        <div id="container">
            <div id="demo_jui">
                <table id="companies" class="display">
                    <thead>
                        <tr>
                            <th>Company name</th>
                            <th>Address</th>
                            <th>Town</th>
                        </tr>
                    </thead>
                    <tbody>
                      <% for(Company c: DataRepository.GetCompanies()){ %>
                    <tr>
                             <td><%=c.getName()%></td>
                         <td><%=c.getAddress()%></td>
                         <td><%=c.getTown()%></td>
                    </tr>
                <% } %>
                    </tbody>
                </table>
         </div>
        </div> 
    </body>
</html>

In this JSP page is included all the necessary JavaScript libraries, and HTML code for the company table is generated. For demonstration purposes, a simple loop generates aTR for each company that is returned by the repository class. However, in your applications, you can use any server-side processing you want (JavaBeans, JSTL components, etc.) because thejQuery DataTables plug-in is independent of the applied server-side technology.

In the document-ready JavaScript event handler, the plain generated table is enhanced with thejQuery DataTables plug-in. There are two parameters that are passed to the plug-in initialization function (these are two parameters I always use):

  1. sPagination - instructing the plug-in to generate pagination with numbers instead of two previous-next buttons, as is generated by default.
  2. bJQueryUI - applying standardjQueryUI styles.

Instead of the plain HTML table, the following component is shown on the client side:

jqury-ui-java-datatable.png

All actions you see in the component are implemented on the client-side (e.g., when you enter text in the text box,TR elements are filtered). This is the fastest way for the user under the assumption that the time required to load the table is not too big. If you have a huge amount of data, you might consider using DataTables in AJAX mode where only partial results are returned to the plug-in.

AJAX-based table

In AJAX mode, only a minimal amount of data is provided to the plug-in using JSON. The plug-in sends AJAX requests to the server containing information of the current state of the view (current page, filter criterion, page number, etc). The server accepts the AJAX call and determines what information should be shown on the client side and returns a JSON response back to the plug-in. Note that in this case, processing must be implemented on the server side.

In AJAX mode, no relevant information is generated in the view page, therefore it can be even a static HTML page. An example of the HTML page used in this example is shown in the following listing:

<!DOCTYPE html>
<html>
    <head>
        <title>Using jQuery DataTables plugin with AJAX 
           source implemented in Java web application</title>
        <link href="media/dataTables/demo_page.css" 
           rel="stylesheet" type="text/css" />
        <link href="media/dataTables/demo_table.css" 
           rel="stylesheet" type="text/css" />
        <link href="media/dataTables/demo_table_jui.css" 
           rel="stylesheet" type="text/css" />
        <link href="media/themes/base/jquery-ui.css" 
          rel="stylesheet" type="text/css" media="all" />
        <link href="media/themes/smoothness/jquery-ui-1.7.2.custom.css" 
          rel="stylesheet" type="text/css" media="all" />
        <script src="scripts/jquery-1.4.4.min.js" 
          type="text/javascript"></script>
        <script src="scripts/jquery.dataTables.min.js" 
          type="text/javascript"></script>
        <script type="text/javascript">
        $(document).ready(function () {
            $("#companies").dataTable({
                "bServerSide": true,
                "sAjaxSource": "/JQueryDataTables/CompanyAjaxDataSource",
                "bProcessing": true,
                "sPaginationType": "full_numbers",
                "bJQueryUI": true
            });
        });
        </script>
    </head>
    <body id="dt_example">
        <div id="container">
            <div id="demo_jui">
        <table id="companies" class="display">
              <thead>
                  <tr>
                       <th>Company name</th>
                       <th>Address</th>
                       <th>Town</th>
                  </tr>
              </thead>
              <tbody>
              </tbody>
        </table>
        </div>
        </div>
    </body>
</html> 

As you can see, the table body is completely empty because the jQuery DataTables plug-in will be populated using the AJAX call. In the document ready event, DataTables is initialized with three additional parameters:

  • bServerSide that instructs DataTables plug-in to take information from the server-side
  • sAjaxSource that defines that URL that should be called by the plug-in to take the data
  • bProcessing (optional) used to show the "Processing" message while the AJAX call is executing

The key part of the server-side code is the component that will provide data to thejQuery DataTables plugin - in this case, this is the component on the server-side that reacts when thesAjaxSource page is called. This can be anything:servlet, JSP page, or any server-sidecode that returns a JSON response based on the parameters sent from the plug-in. ThejQuery DataTables plug-in sends a lot of parameters to the server-side; you can find a detailed documentation on theDataTables site, but here are the most important ones:

  • sEcho - Integer value that is used by DataTables for synchronization purpose. Response from the server-sidecode should return the same value to the plug-in.
  • sKeyword - Text entered in the filter text box and it should be used for filtering records.
  • iDisplayStart - Dirst record that should be shown (used for pagination).
  • iDisplayLength - The number of records that should be returned (this value is equal to the value selected in the 'ShowXXXitems per page' dropdown). This value is also used for pagination.
  • iColumns - The number of columns in the table.
  • iSortingCols - The number of columns used for ordering. Usually this value is 1, but if the user orders results by more than one column (holding the SHIFT key while clicking on the header cells), the DataTables plug-in will send information about the number of columns you should use for ordering results.
  • iSortCol_0, iSortCol_1, iSortCol_2, etc. - The IDs of the columns used for ordering results. If results are ordered by one column, you should order results by theiSortCol_0 column.
  • sSortDir_0, sSortDir_1, sSortDir_2, etc. - The sort direction for each of the columns used for ordering. If results are ordered by one column, an "asc" or "desc" value will be returned in thesSortDir_0 parameter. In the case of multi-column ordering, each parameter in this array will have a direction that matches the column in theiSortCol_ parameter.

The server-side component should have the GET method handler that will be called when the plug-in sends an AJAX request. This method should take the parameters described above, process data, and prepare values that will be sent to the plug-in. An example of the response that is returned back from the servlet is shown in the example below:

{  "sEcho":"1",
    "iTotalRecords":97,
    "iTotalDisplayRecords":3,
    "aaData":[    ["1","a1","a2","a3"],
                  ["2","b1","b2","b3"],
                  ["3","c1","c2","c3"]
        ]
}

Values that the server returns to the DataTables plug-in are:

  • sEcho - An integer value that is used by DataTables for synchronization purposes. On each call sent to the server-side page, the DataTables plug-in sends the sequence number in thesEcho parameter. The same value has to be returned in the response because DataTables uses this for synchronization and matching requests and responses.
  • iTotalRecords - The integer value that represents the total unfiltered number of records that exist on the server-side and that might be displayed if no filter is applied. This value is used only for display purposes; when the user types in a keyword in the search text box, DataTables shows a "Showing 1 to 10 of 23 entries (filtered from 51 total entries)" message. In this case, theiTotalRecords value returned in the response equals 51.
  • iTotalDisplayedRecords - The integer value that represents the number of records that match the current filter. If the user does not enter any value in the search text box, this value should be the same as theiTotalRecords value. The DataTables plug-in uses this value to determine how many pages will be required to generate pagination - if this value is less or equal than the current page size, the pagination buttons will be disabled. When the user types in A keyword in the search text box, DataTables shows a "Showing 1 to 10 of 23 entries (filtered from 51 total entries)" message. In this case, theiTotalDisplayedRecords value returned in the response equals 23.
  • aaData - A two-dimensional array that represents the cell values that will be shown in the table. When DataTables receives data, it will populate the table cells with values from theaaData array. The number of columns in the two dimensional array must match the number of columns in the HTML table (even the hidden ones), and the number of rows should be equal to the number of items that can be shown on the current page (e.g., 10, 25, 50, or 100 - this value is selected in the "Show XXX entries" dropdown).
Code example - Servlet with server-side processing functionalities

Any Java server-side component that accepts the parameters described above and returns the expectedJSON result can be used. In this example, a plainservlet is used for demonstration purposes, but you can use any other component. Theservlet used in this example has adoGet method that accepts parameters and returns aJSON object. The following listing shows an example of the get method:

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
               throws ServletException, IOException {
    JQueryDataTableParamModel param = DataTablesParamUtility.getParam(request);    
    String sEcho = param.sEcho;
    int iTotalRecords; // total number of records (unfiltered)
    int iTotalDisplayRecords;//value will be set when code filters companies by keyword
    JSONArray data = new JSONArray(); //data that will be shown in the table
    //Filtering companies
    //Ordering companies
    //Pagination
    //Generate JSON response
}

The servlet is mapped on the /CompanyAjaxDataSource URL and the get method takes parameters sent by the plug-in. For this purpose, we have added two utility classes:JQueryDataTableParamModel containing the properties that are sent by the plug-in, andDataTablesParamUtility that loads the values of theJQueryDataTableParamModel from the request. Also, in this part ofcode, values that will be sent to the plug-in are prepared. The actualcode that populates properties from the request is omitted, but you can find thecode in thecode example. Note that properties in this class have the same names as the parameters sent by the plug-in so you can easily follow thecode.

The first action that needs to be done on the server-side is filtering of companies by the keyword provided by the plug-in. Thiscode is shown in the listing below:

iTotalRecords = DataRepository.GetCompanies().size();
List<Company> companies = new LinkedList<Company>();
for(Company c : DataRepository.GetCompanies()){
    if(    c.getName().toLowerCase().contains(param.sSearch.toLowerCase())
                ||
        c.getAddress().toLowerCase().contains(param.sSearch.toLowerCase())
                ||
        c.getTown().toLowerCase().contains(param.sSearch.toLowerCase()))
    {
        companies.add(c); // Add a company that matches search criterion
    }
}
iTotalDisplayRecords = companies.size();
//Number of companies that matches search criterion should be returned

The keyword entered in the filter text box is placed in the param.sSearch string. In this example,iTotalRecords is set to the total number of companies that are in the list, a search is performed by the company properties, and a new list of filtered companies that contains the keyword are added in the list. The number of filtered companies is placed in theiTotalDisplayRecords variable. In the second part of thecode, companies are ordered by the column. The followingcode shows ordering done using the index of the column that should be sorted and the direction. On the server-sidecode, you will need to know what column indexes match properties in theCompany class.

final int sortColumnIndex = param.iSortColumnIndex;
final int sortDirection = param.sSortDirection.equals("asc") ? -1 : 1;

Collections.sort(companies, new Comparator<Company>(){
    @Override
    public int compare(Company c1, Company c2) {    
        switch(sortColumnIndex){
        case 0:
            return c1.getName().compareTo(c2.getName()) * sortDirection;
        case 1:
            return c1.getAddress().compareTo(c2.getAddress()) * sortDirection;
        case 2:
            return c1.getTown().compareTo(c2.getTown()) * sortDirection;
        }
        return 0;
    }
});

This is a simplified case where it is assumed that ordering is done by one single column and that index of the column that will be used for sorting and the direction are placed in theparam.iSortColumIndex andparam.sSortDirection properties.

The last functionality that should be implement is pagination. The current page and the length are placed in theiDisplayStart andiDisplayLength properties, and these properties are used to get the sub list that should be returned to the plug-in. An example is shown in the following listing:

if(companies.size()< param.iDisplayStart + param.iDisplayLength)
    companies = companies.subList(param.iDisplayStart, companies.size());
else
    companies = companies.subList(param.iDisplayStart, 
                   param.iDisplayStart + param.iDisplayLength);

When the list is prepared, a JSON object that represents the response should be created. Thecode for creating theJSON response is:

try {
    JSONObject jsonResponse = new JSONObject();
    
    jsonResponse.put("sEcho", sEcho);
    jsonResponse.put("iTotalRecords", iTotalRecords);
    jsonResponse.put("iTotalDisplayRecords", iTotalDisplayRecords);
    
    for(Company c : companies){
        JSONArray row = new JSONArray();
        row.put(c.getName()).put(c.getAddress()).put(c.getTown());
        data.put(row);
    }
    jsonResponse.put("aaData", data);
    
    response.setContentType("application/json");
    response.getWriter().print(jsonResponse.toString());
} catch (JSONException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    response.setContentType("text/html");
    response.getWriter().print(e.getMessage());
}

This example has the echo, total records, and total filtered records properties. Also, the data properties have the matrix containing the name, address, and town information. When this object is returned to the plug-in, filtered information is shown in the table on the client side.

In this example, processing is done in the plain source code; however, in your application, you can use other methods such as SQL, Stored Procedures, HQL, etc. The only important thing is that you returnJSON response with objects that match the current state on the table.

Conclusion

This example shows how you can create effective, fully functional tables in a Java web application using thejQuery DataTables plug-in. Using thecode examples in the article, you can significantly enhance the look and functionalities of your web application. I recommend that you try it - when you integratejQuery DataTables in a few tables in your application, you will see that the implementation is straightforward and that you will be, with some practice, able to implement a lot of functionalities with very little effort.

You can download the code example in the attached project that was created in the Eclipse Java EE IDE for Web Developers, that runs on a Tomcat 7.0 web server. If you have the same configuration, you can run and try this project, and if you have any other development environment, I suggest you create a new project, configure it, and add classes that you can find in the project. I hope that this example will help you to create better table interfaces.

If you are interested in adding full Web 2.0 CRUD functionalities to the JQuery DataTable, I recommend another article Adding data management (CRUD) functionalities to web tables, where I have exlplained how you can configure plugin to automaticaly add inline editing, deleting, and adding new records functionalities to theJQuery DataTables plugin.


基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值