SpringBoot+FreeMarker+Bootstrap+JDBC實(shí)現(xiàn)增刪改查以及分頁(yè)

附上源碼地址源碼地址译柏,點(diǎn)擊"源碼地址"前往github查看

一鄙麦、創(chuàng)建SpringBoot項(xiàng)目

1)File->New->Project

新建項(xiàng)目

2)創(chuàng)建Spring Initializr以及選擇JDK版本

選擇項(xiàng)目工具以及JDK版本

3)填寫(xiě)項(xiàng)目信息

填寫(xiě)項(xiàng)目信息

4)選擇web依賴(lài)包---Spring Web Starter或者Web盟劫,具體根據(jù)頁(yè)面顯示的勾選

選擇web依賴(lài)包

5)選擇項(xiàng)目保存路徑

項(xiàng)目保存路徑

6)創(chuàng)建項(xiàng)目成功塘装,看一下目前的項(xiàng)目結(jié)構(gòu)

項(xiàng)目目錄

二、設(shè)計(jì)數(shù)據(jù)庫(kù)

1)創(chuàng)建數(shù)據(jù)庫(kù)

  • 使用終端進(jìn)入mysql
// "cd"到"mysql"目錄下
$ cd /usr/local/mysql
// 進(jìn)入"mysql"
$ mysql -u root -p
// 輸入密碼
Enter password: 
// 密碼驗(yàn)證成功,則進(jìn)入"mysql"
mysql> 
  • 創(chuàng)建數(shù)據(jù)庫(kù)
// 創(chuàng)建數(shù)據(jù)庫(kù)"js_springboot_demo"
create database js_springboot_demo character set utf8;
// 查看數(shù)據(jù)庫(kù)
show databases;
創(chuàng)建數(shù)據(jù)庫(kù)

2)創(chuàng)建數(shù)據(jù)表

// 進(jìn)入我們的數(shù)據(jù)庫(kù)`js_springboot_demo`
use js_springboot_demo
// 創(chuàng)建數(shù)據(jù)表
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;
// 查看表的詳細(xì)信息
describe user;
創(chuàng)建表

3)連接數(shù)據(jù)庫(kù)

  • idea打開(kāi)項(xiàng)目,選擇右側(cè)database
連接數(shù)據(jù)庫(kù)1
  • 選擇mysql
連接數(shù)據(jù)庫(kù)2
  • mysql數(shù)據(jù)庫(kù)信息填寫(xiě)
連接數(shù)據(jù)庫(kù)3

連接數(shù)據(jù)庫(kù)4
  • 連接成功后十减,再次回到database速址,可以看到我們創(chuàng)建的數(shù)據(jù)庫(kù)以及表、字段等信息
連接數(shù)據(jù)庫(kù)5

三闹炉、添加項(xiàng)目依賴(lài)庫(kù)以及相關(guān)配置

1)添加依賴(lài)庫(kù)

打開(kāi)pom.xml文件,依次添加下列依賴(lài)庫(kù):

  • 添加FreeMarker
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
  • 添加數(shù)據(jù)庫(kù)(mysql嗅钻、jdbc
<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設(shè)置中添加該插件再進(jìn)行依賴(lài)庫(kù)的引入)

a嚣伐、添加lombok插件

安裝lombok插件

b、添加依賴(lài)庫(kù)

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

2)配置

打開(kāi)application.properties文件,添加如下配置:

#本地?cái)?shù)據(jù)庫(kù)
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
#設(shè)定ftl文件路徑
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.expose-spring-macro-helpers=false
#設(shè)定靜態(tài)文件路徑,js,css等
spring.resources.static-locations=classpath:/templates/,classpath:/static/

四根灯、測(cè)試Java Class與前端.ftl頁(yè)面的連接

1)view(即前端.ftl頁(yè)面)

  • templates中創(chuàng)建一個(gè)名為user的目錄芥驳,且在該目錄下創(chuàng)建一個(gè)名為index.ftl文件
創(chuàng)建.ftl頁(yè)面
  • index.ftl內(nèi)容
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>測(cè)試</title>
</head>
<body>
<!-- ${name}為freemarker的模板 -->
<p>hello world!!! ${name} </p>

