SpringBoot actual development background management - architecture description and development

Posted by Dlex on Tue, 04 Jan 2022 14:51:10 +0100

SpringBoot actual development background management - architecture description and development

1. Architecture mode

  • Monomer architecture

  • technical structure

  • springboot + mybatisplus + mysql

  • Front end technology: jquery / layui

  • Font Icon Library: iconfont

2. What are the architectural patterns of background development?

  • Pure enterprise development (all internal design of the company, backstage page and function control, animation, js and css preparation)
  • Use some open source development patterns (layui, bootstrap, jui, extjs), etc. What are the benefits? Fast and convenient, which provides a large number of components and modules. For example: date component, table, form, button, pop-up window, etc. 95%.
  • New background development modes: Vue admin element, elementui, antd, etc. are all front-end and back-end separated architecture modes based on Vue client architecture. (95%)

3. Rendering of menu navigation developed in the background

There are three modes of comparing programs:

1. Iframe based (compare traditional asynchronous + dynamic page rendering)

2. Pure asynchronous (js is used for dynamic splicing and rendering) (compared with traditional asynchronous + dynamic page rendering)

3. Based on route jump (vue scaffold) - vue router

4. Rendering problems with menu navigation

First, manage and control the navigation bar

Thinking: navigation needs to exist in every page, so we can split the public part with the technology contained in the page, and then import it in each page with the defined syntax. that will do

The advantage is that it is convenient for us to unify maintenance and subsequent upgrade and control.

There are such technologies included in freemaker or jsp or thymeleaf. Take thymeleaf as an example:

Create a new common and leftnav The html is as follows

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <body>
        <aside id="asideapp" th:fragment="asidebar"
               class="byte-layout-sider byte-layout-sider-light mp-main-sider animated fadeInLeft"
               style="width: 246px;">
            <div class="byte-layout-sider-children">
                <div class="mp-menu-wrapper f-min-scroll f-hover-scroll mp-menu-wrapper-can-scroll">
                    <div class="byte-menu garr-menu">
                        <div class="byte-menu-inline  base_creation_tab">
                            <div class="byte-menu-inline-header">
                                <a href="/admin/index" class="">
                                    <span style="padding-left: 0px; display: block;">
                                        <span title="Console" class="ksd-icon-sp iconfont fz20 mr-2 iconhome"></span>
                                        <span>Console</span>
                                    </span>
                                </a>
                            </div>
                            <div class="byte-menu-inline-content animated fadeIn"
                                 style="height: auto; display: none;"></div>
                        </div>
                        <div class="byte-menu-inline  base_creation_tab">
                            <div class="byte-menu-inline-header">
                                <a href="javascript:void(0);" class="">
                                    <span style="padding-left: 0px;">
                                        <span title="user management " class="ksd-icon-sp iconfont fz20 mr-2 iconiconzh1"></span>
                                        <span>user management </span>
                                    </span>
                                    <span class="byte-menu-icon-suffix">
                                        <svg viewBox="0 0 1024 1024" width="1em" height="1em" fill="currentColor" class="byte-icon byte-icon-down">
                                            <path d="M512 613.12L858.88 265.6a21.12 21.12 0 0130.08 0l30.08 30.72a21.12 21.12 0 010 30.08L542.08 704a42.24 42.24 0 01-60.16 0L104.96 326.4a21.12 21.12 0 010-30.08l30.08-30.72a21.12 21.12 0 0130.08 0z"></path>
                                        </svg>
                                    </span>
                                </a>
                            </div>
                            <div class="byte-menu-inline-content animated fadeIn" style="display: block;">
                                <div title="user management " data-href="/admin/user/list" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconiconzh1"></span>
                                        <a href="javascript:void(0);">user management </a>
                                    </span>
                                </div>
                                <div title="Statistical module" data-href="/admin/state/list" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconiconzh1"></span>
                                        <a href="javascript:void(0);">Statistical module</a>
                                    </span>
                                </div>
                            </div>
                        </div>

                        <div class="byte-menu-inline  base_creation_tab">
                            <div class="byte-menu-inline-header">
                                <a href="javascript:void(0);" class="">
                                    <span style="padding-left: 0px; display: block;">
                                        <span title="Role management" class="ksd-icon-sp iconfont fz20 mr-2 iconorder1"></span>
                                        <span>Notification management</span>
                                    </span>
                                    <span class="byte-menu-icon-suffix is-open">
                                        <svg viewBox="0 0 1024 1024" width="1em" height="1em" fill="currentColor" class="byte-icon byte-icon-down">
                                            <path d="M512 613.12L858.88 265.6a21.12 21.12 0 0130.08 0l30.08 30.72a21.12 21.12 0 010 30.08L542.08 704a42.24 42.24 0 01-60.16 0L104.96 326.4a21.12 21.12 0 010-30.08l30.08-30.72a21.12 21.12 0 0130.08 0z"></path>
                                        </svg>
                                    </span>
                                </a>
                            </div>
                            <div class="byte-menu-inline-content animated fadeIn"
                                 style="height: auto; display: none;">
                                <div title="Role list" data-href="/admin/permission/list" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconorder1"></span>
                                        <a href="javascript:void(0);">Role list</a>
                                    </span>
                                </div>
                                <div title="Permission list" data-href="/admin/role/list" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconorder1"></span>
                                        <a href="javascript:void(0);">Permission list</a>
                                    </span>
                                </div>
                                <div title="System notification" data-href="/admin/notice/system" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconorder1"></span>
                                        <a href="javascript:void(0);">System notification</a>
                                    </span>
                                </div>
                                <div title="Course notice" data-href="/admin/notice/course" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconorder1"></span>
                                        <a href="javascript:void(0);">Course notice</a>
                                    </span>
                                </div>
                            </div>
                        </div>
                        <div class="byte-menu-inline  base_creation_tab">
                            <div class="byte-menu-inline-header">
                                <a href="javascript:void(0);" class="">
                                    <span style="padding-left: 0px; display: block;">
                                        <span title="system management" class="ksd-icon-sp iconfont fz20 mr-2 iconshangjia2"></span>
                                        <span>system management</span>
                                    </span>
                                    <span class="byte-menu-icon-suffix is-open">
                                        <svg viewBox="0 0 1024 1024" width="1em" height="1em" fill="currentColor" class="byte-icon byte-icon-down">
                                            <path d="M512 613.12L858.88 265.6a21.12 21.12 0 0130.08 0l30.08 30.72a21.12 21.12 0 010 30.08L542.08 704a42.24 42.24 0 01-60.16 0L104.96 326.4a21.12 21.12 0 010-30.08l30.08-30.72a21.12 21.12 0 0130.08 0z"></path>
                                        </svg>
                                    </span>
                                </a>
                            </div>
                            <div class="byte-menu-inline-content animated fadeIn" style="height: auto; display: none;">
                                <div title="Digital account generation" data-href="/admin/system/userNum" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconshangjia2"></span>
                                        <a href="javascript:void(0);">Digital account generation</a>
                                    </span>
                                </div>
                                <div title="Navigation friend chain management" data-href="/admin/system/friendLink" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconshangjia2"></span>
                                        <a href="javascript:void(0);">Navigation friend chain management</a>
                                    </span>
                                </div>
                                <div title="Member price management" data-href="/admin/system/vipPrice" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconshangjia2"></span>
                                        <a href="javascript:void(0);">Member price management</a>
                                    </span>
                                </div>
                                <div title="SEO Administration" data-href="/admin/system/seo" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconshangjia2"></span>
                                        <a href="javascript:void(0);">SEO Administration</a>
                                    </span>
                                </div>
                                <div title="Site settings" data-href="/admin/system/params" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconshangjia2"></span>
                                        <a href="javascript:void(0);">Site settings</a>
                                        <span title="To be completed" class="layui-badge-dot" style="position: absolute; top: 12px; right: 50px;"></span>
                                    </span>
                                </div>
                                <div title="OSS Administration" data-href="/admin/system/oss" class="byte-menu-item">
                                    <span style="padding-left: 24px; display: block;">
                                        <span class="ksd-icon-sp selected-border-right iconfont fz20 mr-2 iconshangjia2"></span>
                                        <a href="javascript:void(0);">OSS Administration</a>
                                        <span title="To be completed" class="layui-badge-dot" style="position: absolute; top: 12px; right: 50px;"></span>
                                    </span>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </aside>
    </body>
