SpringBoot+FreeMarker+Bootstrap+JDBC实现增删改查以及分页

附上源码地址源码地址,点击"源码地址"前往github查看

一、创建SpringBoot项目

1)File->New->Project

新建项目

2)创建Spring Initializr以及选择JDK版本

选择项目工具以及JDK版本

3)填写项目信息

填写项目信息

4)选择web依赖包---Spring Web Starter或者Web,具体根据页面显示的勾选

选择web依赖包

5)选择项目保存路径

项目保存路径

6)创建项目成功,看一下目前的项目结构

项目目录

二、设计数据库

1)创建数据库

  • 使用终端进入mysql
// "cd"到"mysql"目录下
$ cd /usr/local/mysql
// 进入"mysql"
$ mysql -u root -p
// 输入密码
Enter password: 
// 密码验证成功,则进入"mysql"
mysql> 
  • 创建数据库
// 创建数据库"js_springboot_demo"
create database js_springboot_demo character set utf8;
// 查看数据库
show databases;
创建数据库

2)创建数据表

// 进入我们的数据库`js_springboot_demo`
use js_springboot_demo
// 创建数据表
create table user (id int(11) auto_increment primary key, title varchar(255) not null, name varchar(255) null, wx_number varchar(255) null);
// 查看表
show tables;
// 查看表的详细信息
describe user;
创建表

3)连接数据库

  • idea打开项目,选择右侧database
连接数据库1
  • 选择mysql
连接数据库2
  • mysql数据库信息填写
连接数据库3

连接数据库4
  • 连接成功后,再次回到database,可以看到我们创建的数据库以及表、字段等信息
连接数据库5

三、添加项目依赖库以及相关配置

1)添加依赖库

打开pom.xml文件,依次添加下列依赖库:

  • 添加FreeMarker
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
  • 添加数据库(mysqljdbc
<dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
  • 添加Gson
<dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.8.5</version>
</dependency>
  • 添加lombok插件,用于生成gettersetter方法(需要先在idea设置中添加该插件再进行依赖库的引入)

a、添加lombok插件

安装lombok插件

b、添加依赖库

<dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
</dependency>

2)配置

打开application.properties文件,添加如下配置:

#本地数据库
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/js_springboot_demo
spring.datasource.username=root
spring.datasource.password=****

spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5

server.port=8080
server.connection-timeout=10s
server.tomcat.uri-encoding=UTF-8

#freemarker 配置信息
spring.freemarker.cache=true
spring.freemarker.check-template-location=true
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.suffix=.ftl
spring.freemarker.templateEncoding=UTF-8
#设定ftl文件路径
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.expose-spring-macro-helpers=false
#设定静态文件路径,js,css等
spring.resources.static-locations=classpath:/templates/,classpath:/static/

四、测试Java Class与前端.ftl页面的连接

1)view(即前端.ftl页面)

  • templates中创建一个名为user的目录,且在该目录下创建一个名为index.ftl文件
创建.ftl页面
  • index.ftl内容
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>测试</title>
</head>
<body>
<!-- ${name}为freemarker的模板 -->
<p>hello world!!! ${name} </p>

</body>
</html>

2)Controller(即java class

  • 创建一个名为HelloWorldControllerjava class
controller
  • 实现
package com.springboot.helloworld.Controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@RestController
public class HelloWorldController {
    @GetMapping("/index")
    public ModelAndView index(Map<String, Object> map){

        map.put("name", "af");
        return new ModelAndView("user/index", map);
    }
}
  • 页面展示

打开浏览器,访问http://localhost:8080/index

页面展示

如上,可以通过controller访问页面后,接下来我们进行本章重点内容:增删改查以及分页的介绍

五、实现增删改查功能

这里我们先介绍一下java的层级结构,主要分为以下四层:
dao层:主要跟数据库进行交互,称为持久层一般是创建一个dao接口,然后去定义接口的实现类。
entity层:数据库在项目中的类,称为实体层或者model层主要就是去定义与数据库中的对象相对应的属性,包括gettersettertoString方法以及一些构造函数等。
service层:控制业务的,称为业务层主要负责业务模块的逻辑应用设计,也是先设计接口,然后去定义接口的实现类。其实就是将业务逻辑独立出来,有利于复用。
controller层:管理业务以及页面跳转,称为控制层主要获取前端数据,调用service方法,转发到下一个页面等

1)entity

  • 创建实体包

