SpringBoot整合MySQL快速搭建XX管理系統(tǒng)
點(diǎn)擊上方“程序員大白”,選擇“星標(biāo)”公眾號(hào)
重磅干貨,第一時(shí)間送達(dá)

摘要
對(duì)企業(yè)來說,人、物資、能源、資金、信息是5大重要資源。人、物資、能源、資金這些都是可見的有形資源,而信息是一種無形的資源。以前人們比較看重有形的資源,進(jìn)入信息社會(huì)和知識(shí)經(jīng)濟(jì)時(shí)代以后,信息資源就顯得日益重要。因?yàn)樾畔①Y源決定了如何更有效地利用物資資源。信息資源是人類與自然的斗爭(zhēng)中得出的知識(shí)結(jié)晶,掌握了信息資源,就可以更好地利用有形資源,使有形資源發(fā)揮更好的效益。
由此可見,諸如各類管理系統(tǒng)還是很有價(jià)值的,筆者經(jīng)歷的公司內(nèi)部都有自己實(shí)現(xiàn)的管理系統(tǒng),可能有些非互聯(lián)網(wǎng)的公司是依靠其他公司提供的信息管理服務(wù),ERP系統(tǒng)至今還發(fā)揮著重要作用,筆者下班后連忙帶趕,經(jīng)歷數(shù)個(gè)小時(shí)的鏖戰(zhàn),終于做完了此xx管理系統(tǒng),在此與諸位分享。
1 技術(shù)選型
1.1 Mysql8
為什么是mysql8,不是5版本的。沒錯(cuò)就是喜新厭舊啦?。?!
mysql8有何特別之處呢!
1.性能就是好,沒錯(cuò)它就是強(qiáng),所以當(dāng)然上Mysql8,快點(diǎn)上8。

2.Mysql8還支持各種牛逼的功能:SQL窗口函數(shù),GIS,JSON擴(kuò)展語法等等??傊@些功能聽著就挺牛,由于筆者自己還沒弄明白,就不贅述了。
1.2 springboot2
當(dāng)前主流的web開發(fā)框架,不二之選,沒有比這更方便的了,為什么選這個(gè),它就是無敵,沒有競(jìng)爭(zhēng)對(duì)手啊。自動(dòng)裝配,父級(jí)依賴,嵌入tomcat等等,就是無敵呀。

1.3 模板引擎thymeleaf
用模板引擎也實(shí)屬無奈,筆者不會(huì)前端呀,畢竟人的精力是有限的。不過這個(gè)東西還是挺好用的,趕腳用著和幾年前學(xué)寫jsp也差不多。
2 項(xiàng)目構(gòu)建
2.1 創(chuàng)建項(xiàng)目
spring initializer

取個(gè)心愛的項(xiàng)目名字

勾選需要的依賴,mysql,thymeleaf,jpa

2.2 建表
好吧,筆者為了偷懶,沒有建表ddl,直接上jpa,先建一個(gè)需要的庫(kù),create database。做完這些,項(xiàng)目開始的準(zhǔn)備工作就已經(jīng)完了,馬上又帶了激動(dòng)人心的擼代碼環(huán)節(jié)了。
3 項(xiàng)目實(shí)現(xiàn)
3.1 項(xiàng)目效果
主頁面

就是這樣滴,如此就已然發(fā)揮了筆者百分之兩百的前端功力了,各種查閱資料,復(fù)制copy加代碼修改,修修改改終于有了上邊的模樣,應(yīng)該不算太丑吧!好吧,我承認(rèn)了。
3.2 項(xiàng)目結(jié)構(gòu)
和主流web開發(fā)項(xiàng)目的結(jié)構(gòu)基本大同小異:
對(duì)應(yīng)數(shù)據(jù)庫(kù)實(shí)體的entity包,對(duì)應(yīng)數(shù)據(jù)庫(kù)操作的repo目錄,對(duì)應(yīng)業(yè)務(wù)代碼的service目錄,對(duì)應(yīng)restful api的controller目錄。