</html>

Core code

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<aside th:fragment="asidebar"></aside>

Th: fragment = "aside bar" give the specific location of the page template a name: aside bar. This name is introduced in the pages to be included as follows:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="content-type" content="text/html;charset=utf-8">
		<meta name="renderer" content="webkit">
		<meta http-equiv="X-UA-Compatible" content="IE=Edge">
		<meta http-equiv="Pragma" content="no-cache">
		<meta http-equiv="Cache-Control" content="no-cache">
		<meta http-equiv="Expires" content="0">
		<title>back-stage management</title>
		<meta name="keywords" content="HTML, CSS, XML, XHTML, JavaScript">
		<meta name="description" content="franco web Technical course">
		<!-- Background public css js The file storage page contains -->
		<div th:replace="~{commons/header::scriptbar}"></div>
	</head>

	<body data-ext-version="3.1" style="">
		<!-- Head menu navigation -->
		<div th:replace="~{commons/nav::navbar}"></div>
		<!-- Content area -->
		<div id="root" class="ksd-main">
			<div class="pgc-wrapper pgc-index index-wrapper">
				<div class="pgc-content">
					<section class=" mp-main-contain byte-layout-has-sider">
						<!-- Left menu navigation -->
						<div th:replace="~{commons/leftnav::asidebar}"></div>
						<!-- Content table -->
						<div id="ksd-mainbox" class="animated fadeIn pr"></div>
					</section>
				</div>
			</div>
		</div>
		<!-- bottom -->
		<div th:replace="~{commons/footer::footerbar}"></div>
		<!-- Page script -->
		<script th:src="@{/js/admin/index.js}"></script>
	</body>
</html>

Core code:

<div th:replace="~{commons/leftnav::asidebar}"></div>

th:replace stands for commons / leftnav The specific code block name in html is: th:fragment = "asidebar". Take it out and replace the div.

$(function () {
    // Initialize menu navigation
    adminAside.init();
    // Page loading tips
    adminLoading.init();
})

// Control left menu navigation
var adminAside = {
    init:function () {
        this.animate();
        this.menuEvent();
    },

    // Controls the folding and unfolding of the left menu navigation
    animate:function () {
        //Click menu binding click event, and then control the menu below to expand and collapse
        $("#asideapp").find(".byte-menu-inline-header").on("click", function () {
            // Control exclusion
            $(this).parents(".byte-menu-inline").siblings().find(".byte-menu-inline-content").hide();
            $(this).parents(".byte-menu-inline").siblings().find(".byte-menu-icon-suffix").removeClass("is-open");
            $(this).next().toggle();
            $(this).find(".byte-menu-icon-suffix").toggleClass("is-open");
        })
    },

    // From the control menu, click render right template
    menuEvent:function () {
        $("#asideapp").find(".byte-menu-item").on("click", function () {
            var href = $(this).data("href");
            // $.get(href, function (res) {
            //     $("#ksd-mainbox").html(res);
            // })

            $("#ksd-mainbox").load(href);
        })
        // Trigger the first element as the default active item
        $("#asideapp").find(".byte-menu-item").eq(0).trigger("click");
    }

}

// Page loading tips
var adminLoading = {
    init:function () {
        this.animate();
    },
    animate:function () {

    }
}

5. Login

Note: login and logout are handled in the background development, and login is not required. Other background access pages require login interception to enter. Therefore, one of the first issues we consider when doing background work: login interception

5.1 define and register login interceptors

package com.example.config;