</body>
</html>

2)Controller(即java class

  • 創(chuàng)建一個(gè)名為HelloWorldControllerjava class
controller
  • 實(shí)現(xiàn)
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);
    }
}
  • 頁(yè)面展示

打開(kāi)瀏覽器,訪問(wèn)http://localhost:8080/index

頁(yè)面展示

如上,可以通過(guò)controller訪問(wèn)頁(yè)面后谬以,接下來(lái)我們進(jìn)行本章重點(diǎn)內(nèi)容:增刪改查以及分頁(yè)的介紹

五邮丰、實(shí)現(xiàn)增刪改查功能

這里我們先介紹一下java的層級(jí)結(jié)構(gòu)剪廉,主要分為以下四層:
dao層:主要跟數(shù)據(jù)庫(kù)進(jìn)行交互,稱(chēng)為持久層泉沾。一般是創(chuàng)建一個(gè)dao接口,然后去定義接口的實(shí)現(xiàn)類(lèi)揭朝。
entity層:數(shù)據(jù)庫(kù)在項(xiàng)目中的類(lèi),稱(chēng)為實(shí)體層或者model層屯换。主要就是去定義與數(shù)據(jù)庫(kù)中的對(duì)象相對(duì)應(yīng)的屬性,包括getter晕窑、settertoString方法以及一些構(gòu)造函數(shù)等。
service層:控制業(yè)務(wù)的阳柔,稱(chēng)為業(yè)務(wù)層医咨。主要負(fù)責(zé)業(yè)務(wù)模塊的邏輯應(yīng)用設(shè)計(jì)拟淮,也是先設(shè)計(jì)接口,然后去定義接口的實(shí)現(xiàn)類(lèi)委造。其實(shí)就是將業(yè)務(wù)邏輯獨(dú)立出來(lái),有利于復(fù)用。
controller層:管理業(yè)務(wù)以及頁(yè)面跳轉(zhuǎn)跑筝,稱(chēng)為控制層瞒滴。主要獲取前端數(shù)據(jù)曲梗,調(diào)用service方法,轉(zhuǎn)發(fā)到下一個(gè)頁(yè)面等妓忍。

1)entity

  • 創(chuàng)建實(shí)體包

右擊helloworld虏两,選擇New->Package,命名為entity

創(chuàng)建實(shí)體包

  • 創(chuàng)建實(shí)體類(lèi)

右擊entity定罢,選擇New->Java Class,命名為UserEntity搁廓,并添加如表user中的屬性(數(shù)據(jù)表中字段常以_分割引颈,java class中常以駝峰命名耕皮,對(duì)應(yīng)關(guān)系詳解可以查看這篇文章

package com.springboot.helloworld.entity;

import lombok.Data;
//@Data: lombok境蜕,生成getter、setter方法
@Data
public class UserEntity {
//    id
    private int id;
//    標(biāo)題
    private String title;
//    姓名
    private String name;
//    微信
    private String wxNumber;
}

2)dao

  • 同創(chuàng)建實(shí)體包一樣凌停,創(chuàng)建一個(gè)名為dao的包
  • dao下創(chuàng)建一個(gè)名為UserDao的接口

接口創(chuàng)建

UserDao接口中添加如下方法:

package com.springboot.helloworld.dao;

import com.springboot.helloworld.entity.UserEntity;

import java.util.List;

public interface UserDao {
    /***
     * 查詢(xún)用戶(hù)
     * @return
     */
    public List<UserEntity> selectUser(String keyword);
    /**
     * 插入數(shù)據(jù)
     */
    public int insertUser(UserEntity user);

    /**
     * 刪除數(shù)據(jù)
     */
    public int deleteUser(int uid);

    /**
     * 更新數(shù)據(jù)
     */
    public int updateUser(UserEntity user);
}

  • UserDao接口添加實(shí)現(xiàn)類(lèi)粱年,名為UserDaoImpl,并實(shí)現(xiàn)接口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

  • 同創(chuàng)建實(shí)體包一樣罚拟,創(chuàng)建一個(gè)名為service的包
  • service下創(chuàng)建一個(gè)名為UserService的接口