右击helloworld,选择New->Package,命名为entity

创建实体包

  • 创建实体类

右击entity,选择New->Java Class,命名为UserEntity,并添加如表user中的属性(数据表中字段常以_分割,java class中常以驼峰命名,对应关系详解可以查看这篇文章

package com.springboot.helloworld.entity;

import lombok.Data;
//@Data: lombok,生成getter、setter方法
@Data
public class UserEntity {
//    id
    private int id;
//    标题
    private String title;
//    姓名
    private String name;
//    微信
    private String wxNumber;
}

2)dao

  • 同创建实体包一样,创建一个名为dao的包
  • dao下创建一个名为UserDao的接口

接口创建

UserDao接口中添加如下方法:

package com.springboot.helloworld.dao;

import com.springboot.helloworld.entity.UserEntity;

import java.util.List;

public interface UserDao {
    /***
     * 查询用户
     * @return
     */
    public List<UserEntity> selectUser(String keyword);
    /**
     * 插入数据
     */
    public int insertUser(UserEntity user);

    /**
     * 删除数据
     */
    public int deleteUser(int uid);

    /**
     * 更新数据
     */
    public int updateUser(UserEntity user);
}

  • UserDao接口添加实现类,名为UserDaoImpl,并实现接口UserDao的方法
package com.springboot.helloworld.dao.impl;

import com.springboot.helloworld.dao.UserDao;
import com.springboot.helloworld.entity.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public List<UserEntity> selectUser(String keyword) {
        String sql = "SELECT * FROM user WHERE CONCAT(id, title, name, wx_number) LIKE ?";
        return jdbcTemplate.query(sql, new Object[]{"%" + keyword + "%"}, new BeanPropertyRowMapper<>(UserEntity.class));
}

    @Override
    public int insertUser(UserEntity user) {
        String sql = "INSERT INTO user(title, name, wx_number) VALUES(?, ?, ?)";

        return jdbcTemplate.update(sql, user.getTitle(), user.getName(), user.getWxNumber());
    }

    @Override
    public int updateUser(UserEntity user) {
        String sql = "UPDATE user SET title=?, name=?, wx_number=? WHERE id=?";

        return jdbcTemplate.update(sql, user.getTitle(), user.getName(), user.getWxNumber(), user.getId());
    }

    @Override
    public int deleteUser(int uid) {
        String sql = "DELETE FROM user WHERE id=?";
        return jdbcTemplate.update(sql, uid);
    }
}

3)service

  • 同创建实体包一样,创建一个名为service的包
  • service下创建一个名为UserService的接口

UserService接口中添加如下方法:

package com.springboot.helloworld.service;

import com.springboot.helloworld.entity.UserEntity;

import java.util.Map;

public interface UserService {
    //    查询
    public Map<String, Object> selectUser(String keyword);
    //    插入
    public String insertUser(UserEntity user);
    //    删除
    public String deleteUser(String uid);
    //    更新
    public String updateUser(UserEntity user);
}
  • UserService接口添加实现类,名为UserServiceImpl,并实现接口UserService的方法
package com.springboot.helloworld.service.impl;