import com.example.hander.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Auther: giraffe
 * @Date: 2021/07/26/16:43
 * @Description:
 */
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Bean
    public LoginInterceptor getLoginInterceptor() {
        return new LoginInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // Interceptor registration
        registry.addInterceptor(getLoginInterceptor())
                // Exclude login and exit
                .excludePathPatterns("/admin/login",
                        "/admin/logout",
                        "/admin/toLogin")
                // Intercept all background requests
                .addPathPatterns("/admin/**");
    }
}

5.2 exclude login and exit routes in the interceptor

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        // Interceptor registration
        registry.addInterceptor(getLoginInterceptor())
                // Exclude login and exit
                .excludePathPatterns("/admin/login",
                        "/admin/logout",
                        "/admin/toLogin")
                // Intercept all background requests
                .addPathPatterns("/admin/**");
    }

5.3 logged in, jump to the home page

package com.example.controller;

import com.example.common.constant.RConstants;
import com.example.common.exception.ResultCodeEnum;
import com.example.common.exception.ValidationException;
import com.example.entity.User;
import com.example.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;

/**
 * @Auther: giraffe
 * @Date: 2021/07/25/11:07
 * @Description:
 */
@Controller
@Slf4j
public class LoginController extends BaseController {

    @Autowired
    private UserService userService;

    @GetMapping("/login")
    public String login(HttpSession session){
        // First, judge whether the user has logged in
        User sessionUser = (User) session.getAttribute(RConstants.SESSION_USER);
        // If you have logged in, go directly to the home page
        if (sessionUser != null) {
            return "redirect:/admin/index";
        }
        // If you don't log in, go directly to the login page
        return "login";
    }

    @PostMapping("/toLogin")
    @ResponseBody
    public String toLogin(HttpSession session, String nickname, String password){
        log.info("Current user:{},password:{}", nickname, password);
        // Query whether the user exists according to the nickname entered by the user
        User user = userService.getByUserName(nickname);
        // If it does not exist, it returns fail, which means that the user cannot find it
        if(user == null){
            throw new ValidationException(ResultCodeEnum.NICKNAME_NO_EXISTENCE);
        }
        // Judge whether the password entered by the current user is consistent with the database password. If the consistent login is successful
        if (user != null && !user.getPassword().equalsIgnoreCase(password)) {
            throw new ValidationException(ResultCodeEnum.PASSWORD_ERROR);
        }
        // Write the login successful user information into the session
        session.setAttribute(RConstants.SESSION_USER, user);
        // success is returned after successful login
        return "success";
    }

}

5.4. Log out

@GetMapping("/logout")
public String logout(HttpSession session){
    // Log out
    session.invalidate();
    // Exit successfully, redirected to login page
    return "redirect:/admin/login";
}
<a th:href="@{/admin/logout}" style="width: 86px;"><i class="iconfont iconai-out"></i>Log out</a>

5.5 background setting of login page

.bgpic{
  	background:url("xxxx.jpg");
    position:fixed;
    top:0;
    left:0;
    bottom:0;
    right:0;
    filter:blur(1px);
    background-size:cover;
}

6. Complete list query, search and pagination

6.1 configuration of paging interceptor

package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @Auther: giraffe
 * @Date: 2021/07/30/14:53
 * @Description:
 */
@Configuration
@EnableTransactionManagement
public class MyBatisPlusConfig {

    // Paging plug-in
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

6.2 define paging logic

package com.example.controller.state;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.controller.common.BaseController;
import com.example.entity.State;
import com.example.service.state.StateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

/**
 * @Auther: giraffe
 * @Date: 2021/07/28/15:27
 * @Description:
 */
@Controller
public class StateController extends BaseController {

    @Autowired
    private StateService stateService;

    @GetMapping("state/list")
    public String list(ModelMap modelMap){
        Page<State> pageState = stateService.pageList(0, 10);
        // 2: Put data into scope
        // Specific data displayed on each page
        modelMap.put("stateList", pageState.getRecords());
        // Total records
        modelMap.put("total", pageState.getTotal());
        //pageSize is how many pages are displayed per page
        modelMap.put("pageSize", pageState.getSize());
        // pageNo current page
        modelMap.put("pageNo", pageState.getCurrent());
        //  How many pages are there in the pages
        modelMap.put("pages", pageState.getPages());
        // 3: Rendered view template
        return "state/template";
    }