UserService接口中添加如下方法:

package com.springboot.helloworld.service;

import com.springboot.helloworld.entity.UserEntity;

import java.util.Map;

public interface UserService {
    //    查詢(xún)
    public Map<String, Object> selectUser(String keyword);
    //    插入
    public String insertUser(UserEntity user);
    //    刪除
    public String deleteUser(String uid);
    //    更新
    public String updateUser(UserEntity user);
}
  • UserService接口添加實(shí)現(xiàn)類(lèi)台诗,名為UserServiceImpl完箩,并實(shí)現(xiàn)接口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", "沒(méi)有查詢(xún)到數(shù)據(jù)");
        }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", "標(biāo)題不能為空");
        }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

在測(cè)試連接的部分我們已經(jīng)創(chuàng)建了index.ftl頁(yè)面了,這里就不再重復(fù)創(chuàng)建了拉队。

  • 插入

要實(shí)現(xiàn)的效果:先在頁(yè)面上添加一個(gè)插入按鈕弊知,點(diǎn)擊插入彈出模態(tài)框,輸入對(duì)應(yīng)信息粱快,然后在頁(yè)面上顯示插入結(jié)果
代碼

/**
 * 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">標(biāo)題:</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">名稱(chēng):</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">微信號(hào):</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">請(qǐng)求結(jié)果:</p>

/**
 * jQuery代碼 
 **/
//顯示模態(tài)視圖
$('#infoModel').on('show.bs.modal', function (event) {
    // $("#commitBtn").attr("data-id", "insertEvent");

});

//模態(tài)視圖提交內(nèi)容
commitEvent = function (event) {
    // console.log($(event).attr("data-id"));
    insertEvent();
};

//    插入
insertEvent = function () {
    //將form表單內(nèi)容轉(zhuǎn)為json串
    var jsonStr = JSON.stringify($('form').serializeJSON());
    console.log(jsonStr);
//    通過(guò)ajax請(qǐng)求接口
    $.ajax({
        type: "POST",
        url: "/insertUser",
        contentType: "application/json",//數(shù)據(jù)請(qǐng)求格式
        dataType : 'json',//數(shù)據(jù)返回格式
        data: jsonStr,
        success: function(result){
            console.log(result);
            $('#requestResult').append('success===' + result);
            $('#infoModel').modal('hide');
            //插入成功后刷新頁(yè)面
            //window.location.reload();
        },
        error:function(error){
            console.log(error);
            $('#requestResult').append('error===' + error);
            $('#infoModel').modal('hide');
        }
    });
}
  • 查找全部

要實(shí)現(xiàn)的效果:用列表形式展示查詢(xún)到的所有數(shù)據(jù)
代碼

/**
 * html
**/
<#--數(shù)據(jù)展示-->
<div class="table-responsive">
    <table class="table">
        <thead>
        <tr>
            <th scope="col" style="width: 10%;"> ID </th>
            <th scope="col" style="width: 30%;">標(biāo)題</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>
<!-- 修改和刪除的按鈕先放著秩彤,事件會(huì)在后續(xù)代碼中進(jìn)行說(shuō)明 -->                
                    <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>
  • 更新

查找全部的前端頁(yè)面中,已經(jīng)加入了修改刪除按鈕事哭,這里就只寫(xiě)相關(guān)事件了(注:修改同樣是要彈出模態(tài)視圖漫雷,跟插入共用一個(gè),不同之處是修改的時(shí)候需要給form表單賦值鳍咱,那么插入則需要將form表單的值清空):

//顯示模態(tài)視圖
$('#infoModel').on('show.bs.modal', function (event) {
    //獲取當(dāng)前點(diǎn)擊按鈕降盹,用于判斷是插入還是修改
    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用于修改數(shù)據(jù)
        $("#commitBtn").attr("data-rowId", info.id);
    }

    //提交按鈕加上id用于區(qū)分是插入提交還是修改提交
    $("#commitBtn").attr("data-id", btnId);
});