import com.google.gson.JsonObject;
import com.springboot.helloworld.dao.UserDao;
import com.springboot.helloworld.entity.UserEntity;
import com.springboot.helloworld.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public Map<String, Object> selectUser(String keyword) {
        List<UserEntity> list = userDao.selectUser(keyword);
        Map<String, Object> map = new HashMap<>();
        if (list.size() == 0){
            map.put("userList", list);
            map.put("message", "没有查询到数据");
        }else{
            map.put("userList", list);
        }
        return map;
    }

    @Override
    public String insertUser(UserEntity user) {
        JsonObject result = new JsonObject();
        if (user.getName().isEmpty()) {
            result.addProperty("code", "-1");
            result.addProperty("message", "标题不能为空");
        }else{
            int insertResult = userDao.insertUser(user);
            if (insertResult >= 1){
                result.addProperty("code", "200");
                result.addProperty("message", "插入成功");
            }else{
                result.addProperty("code", "0");
                result.addProperty("message", "插入失败");
            }
        }
        return result.toString();
    }

    @Override
    public String updateUser(UserEntity user) {

        JsonObject result = new JsonObject();
        int updateResult = userDao.updateUser(user);
        if (updateResult >= 1){
            result.addProperty("code", "200");
            result.addProperty("message", "修改成功");
        }else{
            result.addProperty("code", "0");
            result.addProperty("message", "修改失败");
        }

        return result.toString();
    }

    @Override
    public String deleteUser(String uid) {
        int deleteResult = userDao.deleteUser(Integer.parseInt(uid));

        JsonObject result = new JsonObject();
        if (deleteResult >= 1){
            result.addProperty("code", "200");
            result.addProperty("message", "删除成功");
        }else{
            result.addProperty("code", "0");
            result.addProperty("message", "删除失败");
        }
        return result.toString();
    }
}

4)web

在测试连接的部分我们已经创建了index.ftl页面了,这里就不再重复创建了。

  • 插入

要实现的效果:先在页面上添加一个插入按钮,点击插入弹出模态框,输入对应信息,然后在页面上显示插入结果
代码

/**
 * html代码 
 **/
<button type="button" class="btn btn-primary" style="float: left;margin:20px 20px 0;" data-toggle="modal" data-target="#infoModel" data-id="insertCommit">插入</button>
<div class="modal fade" id="infoModel" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">New message</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form>
                    <div class="form-group">
                        <label for="recipient-title" class="col-form-label">标题:</label>
                        <input type="text" class="form-control" id="recipient-title" name="title">
                    </div>
                    <div class="form-group">
                        <label for="recipient-name" class="col-form-label">名称:</label>
                        <input type="text" class="form-control" id="recipient-name" name="name">
                    </div>
                    <div class="form-group">
                        <label for="recipient-wxnum" class="col-form-label">微信号:</label>
                        <input type="text" class="form-control" id="recipient-wxnum" name="wxNumber">
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                <button type="button" class="btn btn-primary" id="commitBtn" onclick="commitEvent(this)">提交</button>
            </div>
        </div>
    </div>
</div>
<p id="requestResult">请求结果:</p>

/**
 * jQuery代码 
 **/
//显示模态视图
$('#infoModel').on('show.bs.modal', function (event) {
    // $("#commitBtn").attr("data-id", "insertEvent");

});

//模态视图提交内容
commitEvent = function (event) {
    // console.log($(event).attr("data-id"));
    insertEvent();
};

//    插入
insertEvent = function () {
    //将form表单内容转为json串
    var jsonStr = JSON.stringify($('form').serializeJSON());
    console.log(jsonStr);
//    通过ajax请求接口
    $.ajax({
        type: "POST",
        url: "/insertUser",
        contentType: "application/json",//数据请求格式
        dataType : 'json',//数据返回格式
        data: jsonStr,
        success: function(result){
            console.log(result);
            $('#requestResult').append('success===' + result);
            $('#infoModel').modal('hide');
            //插入成功后刷新页面
            //window.location.reload();
        },
        error:function(error){
            console.log(error);
            $('#requestResult').append('error===' + error);
            $('#infoModel').modal('hide');
        }
    });
}
  • 查找全部

要实现的效果:用列表形式展示查询到的所有数据
代码

/**
 * html
**/
<#--数据展示-->
<div class="table-responsive">
    <table class="table">
        <thead>
        <tr>
            <th scope="col" style="width: 10%;"> ID </th>
            <th scope="col" style="width: 30%;">标题</th>
            <th scope="col" style="width: 20%;">姓名</th>
            <th scope="col" style="width: 20%;">微信</th>
            <th scope="col" style="width: 20%;">操作</th>
        </tr>
        </thead>
        <tbody>
        <#if userList?? && (userList?size > 0)>
            <#list userList as row>
                <tr>
                    <th scope="row">${row.id}</th>
                    <td>${row.title}</td>
                    <td>${row.name}</td>
                    <td>${row.wxNumber}</td>