    @GetMapping("state/listTemplate")
    public String listTemplate(ModelMap modelMap, @RequestParam(name = "pageNo", defaultValue = "1")Integer pageNo,
                               @RequestParam(name = "pageSize", defaultValue = "10")Integer pageSize){
        Page<State> pageState = stateService.pageList(pageNo,pageSize);
        // 2: Put data into scope
        // Specific data displayed on each page
        modelMap.put("stateList", pageState.getRecords());
        // Total records
        modelMap.put("total", pageState.getTotal());
        //pageSize is how many pages are displayed per page
        modelMap.put("pageSize", pageState.getSize());
        // pageNo current page
        modelMap.put("pageNo", pageState.getCurrent());
        //  How many pages are there in the pages
        modelMap.put("pages", pageState.getPages());
        // 3: Rendered view template
        return "state/listTemplate";
    }
}
package com.example.service.state;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.State;
import com.example.mapper.StateMapper;
import org.springframework.stereotype.Service;

/**
 * @Auther: giraffe
 * @Date: 2021/07/30/13:33
 * @Description:
 */
@Service
public class StateServiceImpl extends ServiceImpl<StateMapper, State> implements StateService {

    @Override
    public Page<State> pageList(int pageNo, int pageSize) {
        Page<State> page = new Page<>(pageNo, pageSize);
        // Query paging
        QueryWrapper<State> queryWrapper = new QueryWrapper<>();
        Page<State> pageState = this.page(page, queryWrapper);
        return pageState;
    }
}
package com.example.service.state;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.entity.State;

/**
 * @Auther: giraffe
 * @Date: 2021/07/30/13:32
 * @Description:
 */
public interface StateService extends IService<State> {

    Page<State> pageList(int pageNo, int pageSize);
}

6.3 page initialization paging

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<main id="appbox" class="byte-layout-content garr-container" style="background: rgb(255, 255, 255);">
    <div class="layui-tab-item layui-show">
        <div id="LAY_preview">
            <div class="layui-border-box">
                <div class="layui-table-tool">
                    <span class="mr-4 fl">11 articles in total</span>
                    <div class="layui-table-tool-selfc ml-2 fr">
                        <a href="https://www.kuangstudy.com/bbs" target="_blank" class="layui-btn layui-btn-sm">
                            <span class="iconfont iconhome mr-2 fz12"></span>
                            Visit the home page
                        </a>
                    </div>
                    <div class="layui-table-tool-selfc ml-2 fr">
                        <button class="layui-btn layui-btn-sm">
                            <i class="iconfont iconadd mr-2"></i>
                            Add first level classification
                        </button>
                    </div>
                    <div class="layui-table-tool-selfc fr">
                        <div class="layui-inline">
                            <input title="knock enter Keyboard can also search!" maxlength="100" autocomplete="off"
                                   placeholder="Please enter a category title..." class="layui-input" style="width: 320px; height: 32px; line-height: 32px;">
                        </div>
                        <button class="layui-btn layui-btn-sm">search</button>
                    </div>
                </div>
            </div>
            <div class="layui-table-box">
                <div class="layui-table-body layui-table-main">
                    <table cellspacing="0" cellpadding="0" border="0" class="layui-table">
                        <thead>
                        <tr>
                            <th class="layui-table-col-special">
                                <div class="layui-table-cell  laytable-cell-numbers">
                                    <span>ID</span>
                                </div>
                            </th>
                            <th>
                                <div class="layui-table-cell"><span>title</span></div>
                            </th>
                            <th>
                                <div class="layui-table-cell"><span>Number of participants</span></div>
                            </th>
                            <th>
                                <div class="layui-table-cell"><span>Creation time</span></div>
                            </th>
                            <th>
                                <div class="layui-table-cell"><span>Create user</span></div>
                            </th>
                            <th>
                                <div class="layui-table-cell"><span>state</span></div>
                            </th>
                            <th>
                                <div class="layui-table-cell"><span>operation</span></div>
                            </th>
                        </tr>
                        </thead>
                        <tbody id="state-tbody" th:data-total="${total}" th:data-pages="${pages}"
                               th:data-pageSize="${pageSize}">
                            <div th:replace="~{state/listTemplate::stateList}"></div>
                        </tbody>
                    </table>
                </div>
                <!-- Turn pages -->
                <div class="layui-table-page" id="state-page" style="height: 60px; text-align: center; margin-top: 50px;"></div>
            </div>
        </div>
    </div>

