• Spring Boot + MySQL 快速搭建管理系统,不能太容易了!


    来源:blog.csdn.net/weixin_44671737/article/details/112341805

    摘要

    对企业来说,人、物资、能源、资金、信息是5大重要资源。人、物资、能源、资金这些都是可见的有形资源,而信息是一种无形的资源。以前人们比较看重有形的资源,进入信息社会和知识经济时代以后,信息资源就显得日益重要。

    因为信息资源决定了如何更有效地利用物资资源。信息资源是人类与自然的斗争中得出的知识结晶,掌握了信息资源,就可以更好地利用有形资源,使有形资源发挥更好的效益。

    由此可见,诸如各类管理系统还是很有价值的,笔者经历的公司内部都有自己实现的管理系统,可能有些非互联网的公司是依靠其他公司提供的信息管理服务,ERP系统至今还发挥着重要作用,笔者下班后连忙带赶,经历数个小时的鏖战,终于做完了此xx管理系统,在此与诸位分享。

    1 技术选型

    1.1 Mysql8

    为什么是mysql8,不是5版本的。没错就是喜新厌旧啦!!!

    mysql8有何特别之处呢!

    1.性能就是好,没错它就是强,所以当然上Mysql8,快点上8。

    2.Mysql8还支持各种牛逼的功能:SQL窗口函数,GIS,JSON扩展语法等等。总之这些功能听着就挺牛,由于笔者自己还没弄明白,就不赘述了。

    1.2 springboot2

    当前主流的web开发框架,不二之选,没有比这更方便的了,为什么选这个,它就是无敌,没有竞争对手啊。自动装配,父级依赖,嵌入tomcat等等,就是无敌呀。

    Spring Boot 基础就不介绍了,推荐下这个实战教程:
    https://github.com/javastacks/spring-boot-best-practice

    1.3 模板引擎thymeleaf

    用模板引擎也实属无奈,笔者不会前端呀,毕竟人的精力是有限的。不过这个东西还是挺好用的,赶脚用着和几年前学写jsp也差不多。

    2 项目构建

    2.1 创建项目

    spring initializer

    取个心爱的项目名字

    勾选需要的依赖,mysql,thymeleaf,jpa

    2.2 建表

    好吧,笔者为了偷懒,没有建表ddl,直接上jpa,先建一个需要的库,create database。做完这些,项目开始的准备工作就已经完了,马上又带了激动人心的撸代码环节了。

    3 项目实现

    3.1 项目效果

    主页面

    就是这样滴,如此就已然发挥了笔者百分之两百的前端功力了,各种查阅资料,复制copy加代码修改,修修改改终于有了上边的模样,应该不算太丑吧!好吧,我承认了。

    3.2 项目结构

    和主流web开发项目的结构基本大同小异:

    对应数据库实体的entity包,对应数据库操作的repo目录,对应业务代码的service目录,对应restful api的controller目录。

    4 代码实现

    4.1 前台页面

    首页面,就是上边看到的那个帅气的首页!

    <!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">
                    总人数: [[${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> &nbsp; &nbsp;
                        </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 后台业务实现

    4.2.1 实体类Employee

    对应数据库中的表

    package com.lbh.xxmanager.entity;
    
    import javax.persistence.*;
    
    /**
     * Copyright(c)lbhbinhao@163.com
     * @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 数据库操作层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)lbhbinhao@163.com
     * @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 业务代码service

    接口:

    package com.lbh.xxmanager.service;
    
    import com.lbh.xxmanager.entity.Employee;
    import org.springframework.data.domain.Page;
    
    import java.util.List;
    
    /**
     * Copyright(c)lbhbinhao@163.com
     * @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);
    }
    

    业务实现类:

    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)lbhbinhao@163.com
     *
     * @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)lbhbinhao@163.com
     * @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=你的数据库密码
    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 这样写可以自动建表,更新表
    # 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 总结

    写一个这样简单的后台信息管理还是不难,看来笔者还是宝刀未老。下班回家开始做,不过写博客是真滴难,都过了12点还没有写

    完,写博客和我写代码的时间也相差无几了。哎,我这可怜的头发啊。

    近期热文推荐:

    1.1,000+ 道 Java面试题及答案整理(2022最新版)

    2.劲爆!Java 协程要来了。。。

    3.Spring Boot 2.x 教程,太全了!

    4.Spring Boot 2.6 正式发布,一大波新特性。。

    5.《Java开发手册(嵩山版)》最新发布,速速下载!

    觉得不错,别忘了随手点赞+转发哦!

  • 相关阅读:
    ZT 安卓手机的安全性 prepare for Q
    ZT pthread_cleanup_push()/pthread_cleanup_pop()的详解
    <Lord don’t move that mountain>
    C++浅拷贝和深拷贝的区别
    001 Python简介 输入输出
    016 可等待计时器对象.6
    016 EventDemo 5
    016 事件内核对象4
    016 内核对象的Signal状态3
    016 句柄2
  • 原文地址:https://www.cnblogs.com/javastack/p/15801545.html
Copyright © 2020-2023  润新知