<!-- 修改和删除的按钮先放着,事件会在后续代码中进行说明 -->                
                    <td>
                      <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#infoModel" data-id="alterCommit" data-param='{"id":"${row.id}","title":"${row.title}","name":"${row.name}","wxNumber":"${row.wxNumber}"}'>修改</button>
                      <button class="btn btn-danger" onclick="deleteRow(${row.id})">删除</button>
                  </td>
                </tr>
            </#list>

        <#else>
            <p>${message}</p>
        </#if>
        </tbody>
    </table>
</div>
  • 更新

查找全部的前端页面中,已经加入了修改删除按钮,这里就只写相关事件了(注:修改同样是要弹出模态视图,跟插入共用一个,不同之处是修改的时候需要给form表单赋值,那么插入则需要将form表单的值清空):

//显示模态视图
$('#infoModel').on('show.bs.modal', function (event) {
    //获取当前点击按钮,用于判断是插入还是修改
    var button = $(event.relatedTarget);
    var btnId = button.data('id');
    //用于填充表单
    var modal = $(this);

    if (btnId == "insertCommit"){
        //插入
        modal.find("#recipient-title").val("");
        modal.find("#recipient-name").val("");
        modal.find("#recipient-wxnum").val("");

    } else if (btnId == "alterCommit"){
    //    修改
        var info = button.data("param");
        console.log(info);

        modal.find("#recipient-title").val(info.title);
        modal.find("#recipient-name").val(info.name);
        modal.find("#recipient-wxnum").val(info.wxNumber);

        //传rowid用于修改数据
        $("#commitBtn").attr("data-rowId", info.id);
    }

    //提交按钮加上id用于区分是插入提交还是修改提交
    $("#commitBtn").attr("data-id", btnId);
});

//模态视图提交内容
commitEvent = function (event) {
    var btnId = $(event).attr("data-id");
    if (btnId == "insertCommit") {
        insertEvent();
    }else if (btnId == "alterCommit"){
        var rowId = $(event).attr("data-rowId");
        updateEvent(rowId);
    }

};
//    修改
updateEvent = function (rowId) {
    var object = $('form').serializeJSON();
    var paramInfo = {
        "title": object.title,
        "name" : object.name,
        "wxNumber" : object.wxNumber,
        "id": rowId
    }
    var jsonStr = JSON.stringify(paramInfo);
    console.log(jsonStr);

    $.ajax({
        type: "POST",
        url: "/updateUser",
        contentType: "application/json",
        dataType: "json",
        data: jsonStr,
        success: function(result){
            console.log(result);
            var json = JSON.parse(result);
            //    关闭模态框
            $('#infoModel').modal('hide');
            //刷新页面
            window.location.reload();

        },
        error:function(result){
            alert("error");
            $('#infoModel').modal('hide');
        }
    });
}
  • 关键字搜索

要实现的效果:在搜索框中输入内容,查找数据库中所有包含该内容的数据并展示
代码

/**
 * html
**/
<div class="input-group mb-3" style="width: 90%;margin: 20px 0 0 20px;float: left;">
    <input type="text" class="form-control" id="search_id" placeholder="请输入关键字" aria-label="关键字" aria-describedby="basic-addon2">
    <div class="input-group-append">
        <button class="btn btn-outline-secondary" type="button" type="submit"  onclick="searchId()">搜索</button>
    </div>
</div>
/**
 * jQuery
**/
//    搜索
searchId = function () {
    var keyword = $("#search_id").val();
    window.location.href = "/index?keyword=" + keyword;
}
  • 删除
//    删除
deleteRow = function (rowId) {
    var param = {
        "uid": rowId,
    }
    var jsonStr = JSON.stringify(param);
    $.ajax({
        type: "POST",
        url: "/deleteUser",
        contentType: "application/json",
        dataType: "json",
        data: jsonStr,
        success: function(result){
            console.log(result);
            //刷新页面
            window.location.reload();
        },
        error:function(result){
            alert("error");
        }
    });
}