4 代碼實(shí)現(xiàn)
4.1 前臺(tái)頁面
首頁面,就是上邊看到的那個(gè)帥氣的首頁!
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<meta charset="UTF-8">
<title>xx-manager</title>
</head>
<body>
<header th:replace="xx-header.html"></header>
<div class="container my-2">
<a th:href="@{/newEmployee}" class="btn btn-primary btn-sm mb-3"> 新增 </a>
<table border="1" class = "table table-striped table-responsive-md">
<thead>
<tr>
<th>姓名</th>
<th>郵箱</th>
<th>電話</th>
<th>地址</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="employee : ${employees}">
<td th:text="${employee.name}"></td>
<td th:text="${employee.email}"></td>
<td th:text="${employee.mobile}"></td>
<td th:text="${employee.location}"></td>
<td><a th:href="@{/updateEmployee/{id}(id=${employee.id})}" class="btn btn-primary">修改</a>
<a th:href="@{/deleteEmployee/{id}(id=${employee.id})}" class="btn btn-danger">刪除</a></td>
</tr>
</tbody>
</table>
<div th:if="${totalPages > 1}">
<div class="row col-sm-10">
<div class="col-sm-2">
總?cè)藬?shù): [[${items}]]
</div>
<div class="col-sm-1">
<span th:each="i: ${#numbers.sequence(1, totalPages)}">
<a th:if="${currentPage != i}" th:href="@{'/page/' + ${i}}">[[${i}]]</a>
<span th:unless="${currentPage != i}">[[${i}]]</span>
</span>
</div>
<div class="col-sm-1">
<a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${currentPage + 1}}">下一頁</a>
<span th:unless="${currentPage < totalPages}">下一頁</span>
</div>
<div class="col-sm-1">
<a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${totalPages}}">尾頁</a>
<span th:unless="${currentPage < totalPages}">尾頁</span>
</div>
</div>
</div>
</div>
<footer th:replace="footer.html"></footer>
</body>
</html>
新增功能頁面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<meta charset="UTF-8">
<title>xx-manager</title>
</head>
<body>
<header th:replace="xx-header.html"></header>
<div class="container">
<h1>xx-manager</h1>
<hr>
<h2>保存</h2>
<form action="#" th:action="@{/saveEmployee}" th:object="${employee}" method="POST">
<input type="text" th:field="*{name}" placeholder="姓名" class="form-control mb-4 col-4">
<input type="text" th:field="*{email}" placeholder="郵箱" class="form-control mb-4 col-4">
<input type="text" th:field="*{mobile}" placeholder="電話" class="form-control mb-4 col-4">
<input type="text" th:field="*{location}" placeholder="住址" class="form-control mb-4 col-4">
<button type="submit" class="btn btn-info col-2">保存</button>
</form>
<hr>
<a th:href="@{/}">回退</a>
</div>
<footer th:replace="footer.html"></footer>
</body>
</html>
修改功能頁面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<meta charset="UTF-8">
<title>xx-manager</title>
</head>
<body>
<header th:replace="xx-header.html"></header>
<div class="container">
<h1>xx-manager</h1>
<hr>
<h2>更新</h2>
<form action="#" th:action="@{/saveEmployee}" th:object="${employee}" method="POST">
<input type="hidden" th:field="*{id}" />
<input type="text" th:field="*{name}" class="form-control mb-4 col-4">
<input type="text" th:field="*{email}" class="form-control mb-4 col-4">
<input type="text" th:field="*{mobile}" class="form-control mb-4 col-4">
<input type="text" th:field="*{location}" class="form-control mb-4 col-4">
<button type="submit" class="btn btn-info col-2">修改</button>
</form>
<hr>
<a th:href="@{/}">回退</a>
</div>
<footer th:replace="footer.html"></footer>
</body>
</html>
4.2 后臺(tái)業(yè)務(wù)實(shí)現(xiàn)
4.2.1 實(shí)體類Employee
對(duì)應(yīng)數(shù)據(jù)庫(kù)中的表
package com.lbh.xxmanager.entity;
import javax.persistence.*;
/**
* Copyright(c)[email protected]
* @author liubinhao
* @date 2021/1/7
* ++++ ______ ______ ______
* +++/ /| / /| / /|
* +/_____/ | /_____/ | /_____/ |
* | | | | | | | | |
* | | | | | |________| | |
* | | | | | / | | |
* | | | | |/___________| | |
* | | |___________________ | |____________| | |
* | | / / | | | | | | |
* | |/ _________________/ / | | / | | /
* |_________________________|/b |_____|/ |_____|/
*/
@Entity
@Table(name = "xx_employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
@Column(name = "mobile")
private String mobile;
@Column(name = "location")
private String location;
@Column(name="status")
private int status;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
4.2.2 數(shù)據(jù)庫(kù)操作層repo
package com.lbh.xxmanager.repo;
import com.lbh.xxmanager.entity.Employee;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* Copyright(c)[email protected]
* @author liubinhao
* @date 2021/1/7
* ++++ ______ ______ ______
* +++/ /| / /| / /|
* +/_____/ | /_____/ | /_____/ |
* | | | | | | | | |
* | | | | | |________| | |
* | | | | | / | | |
* | | | | |/___________| | |
* | | |___________________ | |____________| | |
* | | / / | | | | | | |
* | |/ _________________/ / | | / | | /
* |_________________________|/b |_____|/ |_____|/
*/
@Repository
public interface EmployeeRepository extends JpaRepository<Employee,Long> {
List<Employee> findAllByStatus(int status);
Page<Employee> findAllByStatus(int status, Pageable pageable);
Page<Employee> findAllByStatusAndLocationLikeOrNameLikeOrEmailLike(int status,String locaion,String name,String email, Pageable pageable);
}
4.2.3 業(yè)務(wù)代碼service
接口:
package com.lbh.xxmanager.service;
import com.lbh.xxmanager.entity.Employee;
import org.springframework.data.domain.Page;
import java.util.List;
/**
* Copyright(c)[email protected]
* @author liubinhao
* @date 2021/1/7
* ++++ ______ ______ ______
* +++/ /| / /| / /|
* +/_____/ | /_____/ | /_____/ |
* | | | | | | | | |
* | | | | | |________| | |
* | | | | | / | | |
* | | | | |/___________| | |
* | | |___________________ | |____________| | |
* | | / / | | | | | | |
* | |/ _________________/ / | | / | | /
* |_________________________|/b |_____|/ |_____|/
*/
public interface EmployeeService {
List<Employee> findAllEmployees();
void saveEmployee(Employee employee);
Employee getEmployeeById(long id);
void deleteEmployeeById(long id);
Page<Employee> findPaging(int no,int size);
Page<Employee> findPaging(int no,int size,String searchKey);
}
業(yè)務(wù)實(shí)現(xiàn)類:
package com.lbh.xxmanager.service;
import com.lbh.xxmanager.entity.Employee;
import com.lbh.xxmanager.repo.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
/**
* Copyright(c)[email protected]
*
* @author liubinhao
* @date 2021/1/7
* ++++ ______ ______ ______
* +++/ /| / /| / /|
* +/_____/ | /_____/ | /_____/ |
* | | | | | | | | |
* | | | | | |________| | |
* | | | | | / | | |
* | | | | |/___________| | |
* | | |___________________ | |____________| | |
* | | / / | | | | | | |
* | |/ _________________/ / | | / | | /
* |_________________________|/b |_____|/ |_____|/
*/
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
@Override
public List<Employee> findAllEmployees() {
return employeeRepository.findAllByStatus(0);
}
@Override
public void saveEmployee(Employee employee) {
employee.setStatus(0);
employeeRepository.save(employee);
}
@Override
public Employee getEmployeeById(long id) {
Optional<Employee> byId = employeeRepository.findById(id);
Employee employee = null;
if (byId.isPresent()){
employee = byId.get();
}else {
throw new RuntimeException("該id員工不存在!");
}
return employee;
}
@Override
public void deleteEmployeeById(long id) {
Employee employeeById = getEmployeeById(id);
employeeById.setStatus(1);
employeeRepository.save(employeeById);
}
@Override
public Page<Employee> findPaging(int no, int size) {
Pageable pageable = PageRequest.of(no - 1,size);
return employeeRepository.findAllByStatus(0,pageable);
}
@Override
public Page<Employee> findPaging(int no, int size, String searchKey) {
String key = "%"+searchKey+"%";
Pageable pageable = PageRequest.of(no - 1,size);
return employeeRepository.findAllByStatusAndLocationLikeOrNameLikeOrEmailLike(0,key,key,key,pageable);
}
}
4.2.4 Web接口
package com.lbh.xxmanager.controller;
import com.lbh.xxmanager.entity.Employee;
import com.lbh.xxmanager.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.thymeleaf.util.StringUtils;
import java.util.List;
/**
* Copyright(c)[email protected]
* @author liubinhao
* @date 2021/1/7
* ++++ ______ ______ ______
* +++/ /| / /| / /|
* +/_____/ | /_____/ | /_____/ |
* | | | | | | | | |
* | | | | | |________| | |
* | | | | | / | | |
* | | | | |/___________| | |
* | | |___________________ | |____________| | |
* | | / / | | | | | | |
* | |/ _________________/ / | | / | | /
* |_________________________|/b |_____|/ |_____|/
*/
@Controller
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@GetMapping("/")
public String index(Model model){
model.addAttribute("employees",employeeService.findAllEmployees());
return "redirect:/page/1";
}
@GetMapping("/newEmployee")
public String newEmployee(Model model){
Employee employee = new Employee();
model.addAttribute("employee",employee);
return "new_employee";
}
@PostMapping("/saveEmployee")
public String saveEmployee(@ModelAttribute Employee employee){
employeeService.saveEmployee(employee);
return "redirect:/";
}
@GetMapping("/updateEmployee/{id}")
public String updateEmployee(@PathVariable Long id,Model model){
Employee employeeById = employeeService.getEmployeeById(id);
model.addAttribute("employee",employeeById);
return "update_employee";
}
@GetMapping("/deleteEmployee/{id}")
public String deleteEmployee(@PathVariable Long id){
employeeService.deleteEmployeeById(id);
return "redirect:/";
}
@GetMapping("/page/{pageNo}")
public String findPaging(@PathVariable int pageNo, @RequestParam(required = false) String key, Model model){
Page<Employee> paging = null;
if (StringUtils.isEmpty(key)) {
paging = employeeService.findPaging(pageNo, 5);
}
else{
paging = employeeService.findPaging(pageNo, 5,key);
}
List<Employee> content = paging.getContent();
model.addAttribute("currentPage",pageNo);
model.addAttribute("totalPages",paging.getTotalPages());
model.addAttribute("items",paging.getTotalElements());
model.addAttribute("employees",content);
return "index";
}
}
4.3 配置文件
springboot的配置文件
server.port=9001
spring.datasource.username=root
spring.datasource.password=你的數(shù)據(jù)庫(kù)密碼
spring.datasource.url=jdbc:mysql://localhost:3303/xx-manager?serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&autoReconnect=true&useSSL=false&failOverReadOnly=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
# update 這樣寫可以自動(dòng)建表,更新表
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto=update
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
5 總結(jié)
寫一個(gè)這樣簡(jiǎn)單的后臺(tái)信息管理還是不難,看來筆者還是寶刀未老。下班回家開始做,不過寫博客是真滴難,都過了12點(diǎn)還沒有寫
完,寫博客和我寫代碼的時(shí)間也相差無幾了。哎,我這可憐的頭發(fā)啊。

推薦閱讀
關(guān)于程序員大白
程序員大白是一群哈工大,東北大學(xué),西湖大學(xué)和上海交通大學(xué)的碩士博士運(yùn)營(yíng)維護(hù)的號(hào),大家樂于分享高質(zhì)量文章,喜歡總結(jié)知識(shí),歡迎關(guān)注[程序員大白],大家一起學(xué)習(xí)進(jìn)步!