    <script>

        // 1: How to initialize and get the page number of each click
        // 2: How to query the corresponding data according to the paging query and return the corresponding data to the specified location

        var state = {
            page:function (total) {
                var that = this;
                layui.use(['laypage', 'layer'], function() {
                    var layPage = layui.laypage
                        , layer = layui.layer;

                    //The total number of pages is greater than the total number of pages
                    layPage.render({
                        elem: 'state-page'
                        , count: total //Total data
                        , jump: function (obj) {
                            // Get the current user click the current page
                            var currentPageNo = obj.curr;
                            // if(currentPageNo > 1){
                                // Click on each page of rendered data
                                that.loadData(currentPageNo);
                            // }
                        }
                    });
                });
            },
            // Load background data
            // loadData:function (pageNo) {
            //     $.get("/admin/state/listTemplate", {pageNo:pageNo}, function (res) {
            //         //Find the content of the rendered tbody on the second page
            //         var tbodyHtml = $(res).find("#state-tbody").html();
            //         //Put the found content into the current tbody
            //         $("#state-tbody").html(tbodyHtml);
            //     })
            // }
            loadData:function(pageNo){
                $.get("/admin/state/listTemplate",{pageNo:pageNo},function(res){
                    $("#state-tbody").html(res);
                })
            }
        };

        $(function () {
            // Get total records
            var total = $("#state-tbody").data("total");
            // Initialize paging based on total
            state.page(total);
        })
    </script>

</main>
</body>
</html>

Core code

  <tbody id="ksd-tbody" th:data-total="${total}" th:data-pages="${pages}">

1. The above code takes out the data in the background scope through thymeleaf's template rendering technology.

// Specific data displayed on each page
modelMap.put("stateList", pageState.getRecords());
// Total records
modelMap.put("total", pageState.getTotal());
//pageSize is how many pages are displayed per page
modelMap.put("pageSize", pageState.getSize());
// pageNo current page
modelMap.put("pageNo", pageState.getCurrent());
//  How many pages are there in the pages
modelMap.put("pages", pageState.getPages());

2. Then it is rendered to the left position through ajax, and then JS is loaded, the total number of records is de duplicated through jQuery's data syntax, and then paging can be initialized.

// The entry of iframe and iframe is not triggered immediately, including all the functions of the current node 
$(function(){
     // 1. Get the total number of records from the KSD tbody attribute
     var total = $("#ksd-tbody").data("total");
     // 2. Just initialize paging according to total
     ksdState.page(total);
 })
```

Core code

  <tbody id="ksd-tbody" th:data-total="${total}" th:data-pages="${pages}">

1. The above code takes out the data in the background scope through thymeleaf's template rendering technology.

// Specific data displayed on each page
modelMap.put("stateList", pageState.getRecords());
// Total records
modelMap.put("total", pageState.getTotal());
//pageSize is how many pages are displayed per page
modelMap.put("pageSize", pageState.getSize());
// pageNo current page
modelMap.put("pageNo", pageState.getCurrent());
//  How many pages are there in the pages
modelMap.put("pages", pageState.getPages());

2. Then it is rendered to the left position through ajax, and then JS is loaded, the total number of records is de duplicated through jQuery's data syntax, and then paging can be initialized.

// All current nodes, excluding the entry function triggered immediately after image and iframe are loaded 
$(function(){
     // 1. Get the total number of records from the KSD tbody attribute
     var total = $("#ksd-tbody").data("total");
     // 2. Just initialize paging according to total
     ksdState.page(total);
 })

Topics: Java Maven Spring