5)controller

在测试连接的部分我们已经创建了HelloWorldController页面了,这里就不再重复创建了。

在开始Controller之前,有个知识点需要提一下。在这个项目中,我们使用@RequestBody注解来使Spring自动将http中的body(json格式)转换为java内部的类。该项目中我们使用了Gson,但由于Spring内部默认使用JackSon来进行转换,所以我们需要配置一下。

  • 配置Gson

创建:
创建一个名为GsonHttpMessageConverterConfiguration的类:

Gson配置

配置:

package com.springboot.helloworld.config;

import com.google.gson.Gson;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.GsonHttpMessageConverter;

@Configuration
@ConditionalOnClass(Gson.class)
@ConditionalOnMissingClass("com.fasterxml.jackson.core.JsonGenerator")
@ConditionalOnBean(Gson.class)
public class GsonHttpMessageConverterConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public GsonHttpMessageConverter gsonHttpMessageConverter(Gson gson) {
        GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
        converter.setGson(gson);
        return converter;
    }
}

HelloworldApplication启动类中加入不适用JackSon的代码:

@SpringBootApplication (
//        确保Jackson没有被使用
        exclude = {
                JacksonAutoConfiguration.class,
        }
)

有了以上配置,我们就可以使用Gson中的JsonObject来接收前端传过来的json串了。

  • 插入
//    插入
@PostMapping(value = "/insertUser", consumes="application/json")
public String insert(@RequestBody JsonObject object){
    UserEntity user = new Gson().fromJson(object, UserEntity.class);
    return userService.insertUser(user);
}
  • 查找/关键字搜索

由于需要将查询结果显示在index页面上,即访问http://localhost:8080/index展示查询结果,所以HelloWorldController中查询就写在上面测试连接的方法中:

//默认keyword为空串,即查找全部
@GetMapping(value = "/index")
public ModelAndView index(@RequestParam(value = "keyword", defaultValue = "") String keyword){
    return new ModelAndView("user/index", userService.selectUser(keyword));
}
  • 更新
//    修改
@PostMapping(value = "/updateUser", consumes = "application/json")
public String update(@RequestBody JsonObject object){
    UserEntity user = new Gson().fromJson(object, UserEntity.class);
    return userService.updateUser(user);
}
  • 删除
//    删除
@PostMapping(value = "/deleteUser", consumes = "application/json")
public String delete(@RequestBody JsonObject object){
    String userId = object.get("uid").toString();
    return userService.deleteUser(userId);
}

到这里为止,我们的增删改查功能已经全部实现,接下来我们看分页的实现。

六、实现分页功能

主要实现分页从数据库中查询记录,包括加入关键字搜索的分页查询。

1) 添加PageEntity实体类

entity包下添加分页的实体类,并实现构造方法计算总页数等数据。
PageEntity实体类的实现

package com.springboot.helloworld.entity;

import lombok.Data;

import java.util.List;

@Data
public class PageEntity {
    /**
     * 当前页码
     */
    private int currentPage;
    /**
     * 每页显示条数
     */
    private int pageSize;
    /**
     * 数据库查询到的记录总条数
     */
    private int totalRecordSize;
    /**
     * 当前页的数据列表
     */
    private List<UserEntity> currentRecordList;
    /**
     * 关键字
     */
    private String keyword;


    /**
     * 总页数
     */
    private int totalPage;
    /**
     * 页码开始索引
     */
    private int startPageIndex;
    /**
     * 页码结束索引
     */
    private int endPageIndex;


//    构造方法
    public PageEntity(int currentPage, int pageSize, String keyword, int totalRecordSize, List<UserEntity> recordList){
        this.currentPage = currentPage;
        this.pageSize = pageSize;
        this.keyword = keyword;
        this.totalRecordSize = totalRecordSize;
        this.currentRecordList = recordList;

        /**
         * 计算总页数
         */
        totalPage = (totalRecordSize + pageSize - 1) / pageSize;
        /**
         * 计算beginPageIndex以及endPageIndex
         * 如果是10页以内,则页数为1~10
         * 大于10页,则显示10附近的10个页数,比如6~15、7~16......
         */
        if (totalPage <= 10){
            startPageIndex = 1;
            endPageIndex = totalPage;
        }else{
//            前4页+当前页+后5页
            startPageIndex = currentPage - 4;
            endPageIndex = currentPage + 5;
//            当前面页数不足4页时,显示前10个页面
            if (startPageIndex < 1){
                startPageIndex = 1;
                endPageIndex = 10;
            }
//            当后面页数不足5页时,显示后面10个页码
            if (endPageIndex > totalPage){
                startPageIndex = totalPage - 10 + 1;
                endPageIndex = totalPage;
            }
        }

    }
}