//模態(tài)視圖提交內(nèi)容
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);
            //    關(guān)閉模態(tài)框
            $('#infoModel').modal('hide');
            //刷新頁(yè)面
            window.location.reload();

        },
        error:function(result){
            alert("error");
            $('#infoModel').modal('hide');
        }
    });
}
  • 關(guān)鍵字搜索

要實(shí)現(xiàn)的效果:在搜索框中輸入內(nèi)容,查找數(shù)據(jù)庫(kù)中所有包含該內(nèi)容的數(shù)據(jù)并展示
代碼

/**
 * 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="請(qǐng)輸入關(guān)鍵字" aria-label="關(guān)鍵字" 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);
            //刷新頁(yè)面
            window.location.reload();
        },
        error:function(result){
            alert("error");
        }
    });
}

5)controller

在測(cè)試連接的部分我們已經(jīng)創(chuàng)建了HelloWorldController頁(yè)面了谤辜,這里就不再重復(fù)創(chuàng)建了蓄坏。

在開(kāi)始Controller之前,有個(gè)知識(shí)點(diǎn)需要提一下每辟。在這個(gè)項(xiàng)目中剑辫,我們使用@RequestBody注解來(lái)使Spring自動(dòng)將http中的body(json格式)轉(zhuǎn)換為java內(nèi)部的類(lèi)。該項(xiàng)目中我們使用了Gson渠欺,但由于Spring內(nèi)部默認(rèn)使用JackSon來(lái)進(jìn)行轉(zhuǎn)換妹蔽,所以我們需要配置一下。

  • 配置Gson

創(chuàng)建:
創(chuàng)建一個(gè)名為GsonHttpMessageConverterConfiguration的類(lèi):

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啟動(dòng)類(lèi)中加入不適用JackSon的代碼:

@SpringBootApplication (
//        確保Jackson沒(méi)有被使用
        exclude = {
                JacksonAutoConfiguration.class,
        }
)

有了以上配置挠将,我們就可以使用Gson中的JsonObject來(lái)接收前端傳過(guò)來(lái)的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);
}
  • 查找/關(guān)鍵字搜索

由于需要將查詢(xún)結(jié)果顯示在index頁(yè)面上,即訪問(wèn)http://localhost:8080/index展示查詢(xún)結(jié)果舔稀,所以HelloWorldController中查詢(xún)就寫(xiě)在上面測(cè)試連接的方法中:

//默認(rèn)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);
}

到這里為止,我們的增刪改查功能已經(jīng)全部實(shí)現(xiàn)内贮,接下來(lái)我們看分頁(yè)的實(shí)現(xiàn)产园。

六、實(shí)現(xiàn)分頁(yè)功能

主要實(shí)現(xiàn)分頁(yè)從數(shù)據(jù)庫(kù)中查詢(xún)記錄夜郁,包括加入關(guān)鍵字搜索的分頁(yè)查詢(xún)什燕。

1) 添加PageEntity實(shí)體類(lèi)

entity包下添加分頁(yè)的實(shí)體類(lèi),并實(shí)現(xiàn)構(gòu)造方法計(jì)算總頁(yè)數(shù)等數(shù)據(jù)竞端。
PageEntity實(shí)體類(lèi)的實(shí)現(xiàn)

package com.springboot.helloworld.entity;

import lombok.Data;

import java.util.List;

@Data
public class PageEntity {
    /**
     * 當(dāng)前頁(yè)碼
     */
    private int currentPage;
    /**
     * 每頁(yè)顯示條數(shù)
     */
    private int pageSize;
    /**
     * 數(shù)據(jù)庫(kù)查詢(xún)到的記錄總條數(shù)
     */
    private int totalRecordSize;
    /**
     * 當(dāng)前頁(yè)的數(shù)據(jù)列表
     */
    private List<UserEntity> currentRecordList;
    /**
     * 關(guān)鍵字
     */
    private String keyword;


    /**
     * 總頁(yè)數(shù)
     */
    private int totalPage;
    /**
     * 頁(yè)碼開(kāi)始索引
     */
    private int startPageIndex;
    /**
     * 頁(yè)碼結(jié)束索引
     */
    private int endPageIndex;