2) 在UserDao中添加分页查询接口,并在UserDaoImpl中实现该接口方法

UserDao实现代码:

/**
 * 分页查询
 */
public PageEntity selectPageUser(int start, int size, String keyword);

UserDaoImpl实现代码:

@Override
public PageEntity selectPageUser(int start, int size, String keyword) {
//         查询记录列表
    String sql = "SELECT * FROM user WHERE CONCAT(id, title, name, wx_number) LIKE ? LIMIT ?,?";
//        查询总记录数
    String recordSql = "SELECT COUNT(id) FROM user WHERE CONCAT(id, title, name, wx_number) LIKE ?";

    List<UserEntity> list = jdbcTemplate.query(sql, new Object[]{"%" + keyword + "%", (start-1)*size, size}, new BeanPropertyRowMapper<>(UserEntity.class));
    int count = jdbcTemplate.queryForObject(recordSql, new Object[]{"%" + keyword + "%"}, Integer.class);
    return new PageEntity(start, size, keyword, count, list);
}

3) 在UserService中添加分页查询接口,并在UserServiceImpl中实现该接口方法

UserService实现代码:

//    分页
public Map<String, Object> selectPageUser(int start, int size, String keyword);

UserServiceImpl实现代码:

@Override
public Map<String, Object> selectPageUser(int start, int size, String keyword) {
        PageEntity pageEntity = userDao.selectPageUser(start, size, keyword);
        List<UserEntity> list = pageEntity.getCurrentRecordList();
        Map<String, Object> map = new HashMap<>();
        map.put("userList", list);
        map.put("currentPage", pageEntity.getCurrentPage());
        map.put("totalPage", pageEntity.getTotalPage());
        map.put("keyword", pageEntity.getKeyword());
        map.put("pageUrl", "/index?");
        if (list.size() == 0){
            map.put("message", "暂时没有数据哦");
        }
        return map;
}

4) 在HelloWorldController中,修改index方法

@GetMapping(value = "/index")
public ModelAndView index(@RequestParam(value = "keyword", defaultValue = "") String keyword, @RequestParam(value = "page", defaultValue = "1") Integer page){
    return new ModelAndView("user/index", userService.selectPageUser(page, 5, keyword));
}

5) 在index.ftl页面中加入分页

<#if userList?? && (userList?size > 0)>
<#--分页-->
<div class="col-md-12 column">
    <ul class="pagination">
    <#--lte  less than or equal 小于等于-->
        <#if currentPage lte 1>
            <li class="disabled">
                <a class="page-link" href="#"><<</a>
            </li>
        <#else>
            <li>
                <a class="page-link" href="${pageUrl}page=${currentPage - 1}&keyword=${keyword}"><<</a>
            </li>
        </#if>

        <#list 1..totalPage as index>
            <#if currentPage == index>
                <li class="page-item active">
                    <a class="page-link" href="#">${index}</a>
                </li>
            <#else>
                <li>
                    <a class="page-link" href="${pageUrl}page=${index}&keyword=${keyword}">${index}</a>
                </li>
            </#if>
        </#list>
    <#--gte  greater than or equal  大于等于-->
        <#if currentPage gte totalPage>
            <li class="disabled">
                <a class="page-link" href="#">>></a>
            </li>
        <#else>
            <li>
                <a class="page-link" href="${pageUrl}page=${currentPage + 1}&keyword=${keyword}">>></a>
            </li>
        </#if>
    </ul>
</div>
</#if>

七、效果展示

效果展示
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342