//    構(gòu)造方法
    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;

        /**
         * 計(jì)算總頁(yè)數(shù)
         */
        totalPage = (totalRecordSize + pageSize - 1) / pageSize;
        /**
         * 計(jì)算beginPageIndex以及endPageIndex
         * 如果是10頁(yè)以?xún)?nèi)屎即,則頁(yè)數(shù)為1~10
         * 大于10頁(yè),則顯示10附近的10個(gè)頁(yè)數(shù),比如6~15技俐、7~16......
         */
        if (totalPage <= 10){
            startPageIndex = 1;
            endPageIndex = totalPage;
        }else{
//            前4頁(yè)+當(dāng)前頁(yè)+后5頁(yè)
            startPageIndex = currentPage - 4;
            endPageIndex = currentPage + 5;
//            當(dāng)前面頁(yè)數(shù)不足4頁(yè)時(shí)乘陪,顯示前10個(gè)頁(yè)面
            if (startPageIndex < 1){
                startPageIndex = 1;
                endPageIndex = 10;
            }
//            當(dāng)后面頁(yè)數(shù)不足5頁(yè)時(shí),顯示后面10個(gè)頁(yè)碼
            if (endPageIndex > totalPage){
                startPageIndex = totalPage - 10 + 1;
                endPageIndex = totalPage;
            }
        }

    }
}

2) 在UserDao中添加分頁(yè)查詢(xún)接口雕擂,并在UserDaoImpl中實(shí)現(xiàn)該接口方法

UserDao實(shí)現(xiàn)代碼:

/**
 * 分頁(yè)查詢(xún)
 */
public PageEntity selectPageUser(int start, int size, String keyword);

UserDaoImpl實(shí)現(xiàn)代碼:

@Override
public PageEntity selectPageUser(int start, int size, String keyword) {
//         查詢(xún)記錄列表
    String sql = "SELECT * FROM user WHERE CONCAT(id, title, name, wx_number) LIKE ? LIMIT ?,?";
//        查詢(xún)總記錄數(shù)
    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中添加分頁(yè)查詢(xún)接口啡邑,并在UserServiceImpl中實(shí)現(xiàn)該接口方法

UserService實(shí)現(xiàn)代碼:

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

UserServiceImpl實(shí)現(xiàn)代碼:

@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", "暫時(shí)沒(méi)有數(shù)據(jù)哦");
        }
        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頁(yè)面中加入分頁(yè)

<#if userList?? && (userList?size > 0)>
<#--分頁(yè)-->
<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>

七井赌、效果展示

效果展示
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谣拣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子族展,更是在濱河造成了極大的恐慌森缠,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仪缸,死亡現(xiàn)場(chǎng)離奇詭異贵涵,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)恰画,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)宾茂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人拴还,你說(shuō)我怎么就攤上這事跨晴。” “怎么了片林?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵端盆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么践剂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮焚鹊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘韧献。我一直安慰自己末患,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布锤窑。 她就那樣靜靜地躺著璧针,像睡著了一般。 火紅的嫁衣襯著肌膚如雪果复。 梳的紋絲不亂的頭發(fā)上陈莽,一...
    開(kāi)封第一講書(shū)人閱讀 52,793評(píng)論 1 314
  • 那天渤昌,我揣著相機(jī)與錄音虽抄,去河邊找鬼走搁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛迈窟,可吹牛的內(nèi)容都是我干的私植。 我是一名探鬼主播,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼车酣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼曲稼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起湖员,我...
    開(kāi)封第一講書(shū)人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤贫悄,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后娘摔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體窄坦,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年凳寺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鸭津。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肠缨,死狀恐怖逆趋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晒奕,我是刑警寧澤闻书,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站脑慧,受9級(jí)特大地震影響惠窄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜漾橙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一杆融、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧霜运,春花似錦脾歇、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至焦除,卻和暖如春激况,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工乌逐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留竭讳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓浙踢,卻偏偏與公主長(zhǎng)得像绢慢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洛波,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361