• 基于Spring Boot框架的员工管理系统(实现增删改查功能——项目整体流程超详细)


    提示:此项目仅作为本博主的学习笔记记录,不作为商品售卖,文中某个方法或单词或许会因为马虎写错,但本文重点讲的是思路,资源可找博主私聊


    前言

    CRUD是指在数据库中进行的基本操作,即创建(Create)、读取(Retrieve)、更新(Update)和删除(Delete)。
    在编程中,这些操作对应着对数据库中数据的增删改查。
    提示:此项目我用的是idea工具,具体的一些配置可以看下面的链接
    计算机专业、软件技术、工程等软件专业同学电脑必配环境

    如果想从零开始写请看下面的SpringBoot项目构建方式链接
    SpringBoot项目构建方式
    开始会有个初始压缩包,在这个初始压缩包内写代码
    在这里插入图片描述
    在这里插入图片描述

    进入初始项目后看到项目结构:
    请添加图片描述

    用户看的是View层视图层,数据从Controller/Action层过来

    Controller控制器通过接收前端传过来的参数进行业务操作,在返回一个指定的路径或者数据表直接调用Service,Service调用Mapper

    Service层, 存放业务逻辑处理,也是一些关于数据库处理的操作,但不是直接和数据库打交道,他有接口还有接口的实现方法,在接口的实现方法中需要导入mapper层,mapper层是直接跟数据库打交道的,他也是个接口,只有方法名字,具体实现在mapper.xml文件里,service是供我们使用的方法

    Service的 impl 文件将Mapper和Service进行整合

    Model层=entity层=pojo层,存放我们的实体类,与数据库中的属性值基本保持一致,与Mapper层连接

    mapper层=dao层,对数据库进行数据持久化操作(把数据放到持久化的介质中,同时提供增删改查操作), 他的方法语句直接针对数据库操作
    mapper的接口对应resources下的xml文件,它只有方法名,封装了对数据库进行的数据持久化操作

    其中还有个core文件夹,里面放的是工具类包括一些拦截器

    在这里插入图片描述


    提示:以下是本篇文章正文内容,下面案例可供参考

    本文SpringBoot 框架代码编写流程(看个人习惯,无硬性标准)
    1、画页面 HTML
    2、编写控制层代码的方法:Action / Controller
    3、编写数据持久层代码:Mapper + Mapper.xml(数据库)
    4、编写业务层代码:Service + Impl
    5、完善控制层代码的方法:Action / Controller

    关于Thymeleaf 前端

    目前Java比较流行的模板引擎有Thymeleaf和Freemarker,Thymeleaf的话更适合当前的人员分工问题,回忆一下以前的Jsp页面,必须要动态渲染才能看到真实的效果,写页面的和写后端的分工不太明确 。

    Thymeleaf是动静分离的,页面中的动态标签是需要传递有数据的时候才会渲染,不然就是原本默认的静态的样子 。
    Thymeleaf 快速入门
    Thymeleaf 官网

    后台做逻辑会有个绑定,传到前端设计的页面上,后台如果传过来数据就会用后台数据,如果后台没有数据,也能用静态的形式展示出来

    common文件夹介绍

    在这里插入图片描述
    LoginInterceptor登录拦截器,用于阻止未登录用户访问系统

    CrossOriginInterceptor拦截器

    在MyInterceptorConfig配置,interceptor实际上也是一种filter的实现 ,这里注册CrossOriginInterceptor拦截器,注册LoginInterceptor拦截器。并且所有路径都被拦截,除了静态不拦截路径

    //拦截器
    @Override
    	public void addInterceptors(InterceptorRegistry registry) {
    		// TODO Auto-generated method stub
    		WebMvcConfigurer.super.addInterceptors(registry);
    		// 注册CrossOriginInterceptor拦截器
    		registry.addInterceptor(new CrossOriginInterceptor());
    		// 注册LoginInterceptor拦截器
    		InterceptorRegistration registration = registry.addInterceptor(new LoginInterceptor());
    		registration.addPathPatterns("/**"); // 所有路径都被拦截
    		registration.excludePathPatterns( // 添加不拦截路径
    				"/", // 首页
    				"/user/login", // 登录
    				"/user/addUser", // 注册
    				"/user/checkUsername", // 检查用户名
    				"/**/*.html", // html静态资源
    				"/**/*.js", // js静态资源
    				"/**/*.css", // css静态资源
    				"/test/**" // css静态资源
    		);	
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    关于首页静态资源

    所有静态资源都需要thymeleaf接管

    可以在resources下创建目录处理静态资源,目录优先级是:resources > static(默认)> public

    测试:将静态资源文件放到resources/static/public或者**/****目录下资源都可以被访问, 比如在static下创建1.js文件,可以被访问localhost:8080/springbootdemo/1.js

    模板引擎: 将 html 页面放在 resources/templates 包下 ,在templates目录下的所有页面,可以通过controller来跳转。

    项目里使用了thymeleaf,所以得在pom.xml文件里加入thymeleaf 相关依赖

     <dependency>
         <groupId>org.thymeleafgroupId>
         <artifactId>thymeleaf-spring5artifactId>
    dependency>
    <dependency>
        <groupId>org.thymeleaf.extrasgroupId>
        <artifactId>thymeleaf-extras-java8timeartifactId>
    dependency>
    
    
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-thymeleafartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    一、SpringBoot整合Mybatis

    Mybatis简介

    1、添加Mybatis的起步依赖

    整合MyBatis

    
            <dependency>
                <groupId>org.mybatis.spring.bootgroupId>
                <artifactId>mybatis-spring-boot-starterartifactId>
                <version>2.1.0version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    添加数据库驱动坐标

    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、添加数据库连接信息

    application-dev.yaml中添加数据量的连接信息,因为在application.yaml中配置了active: dev,所以生产环境application-pro.yaml不用管,只需要改application-dev.yaml

    代码如下(示例):

    # 开发环境
    spring:
      #数据源配置
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/staff?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false
        username: root
        password: root
        hikari:
          maximum-pool-size: 2
          minimum-idle: 2
    
    #mybatis配置
    mybatis:
      #mapper配置文件
      config-location: classpath:mybatis-config.xml
      mapper-locations: classpath:mapper/*.xml
      type-aliases-package: cn.springbootdemo.model
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3、创建实体Bean

    接下来创建model层的User实体类

    第一种:创建User实体类

    我用的是这种
    把数据库表里的字段定义一下变量,鼠标右键生成 get、set方法,重写toString方法
    在这里插入图片描述

    package cn.springbootdemo.model;
    
    public class  User {
    	private int userid;
    	private String username;
    	private String password;
    	private String realname;
    	private String birthdate;
    	private String gender;
    	private String interest;
    	private String degree;
    	private String intro;
    	public int getUserid() {
    		return userid;
    	}
    	public void setUserid(int userid) {
    		this.userid = userid;
    	}
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    	public String getRealname() {
    		return realname;
    	}
    	public void setRealname(String realname) {
    		this.realname = realname;
    	}
    	public String getBirthdate() {
    		return birthdate;
    	}
    	public void setBirthdate(String birthdate) {
    		this.birthdate = birthdate;
    	}
    	public String getGender() {
    		return gender;
    	}
    	public void setGender(String gender) {
    		this.gender = gender;
    	}
    	public String getInterest() {
    		return interest;
    	}
    	public void setInterest(String interest) {
    		this.interest = interest;
    	}
    	public String getDegree() {
    		return degree;
    	}
    	public void setDegree(String degree) {
    		this.degree = degree;
    	}
    	public String getIntro() {
    		return intro;
    	}
    	public void setIntro(String intro) {
    		this.intro = intro;
    	}
    	@Override
    	public String toString() {
    		return "User [userid=" + userid + ", username=" + username + ", password=" + password + ", realname=" + realname
    				+ ", birthdate=" + birthdate + ", gender=" + gender + ", interest=" + interest + ", degree=" + degree
    				+ ", intro=" + intro + "]";
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    第二种:创建User实体类

    另外(为了方便使用先把lombok导入,在pom.xml中文件中加)

    <dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    User实体类

    package cn.springbootdemo.model;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    @Data   //加了这个注解get、set方法就不用写了
    @NoArgsConstructor
    @AllArgsConstructor   //无参构造和全参构造可以不加
    public class  User {
    	private int userid;
    	private String username;
    	private String password;
    	private String realname;
    	private String birthdate;
    	private String gender;
    	private String interest;
    	private String degree;
    	private String intro;
    	@Override   //重写toString
    	public String toString() {
    		return "User [userid=" + userid + ", username=" + username + ", password=" + password + ", realname=" + realname
    				+ ", birthdate=" + birthdate + ", gender=" + gender + ", interest=" + interest + ", degree=" + degree
    				+ ", intro=" + intro + "]";
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4、编写Mapper

    注意:@Mapper标记该类是一个mybatis的mapper接口,可以被spring boot自动扫描到spring上下文中

    与启动类同一级别创建mapper文件夹创建UserMapper接口
    在这里插入图片描述

    package cn.springbootdemo.mapper;
    
    import cn.springbootdemo.model.User;
    import org.apache.ibatis.annotations.Mapper;
    import org.springframework.stereotype.Repository;
    
    @Mapper//使用@Mapper注解,表示这是操作数据库的mapper,SpringBoot自动扫描
    //也可以在启动类里使用MapperScan("cn.springbootdemo.mapper")注解,参数是包名,一个效果
    // Dao层,所以可以使用@Repository,当然也可以使用Component注解,不写也OK
    @Repository
    public interface UserMapper {
    
        void addUser(User user);//注册
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    5、配置Mapper映射文件

    在resources文件夹下创建mapper文件夹,并创建UserMapper.xml文件
    在这里插入图片描述

    Mybatis中文文档官网:https://mybatis.net.cn/getting-started.html

    其中:

    1、namespace命名空间必须与@Mapper注解的Mapper接口的全类名一致
    这里的全类名要去UserMapper.java里面去找://全类名: cn.springbootdemo.mapper.UserMapper
    其中cn.springbootdemo.mapper就是第一行package后面的包
    然后UserMapper是这个.java的接口名

    2、xml文件名必须与@Mapper注解的接口名一致
    3、标签中的 id必须与@Mapper注解的的接口中的方法名一致,且参数一致

    这里需要确认:整合对应application-dev.yaml里type-aliases-package别名扫描包、mapper-locations 定义mapper位置 ,即加载Mybatis映射文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="cn.springbootdemo.mapper.UserMapper">
            <insert id="addUser" parameterType="User">
                insert into demo_users
                values(null,#{username},#{password},#{realname},#{birthdate},#{gender},#{interest},#{degree},#{intro})
            </insert>
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    接下来写service,定义一个UserService接口
    在这里插入图片描述

    @Service
    public interface UserService {
        int addUser(User user);
    
        List<User> getUserList(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后对应着写接口的实现类UserServiceImpl
    在这里插入图片描述

    但是service.impl下的两个文件是有层级关系的,我们把UserService放在上一层
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    最后:
    在这里插入图片描述

    6、定义controller

    定义service(以addUser为例) service.impl.UserServiceImpl

    刚才在UserMapper.java中有个addUser注册方法,然后这个注册方法映射到UserMapper.xml里面执行了SQL语句

    @Service //使用@Service注解,SpringBoot自动扫描
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserMapper mapper;
        
        @Override
        public int addUser(User user) {
            //默认执行成功
            mapper.addUser(user);
            return 0;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    7、创建UserAction类

    @Controller
    @RequestMapping("/user")
    public class UserAction {
          @Autowired
          private UserService userService;
    
          @RequestMapping("/addUser")
          public String addUser(User user, Map<String,String> m) {
              int f = userService.addUser(user);
              if (f == 0) {
                  m.put("msg","注册成功");
              }
              return "login";
          }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    现在我们运行一下看看结果
    请添加图片描述

    其中出生日期这里是可以选时间的,这里用了一个日期的校验,在home.html里
    在这里插入图片描述

    点击确定后显示的页面:
    在这里插入图片描述

    点击登录显示页面:
    在这里插入图片描述

    回到数据库可视化页面可以看到我刚刚加的这条数据:
    在这里插入图片描述

    如果数据库里没有更新数据,那就去数据库配置里面看:
    数据库名字或密码改没改
    在这里插入图片描述

    二、做首页

    ①、新建HomeAction类

    首先在action文件夹内新建HomeAction类
    SpringBoot中Controller控制层重要注解

    @Controller
    @RequestMapping("/") //URL
    public class HomeAction {
        @RequestMapping("/")// 直接访问http://localhost:8080/
        public String home(){
            return "home";
        }
    
        @RequestMapping("/login")// 访问http://localhost:8080/login
        public String login(){
            return "login";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    现在应该能显示首页了
    请添加图片描述

    ②、将页面转化为Thymeleaf形式

    现在是单纯的HTML页面,接下来把他转化为Thymeleaf形式,首先加入thymeleaf模板

    <!doctype html>
    <html lang="ch" xmlns:th="http://www.thymeleaf.org"> 
    
    </html>
    
    • 1
    • 2
    • 3
    • 4

    我们回到首页home.html
    把第2行的改成

    把第18行的本地文件

    改成Thymeleaf形式的:

    同样在22行把script src里面的内容也改成Thymeleaf形式的:

    接下来把我们把from表单中的确定按钮的onclick事件去掉(大约在172行),然后把类型button改成submit,当点击确定的时候就相当于把后台服务器 type类型进行提交

    //原来代码:
    <button class="btn btn-primary" type="button" onclick="addUser()">确定</button>
    //更改代码:
    <button class="btn btn-primary" type="submit">确定</button>
    
    • 1
    • 2
    • 3
    • 4

    当我们点击确定的时候,我们得把表单目的地址写上,回到 from表单起点位置(大约在41行),当点确定的时候需要对表单进行一个提交

    //原来代码:
    <form class="form" id="regForm"
    //更改代码:
    <form class="form" id="regForm" th:method="post" th:action="@{/user/addUser}">
    
    • 1
    • 2
    • 3
    • 4

    现在就把home页面改造成了Thymeleaf形式了


    home.html文件中用到了cdn加速(内容分发网络) 知识
    就是一个文件在全国各地都有服务器,可以用cdn的技术进行就近分配,以速度最优为原则;也有图片优化等等。需要的话可以进下面网址找相应版本
    cdn加速
    在这里插入图片描述

    ③、javascript的编写

    这里说的是验证的功能,做表单的时候一定要进行校验,小心被攻击,尤其是SQL注入的时候

    <script type="text/javascript">
    	$(function () {
    		$("#regForm").bootstrapValidator({
    			message: 'This value is not valid',
    			feedbackIcons: {
    				valid: 'glyphicon glyphicon-ok',
    				invalid: 'glyphicon glyphicon-remove',
    				validating: 'glyphicon glyphicon-refresh'
    			},
    			fields: {
    				username: {
    					message: '用户名验证失败',
    					validators: {
    						notEmpty: {
    							message: '用户名不能为空'
    						}
    					}
    				},
    				password: {
    					message: '密码验证失败',
    					validators: {
    						notEmpty: {
    							message: '密码不能为空'
    						}
    					}
    				},
    				password1: {
    					message: '密码确认验证失败',
    					validators: {
    						notEmpty: {
    							message: '密码确认不能为空'
    						}
    					}
    				},
    				realname: {
    					message: '姓名验证失败',
    					validators: {
    						notEmpty: {
    							message: '姓名不能为空'
    						}
    					}
    				}
    			}
    		});
    	});
    
    	$(document).ready(function () {
    		$("#regForm #username").blur(checkName);
    	});
    
    	function checkName() {
    		var username = $("#regForm #username").val();
    		if (username) {
    			$.post("./user/checkUsername",
    					{username: username},
    					function (data) {
    						if (data.result == "yes") {
    							$("#result").html("

    恭喜您,用户名未被注册,请继续!

    "
    ); } else { $("#result").html("

    对不起,用户名已被注册,请更换!

    "
    ); } }); /* $.ajax({ url : "${pageContext.request.contextPath}/user/checkName", type : "post", // data表示发送的数据 data :JSON.stringify({username:username}), // 定义发送请求的数据格式为JSON字符串 contentType : "application/json;charset=UTF-8", //定义回调响应的数据格式为JSON字符串,该属性可以省略 dataType : "json", //成功响应的结果 success : function(data){ if(data.result){ $("#result").html("

    恭喜您,用户名未被注册,请继续!

    "); }else{ $("#result").html("

    对不起,用户名已被注册,请更换!

    "); } } }); */
    } } </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    完整的home.html代码

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Insert title here</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>Hello, Bootstrap Table!</title>
        <!-- 最新 Bootstrap4 核心 CSS 文件 -->
        <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
    
        <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
        <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
        <!-- bootstrap.bundle.min.js 用于弹窗、提示、下拉菜单,包含了 popper.min.js -->
        <script src="https://cdn.staticfile.org/popper.js/1.16.0/umd/popper.min.js"></script>
        <!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
        <script src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
        <!-- DaterangePicker -->
        <link rel="stylesheet" type="text/css" media="all" th:href="@{/daterangepicker/daterangepicker.css}"/>
        <!-- BootStrapValidator -->
        <link rel="stylesheet"
              href="https://cdn.bootcss.com/jquery.bootstrapvalidator/0.5.3/css/bootstrapValidator.min.css">
        <script type="text/javascript"
                src="https://cdn.bootcss.com/jquery.bootstrapvalidator/0.5.3/js/bootstrapValidator.min.js"></script>
        <script th:src="@{/js/functions.js}"></script>
        <script type="text/javascript">
            $(function () {
                $("#regForm").bootstrapValidator({
                    message: 'This value is not valid',
                    feedbackIcons: {
                        valid: 'glyphicon glyphicon-ok',
                        invalid: 'glyphicon glyphicon-remove',
                        validating: 'glyphicon glyphicon-refresh'
                    },
                    fields: {
                        username: {
                            message: '用户名验证失败',
                            validators: {
                                notEmpty: {
                                    message: '用户名不能为空'
                                }
                            }
                        },
                        password: {
                            message: '密码验证失败',
                            validators: {
                                notEmpty: {
                                    message: '密码不能为空'
                                }
                            }
                        },
                        password1: {
                            message: '密码确认验证失败',
                            validators: {
                                notEmpty: {
                                    message: '密码确认不能为空'
                                }
                            }
                        },
                        realname: {
                            message: '姓名验证失败',
                            validators: {
                                notEmpty: {
                                    message: '姓名不能为空'
                                }
                            }
                        }
                    }
                });
            });
    
            $(document).ready(function () {
                $("#regForm #username").blur(checkName);
            });
    
            function checkName() {
                var username = $("#regForm #username").val();
                if (username) {
                    $.post("./user/checkUsername",
                        {username: username},
                        function (data) {
                            if (data.result == "yes") {
                                $("#result").html("

    恭喜您,用户名未被注册,请继续!

    "
    ); } else { $("#result").html("

    对不起,用户名已被注册,请更换!

    "
    ); } }); /* $.ajax({ url : "${pageContext.request.contextPath}/user/checkName", type : "post", // data表示发送的数据 data :JSON.stringify({username:username}), // 定义发送请求的数据格式为JSON字符串 contentType : "application/json;charset=UTF-8", //定义回调响应的数据格式为JSON字符串,该属性可以省略 dataType : "json", //成功响应的结果 success : function(data){ if(data.result){ $("#result").html("

    恭喜您,用户名未被注册,请继续!

    "); }else{ $("#result").html("

    对不起,用户名已被注册,请更换!

    "); } } }); */
    } } </script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-12"> <div class="text-center"> <a type="button" class="btn btn-outline-info" th:href="@{/user/getUserListWithPage}">查看所有用户信息</a> </div> </div> </div> <hr> <div class="row"> <div class="col-md-10 offset-md-1"> <form class="form" id="regForm" th:method="post" th:action="@{/user/addUser}"> <div class="modal-header"> <h4 class="modal-title">请填写注册信息</h4> </div> <div class="modal-body"> <div class="form-group row"> <div class="col-md-2"> <label for="username">用户名</label> </div> <div class="col-md-6"> <input type="text" id="username" name="username" class="form-control input-sm" placeholder="用户名" required/> <span id="result"></span> </div> </div> <div class="form-group row"> <div class="col-md-2"> <label for="password">密码</label> </div> <div class="col-md-6"> <input type="password" id="password" name="password" class="form-control input-sm" placeholder="密码" required/> </div> </div> <div class="form-group row"> <div class="col-md-2"> <label for="password1">密码确认</label> </div> <div class="col-md-6"> <input type="password" id="password1" name="password1" class="form-control input-sm" placeholder="密码确认" required/> </div> </div> <div class="form-group row"> <div class="col-md-2"> <label for="realname">姓名</label> </div> <div class="col-md-6"> <input type="text" id="realname" name="realname" class="form-control input-sm" placeholder="姓名"/> </div> </div> <div class="form-group row"> <div class="col-md-2"> <label for="birthdate">出生日期</label> </div> <div class="col-md-6"> <input type="text" id="birthdate" name="birthdate" class="form-control input-sm"> <script type="text/javascript" src="./daterangepicker/require.js" data-main="./daterangepicker/main.js"></script> </div> </div> <div class="form-group row"> <div class="col-md-2"> <label for="gender">性别</label> </div> <div class="col-md-6"> <div class="form-check form-check-inline"> <input type="radio" class="form-check-input" name="gender" value="1" checked> <label class="form-check-label" for="gender"></label> </div> <div class="form-check form-check-inline"> <input type="radio" class="form-check-input" name="gender" value="0"> <label class="form-check-label" for="gender"></label> </div> </div> </div> <div class="form-group row"> <div class="col-md-2"> <label for="interest">爱好</label> </div> <div class="col-md-6"> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input" name="interest" value="旅游"> <label class="form-check-label" for="interest">旅游</label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input" name="interest" value="登山"> <label class="form-check-label" for="interest">登山</label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input" name="interest" value="健身"> <label class="form-check-label" for="interest">健身</label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input" name="interest" value="上网"> <label class="form-check-label" for="interest">上网</label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input" name="interest" value="游泳"> <label class="form-check-label" for="interest">游泳</label> </div> </div> </div> <div class="form-group row"> <div class="col-md-2"> <label for="degree">学历</label> </div> <div class="col-md-6"> <select id="degree" name="degree" class="form-control"> <option value="0" selected>--请选择--</option> <option value="1">高中</option> <option value="2">专科</option> <option value="3">本科</option> <option value="4">研究生</option> </select> </div> </div> <div class="form-group row"> <div class="col-md-2"> <label for="intro">自我介绍</label> </div> <div class="col-md-6"> <textarea name="intro" rows="5" cols="20" class="form-control"></textarea> </div> </div> </div> <div class="modal-footer"> <div class="form-group"> <div class="text-center"> <button class="btn btn-primary" type="submit">确定</button> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <button class="btn btn-secondary" type="reset">重置</button> </div> </div> </div> </form> </div> </div> </div> </body> </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266

    1、注册页面的完善(增)

    接下来我们把注册功能完善下,因为用户注册后不可能去看数据库,我们要有个显示页面,显示注册成功还是失败,而且在注册时我们是默认他是注册成功的,实际情况下注册的用户名是一不一样? 注册完后还有个返回首页,注册成功后要有个登录功能

    1、我们先写注册失败的代码,在UserAction里面:

     public String addUser(User user, Map<String,String> m) {
              int f = userService.addUser(user);
              if (f == 0) {
                  m.put("result","yes");
                  m.put("msg","注册成功");
              }else if(f==1){
                  m.put("result","no");
                  m.put("msg","注册失败,用户名重复");
              }else {
                  m.put("result","no");
                  m.put("msg", "注册失败,数据库错误");
              }
              return "login";
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    我们之前写得 f==0,f在userService里来的,userService这有个addUser方法
    之前addUser只是返回0,现在我们让他返回1或2

    2、我们回到UserService:
    UserService已经有一个addUser接口了,他具体的实现在UserServiceImpl内
    在这里插入图片描述

    我们就去看UserServiceImpl,在这里面我们要加一些其他的方法
    比如先看注册失败,用户名重复,这个错误
    在里面加个try catch语句,如果有错误就用catch语句捕获这个Exception异常并打印

    3、我们先判断这个数据库有没有这个用户,对数据库进行一个查询操作
    在mapper包下的UserMapper接口中加入下面代码

     //查询有没有这个用户:0011
        int existUser(User user);///1、使用count查以0011为名字的用户
        User existsUser(User user);//2、查以0011为名字的用户
    
    • 1
    • 2
    • 3

    接下来去UserMapper.xml里面写数据库查询操作语句
    先写第一个:使用count查以0011为名字的用户

        <select id="existUser" parameterType="User" resultType="int">
            select count(*) from demo_users where username = #{username}
        </select>
         <!--第一个:使用count查以0011为名字的用户,上面的username是变量-->
    
    • 1
    • 2
    • 3
    • 4

    但是查询语句对不对呢?这时候可以打开idea内显示图形化页面,然后把查询语句复制进去验证
    在这里插入图片描述
    值得注意的是:select count(*) from demo_users where username = #{username}中的 #{username}是个变量
    比如说我们查询以0011为名字的:select count(*) from demo_users where username = '0011'
    在这里插入图片描述

    count这里返回1,说明有一个用户的名字是0011
    当然count也可以不做统计,把以0011做名字的用户返回回来:select * from demo_users where username = '0011'
    在这里插入图片描述
    下面接着写第二个:查以0011为名字的用户

        <select id="existsUser" parameterType="User" resultType="User">
            select userid,username from demo_users where username=#{username} and password=#{password}
        </select>
        <!--第二个:查以0011为名字的用户,username和password是变量,
        在图形化页面中的查询语句是:select userid,username from demo_users where username='0011' and password='0011'
        -->
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4、现在我们就可以在UserServiceImpl 里面写 try catch语句了,当然前面写得默认注册成功就要删掉了

    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserMapper mapper;
        @Override
        public int addUser(User user) {
          //  默认执行成功
          //  mapper.addUser(user);
          //  return 0;
            try{
                //如果你的数据库没有这个用户返回0,否则返回1
                if(mapper.existUser(user)==0){
                    return 0;  //用户不存在,可以注册
                }else{
                    return 1;  //用户存在,不可注册
                }
            }catch (Exception e){
                e.printStackTrace();
                return 2; //如果报错返回2
            }
        }
    
        @Override
        public List<User> getUserList(User user) {
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    5、现在注册功能就写得差不多了,但是在UserAction中我们写的是返回login页面,我们应该让他返回到 result结果页面
    我是复制的home.html,再粘贴到user文件夹下,重命名为:result.html
    请添加图片描述
    所以在UserAction最后一行返回login改成:return "user/result";
    把 result.html里面的代码改成:

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
    	<title>Insert title here</title>
    	<meta charset="UTF-8">
    	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    	<title>Hello, Bootstrap Table!</title>
    	<!-- 最新 Bootstrap4 核心 CSS 文件 -->
    	<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
    
    	<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    	<script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
    	<!-- bootstrap.bundle.min.js 用于弹窗、提示、下拉菜单,包含了 popper.min.js -->
    	<script src="https://cdn.staticfile.org/popper.js/1.16.0/umd/popper.min.js"></script>
    	<!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
    	<script src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
    	<!-- DaterangePicker -->
    	<link rel="stylesheet" type="text/css" media="all" th:href="@{/daterangepicker/daterangepicker.css}"/>
    	<!-- BootStrapValidator -->
    	<link rel="stylesheet"
    		  href="https://cdn.bootcss.com/jquery.bootstrapvalidator/0.5.3/css/bootstrapValidator.min.css">
    	<script type="text/javascript"
    			src="https://cdn.bootcss.com/jquery.bootstrapvalidator/0.5.3/js/bootstrapValidator.min.js"></script>
    	<script th:src="@{/js/functions.js}"></script>
    
    </head>
    <body style="margin: 200px">
    <div class="container-fluid">
    	<div class="row">
    		<div class="m-auto">
    			<p class = "text-success" th:if="${result=='yes'}"><span th:text="${msg}"></span></p>
    			<p class = "text-danger" th:if="${result=='no'}"><span th:text="${msg}"></span></p>
    		</div>
    	</div>
    </div>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    这时候我们再重新运行下,再注册一个数据库里有的名字
    在这里插入图片描述
    点击确定后:
    在这里插入图片描述

    6、现在注册不成功的结果出来了,但是页面太简单了,起码有个跳转加个超链接,不可能让用户按左上角返回箭头返回,无论注册成功与否都要有个超链接,让他跳转一下
    所以接着写result.html页面:

    	<div class = "row">
    		<div class="m-auto">
    			<a th:href="@{/}">返回首页</a>
    			<a th:href="@{/user/getUserList}">查看所有用户</a>
    		</div>
    	</div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后就多了这两个超链接,点进去后他们显示的页面也分别放在了下面
    在这里插入图片描述

    在点查看用户的时候显示的是:
    {“login”:“请先登录”,“redirUrl”:“/user/getUserList”}
    要求先登录,跳转的路径是/user/getUserList,假如要在做其他的东西,必须要把login这个功能做了,否则他都会拦截
    在common文件夹里有个LoginInterceptor.java(拦截器功能)
    在这里插入图片描述

    在新的页面中可以看到:他的要求就是请先登录
    在这里插入图片描述

    2、登录功能(查)

    我们先把LoginInterceptor.java(拦截器功能)里面最后几行注释掉,这几行是输出流的功能
    需要注释的代码:
    在这里插入图片描述
    我们在这注释代码下面做一个跳转到登录页面的功能:

    arg0.getRequestDispatcher("login").forward(arg0,arg1);
    
    • 1

    再运行下:
    还是先显示注册页面,添加信息
    在这里插入图片描述
    然后这次点击查看所有用户
    在这里插入图片描述
    然后就跳转到 login页面了
    在这里插入图片描述

    注册前的检测

    这个功能就是在你注册这个用户前检测数据库有没有这个用户名
    这个功能的实现的逻辑在home.html页面内
    在这里插入图片描述
    1、我们回到UserAction里写checkUsername这个函数

        @ResponseBody
        @RequestMapping("/checkUsername")
        public Map<String, String> checkUsername(User user) {
            System.out.println("checkUsername=================" + user);
            boolean f = userService.checkUsername(user); //可以注册
            Map<String, String> m = new HashMap<String,String>();
            if (f) {
                m.put("result", "yes");
                m.put("msg", "");
            } else {
                m.put("result", "no");
                m.put("msg", "对不起,该用户名已存在,请更换");
            }
            System.out.println("checkUsername : " + m);
            return m;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2、这时候我们可以看到checkUsername这里有个报错,我们把鼠标放上去后点击红色的提示,在UserService里面创建这个checkUsername方法,它会自动生成
    自动生成的那行代码的意思是:根据用户名判断是否有该用户,如果没有则可以注册
    在这里插入图片描述
    3、这时候UserServiceImpl类中有个报错,我们【Alt+回车】导入这个方法即可
    然后在这里面写个简单的逻辑:
    如果existUser(user)==0就是没有注册,如果 !=0 就是已经注册了

      @Override
        public boolean checkUsername(User user) {
            if(mapper.existUser(user)==0){
                return true;
            }else{
            return false;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行截图:
    在这里插入图片描述
    在这里插入图片描述

    登录功能的编写

    1、我们现在统一一下 login.html页面
    完整的 login.html代码

    里面就是一个表单和俩按钮

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Insert title here</title>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title></title>
        <!-- 最新 Bootstrap4 核心 CSS 文件 -->
        <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
        <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
        <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
        <!-- bootstrap.bundle.min.js 用于弹窗、提示、下拉菜单,包含了 popper.min.js -->
        <script src="https://cdn.staticfile.org/popper.js/1.16.0/umd/popper.min.js"></script>
        <!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
        <script src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
        <script th:src="@{/js/functions.js}"></script>
        <script type="text/javascript" th:inline="javascript">
            $(document).ready(
                function () {
                    $('#loginFormModal').modal();
                }
            );
        </script>
    </head>
    <body>
    <div class="modal fade" id="loginFormModal" role="dialog" aria-hidden="true" aria-labelledby="myModalLabel">
        <div class="modal-dialog">
            <div class="modal-content">  <!-- 对loginForm这个表单进行提交,提交方式是post,提交路径是/user/login -->
                <form class="form-signin" id="loginForm" th:method="post" th:action="@{/user/login}">
                    <div class="modal-header">
                        <h5 class="modal-title" id="myModalLabel">用户登录</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        <label for="username" class="sr-only">用户名</label>
                        <input type="text" id="username" name="username" class="form-control"
                               placeholder="用户名" required autofocus>
                        <label for="password" class="sr-only">密码</label>
                        <input type="password" id="password" name="password" class="form-control"
                               placeholder="密码" required>
                        <div class="text-danger" th:text="${login!='yes'?login:''}"></div>
                    </div>
                    <div class="modal-footer">
    
                        <button class="btn btn-primary" type="submit" id="loginBtn">登录</button>
                        <button class="btn btn-secondary" type="button" data-dismiss="modal">关闭窗口</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    我们现在需要写一个http://localhost:8080/springbootdemo/user/login这样的URL,到这个里面写逻辑

    2、我们直接进到action这个页面,写user/login这个逻辑

    1. 查数据库有没有这个人
    2. 如果有就登入,登录信息存起来,跳转到目标页
    3. 没有还得回到登录页

    因为我们在UserMapper接口里面已经定义完了,所以我们先进到UserService接口里面查有没有这个人
    在这里插入图片描述
    3、UserService接口内新增代码:User existsUser(User user);

    然后到UserServiceImpl实现类里面【Alt+回车】把这个方法加进来
    其实就是向数据库查,查有没有这个人,查询的语句写过了,我们调用一下就行:return mapper.existsUser(user);

    4、现在就可以到 action里面写逻辑了

    //登录功能
        @RequestMapping("/login") //目标地址
        public String login(User user, HttpSession session, Map<String, String> m) {
            //1、查数据库有没有这个人
            User dbUser=userService.existsUser(user);
            //2、如果有就登入,登录信息存起来,跳转到目标页
            if(dbUser !=null){
                session.setAttribute(Constants.LOGIN_USER,dbUser);  //存起来
                m.put("login","yes");
               String redirUrl = (String) session.getAttribute(Constants.ORIGINAL_URL);
               return "/redirect"+redirUrl;
            }else{
            //3、没有还得回到登录页
                m.put("login",Constants.LOGIN_ERR);
            return "/login";
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    其中Constants. 后面的名字在core文件夹下的Constants类里面找,或者在这里面改
    在这里插入图片描述

    运行后查看所有用户后登录:
    在这里插入图片描述

    3、显示用户表格页面(查)

    紧接上图,因为user/getUserList还没写,他就是向后台拿所有的用户信息,把所有的用户拿到后存到一个list里面,然后通过前端Thymeleaf把他渲染出来

    1、我们接着去UserAction里面去写getUserList

        @RequestMapping("/getUserList")
        public String getUserList(User user, Map<String, List<User>> m) {
            //向数据库查询user信息,存储到list里,再把list放到map里
             return "user/userList";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、我们现在还没有 userList页面,需要创建一个
    我直接就把 user文件夹下的 result.html复制了一下,重新粘回 user文件夹下,重命名为:userList.html
    在这里面随便写点东西,看看能不能返回
    在运行程序后,填写注册信息后点击确定,选择查看所有用户
    在这里插入图片描述
    可以看到里面已近有返回了

    3、我们接着写UserAction里的逻辑,我们向数据库查,是操作xml文件,在这里面进行数据库的增删改查,对应的Mapper接口文件里定义查询规则

    首先在mapper文件夹下的UserMapper里面定义规则 List

        List<User> getUserList(User user); //查询数据库里面所有用户信息
    
    • 1

    4、然后到UserMapper.xml 里面写查询语句:
    我们不仅要查全部的,还要有模糊查询(用户名、性别)

        <select id="getUserList" parameterType="User" resultType="User">
            select  * from demo_users
            <where>
                <if test = "username != null and username != ''">
                    and username like concat('%',#{username},'%')
                      <!-- SELECT * FROM demo_users WHERE username LIKE CONCAT('%','a','%')
                        这条语句是在图形可视化页面查找用户名带a的 -->
                </if>
                <if test = "gender != null and gender != ''">
                    and gender = #{gender}
                </if>
            </where>
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    5、接着就在service定义接口,然后在接口实现类把他的逻辑写出来
    首先在service文件夹下的UserService接口里面写接口:

    List<User> getUserList(User user);//查询用户信息,存到list里
    
    • 1

    然后在实现类impl文件夹下的UserServiceImpl里面(导包),把返回值改一下:

    return mapper.getUserList(user);
    
    • 1

    6、接着回到controller里面写逻辑

        @RequestMapping("/getUserList")
        public String getUserList(User user, Map<String, List<User>> m) {
            //向数据库查询user信息,存储到list里,再把list放到map里
            //Mapper定义规则List,在xml里查询
            List<User> userList = userService.getUserList(user);
            System.out.println("userList----:"+userList);//sout快捷键
            return "user/userList";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    随后我们运行程序,输入注册信息后点击查看所有用户,再点击登录:
    能显示页面
    并且回到控制台看到有输出,证明已经从后台已经读到user了,并且存到list了
    在这里插入图片描述

    现在已经拿到userList了,接着存到map里面
    在 return “user/userList”; 上面写:

            m.put("userList",userList);
            System.out.println("m----:"+m);//sout快捷键
    
    • 1
    • 2

    随后我们运行程序,输入注册信息后点击查看所有用户,再点击登录:
    能显示页面
    并且回到控制台看到m也有输出
    在这里插入图片描述

    7、下面就到前端去做userList页面渲染
    这里用到了bootstrap表格

    <body style="margin: 200px">
    <div class="container-fluid" >
    	<div class="row">
    		<div class="col-md-12" >
    			<table class="table table-bordered">
    				<caption>边框表格布局</caption>
    				<thead>
    				<tr>
    					<th>用户名</th>
    					<th>真名</th>
    					<th>生日</th>
    					<th>性别</th>
    					<th>兴趣爱好</th>
    					<th>学历</th>
    					<th>自我介绍</th>
    					<th>操作</th>
    				</tr>
    				</thead>
    				<tbody>
    				<tr>
    					<td>Tanmay</td>
    					<td>Bangalore</td>
    					<td>560001</td>
    					<td>Tanmay</td>
    					<td>Bangalore</td>
    					<td>560001</td>
    					<td>Tanmay</td>
    					<td>Bangalore</td>
    				</tr>
    				</tbody>
    			</table>
    		</div>
    	</div>
    </div>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    刚才在controller里面已经能从数据库查的数据,这个userList,这个数据拿到后已经能存到map里面了,而且map在做页面跳转的时候通过键值对的形式已经把userList传递给user/userList页面了
    我们拿到数据后对userList做循环(对数据做循环):th:each="tag:${user.getTags()}"

    所以userList页面里面的body代码改成:

    <body style="margin: 200px">
    <div class="container-fluid" >
    	<div class="row">
    		<div class="col-md-12" >
    			<table class="table table-bordered">
    				<caption>边框表格布局</caption>
    				<thead>
    				<tr>
    					<th>序号</th>
    					<th>用户名</th>
    					<th>真名</th>
    					<th>生日</th>
    					<th>性别</th>
    					<th>兴趣爱好</th>
    					<th>学历</th>
    					<th>自我介绍</th>
    					<th>操作</th>
    				</tr>
    				</thead>
    				<tbody>
    				<tr th:each="user,stat:${userList}">
    					<td th:text="${stat.count}">1</td>
    					<td th:text="${user.username}">Tanmay</td>
    					<td th:text="${user.realname}">二哈喇子</td>
    					<td th:text="${user.birthdate}">2022-09-08</td>
    					<td th:text="${user.gender == '1'?'男':'女'}">1</td>
    					<td th:switch="${user.degree}">
    						<span th:case="'0'">高中</span>
    						<span th:case="'1'">专科</span>
    						<span th:case="'2'">本科</span>
    						<span th:case="'3'">研究生</span>
    					</td>
    					<td th:text="${user.intro}">本人积极向上</td>
    					<td>
    						<a href="#">修改</a>
    						<a href="#">删除</a>
    					</td>
    
    				</tr>
    				</tbody>
    			</table>
    		</div>
    	</div>
    </div>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    随后我们运行程序,输入注册信息后点击查看所有用户,看到的显示用户表格页面
    在这里插入图片描述

    模糊查询和返回首页按钮功能

    我们继续完善该页面,加入模糊查询和返回首页按钮
    模糊查询代码:

    放在

    之上

    	    <hr>
    	    <div class="row">
    	        <div class="col-md-12">
    	            <form class="form-inline" role="form" id="searchForm" th:method="post" th:action="@{/user/getUserList}">
    	                <div class="form-group col-md-2 offset-1">
    	                    <input class="form-control input-sm" type="text" id="username" name="username" placeholder="用户名"
    						th:value="${param.username}"/>
    	                </div>
    	                <div class="form-group col-md-2">
    	                    <select class="form-control input-sm" id="gender" name="gender" >
    	                        <option value="">---不限制性别---</option>
    	                        <option value="1" th:selected="${#strings.trim(param.gender)=='1'}"></option>
    	                        <option value="0" th:selected="${#strings.trim(param.gender)=='0'}"></option>
    	                    </select>
    	                </div>
    	                <div class="form-group col-md-1">
    	                    <button class="btn btn-primary btn-sm" type="submit" >搜索</button>
    	                </div>
    	            </form>
    	        </div>
    	    </div>
    	    <hr>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    返回首页按钮代码

    放在表格之下

    	    <hr>
    	    <div class="row">
    	        <div class="col-md-12">
    	            <div class="text-center">
    	                <a type="button" class="btn btn-outline-info" th:href="@{/}">返回首页</a>
    	            </div>
    	        </div>
    	    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    页面显示:
    在这里插入图片描述
    模糊查询功能实现页面
    在这里插入图片描述
    在这里插入图片描述
    返回首页功能页面
    在这里插入图片描述


    三、修改用户

    在点击修改按钮后(userList页面)→在action里写逻辑:弹出新页面 edit.html →新页面里显示已经有的用户信息→使用表单元素展示(输入框)展示已有信息→修改信息→点击表单的提交→@{/user/updateUser}(方法)→数据库进行更新(service→mapper→xml)→在页面返回结果 result

    1、入口地址:userList.html中:

    代码如下(示例):

    <a th:href="@{/user/getUser(userid=${user.userid})}">修改</a>
    
    • 1

    2、写修改功能的第一步的Controller层代码:
    UserAction.java的getUser()方法:

    代码如下(示例):

    //查询用户信息,弹出新页面edit.html
        @RequestMapping( "/getUser")
        public String getUser(String userid,Map<String,String> m) {
            //返回跳转地址
            return "/user/edit";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、写修改功能的第一步的View层代码:
    edit.html: 我是随便写了点,看能不能显示

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
      <title>Insert title here</title>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      <title>Hello, Bootstrap Table!</title>
      <!-- 最新 Bootstrap4 核心 CSS 文件 -->
      <link rel="stylesheet" th:href="@{//cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css}">
      <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
      <script th:src="@{//cdn.staticfile.org/jquery/3.4.1/jquery.min.js}"></script>
      <!-- bootstrap.bundle.min.js 用于弹窗、提示、下拉菜单,包含了 popper.min.js -->
      <script th:src="@{//cdn.staticfile.org/popper.js/1.16.0/umd/popper.min.js}"></script>
      <!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
      <script th:src="@{//cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js}"></script>
      <!-- DaterangePicker -->
      <link rel="stylesheet" type="text/css" media="all" th:href="@{/daterangepicker/daterangepicker.css}" />
      <!-- BootStrapValidator -->
      <link rel="stylesheet" th:href="@{/css/bootstrapValidator.css}">
      <script type="text/javascript" th:src="@{/js/bootstrapValidator.js}"></script>
      <script th:src="@{/js/functions.js}"></script>
      <script type="text/javascript" th:src="@{/js/validate.js}"></script>
      <script type="text/javascript">
        $(document).ready(function() {
          validateForm("editForm");
        });
      </script>
    </head>
    <body>
    <div class="container-fluid">
      <div class="row">
        <div class="col-md-12">
          <div class="text-center">
            <a type="button" class="btn btn-outline-info" th:href="@{/user/getUserList}">查看所有用户信息</a>
          </div>
        </div>
      </div>
      <hr>
    </div>
    
      <div class="row">
        <div class="col-md-10 offset-md-1">
          <form class="form" id="editForm" th:method="post" th:action="@{/user/updateUser}">
            <input type="hidden" name="userid" th:value="${user.userid}">
            <div class="modal-header">
              <h4 class="modal-title">请填写修改信息</h4>
            </div>
            <div class="modal-body">
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="username">用户名</label>
                </div>
                <div class="col-md-6">
                  <input type="text" id="username" name="username" th:value="${user.username}"
                         class="form-control input-sm" placeholder="用户名" required readonly/> <span
                        id="result"></span>
                </div>
              </div>
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="password">密码</label>
                </div>
                <div class="col-md-6">
                  <input type="password" id="password" name="password" th:value="${user.password}"
                         class="form-control input-sm" placeholder="密码" required />
                </div>
              </div>
    
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="password1">密码确认</label>
                </div>
                <div class="col-md-6">
                  <input type="password" id="password1" name="password1" th:value="${user.password}"
                         class="form-control input-sm" placeholder="密码确认" required />
                </div>
              </div>
    
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="realname">姓名</label>
                </div>
                <div class="col-md-6">
                  <input type="text" id="realname" name="realname"
                         th:value="${user.realname}" class="form-control input-sm" placeholder="姓名" />
                </div>
              </div>
    
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="birthdate">出生日期</label>
                </div>
                <div class="col-md-6">
                  <input type="text" id="birthdate" name="birthdate"  th:value="${user.birthdate}"
                         class="form-control input-sm">
                  <script type="text/javascript"
                          src="./daterangepicker/require.js"
                          data-main="./daterangepicker/main.js"></script>
                </div>
              </div>
    
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="gender">性别</label>
                </div>
                <div class="col-md-6">
                  <div class="form-check form-check-inline">
                    <input type="radio" class="form-check-input" name="gender"
                           value="1" th:checked="${user.gender}==1"> <label class="form-check-label"
                                                                            for="gender"></label>
                  </div>
                  <div class="form-check form-check-inline">
                    <input type="radio" class="form-check-input" name="gender"
                           value="0" th:checked="${user.gender}==0"> <label class="form-check-label"
                                                                            for="gender"></label>
                  </div>
                </div>
              </div>
    
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="interest">爱好</label>
                </div>
                <div class="col-md-6">
                  <div class="form-check form-check-inline">
                    <input type="checkbox" class="form-check-input" name="interest"	value="旅游" th:checked="${#strings.contains(user.interest,'旅游')}" >
                    <label class="form-check-label"	for="interest">旅游</label>
                  </div>
                  <div class="form-check form-check-inline">
                    <input type="checkbox" class="form-check-input" name="interest"	value="登山" th:checked="${#strings.contains(user.interest,'登山')}">
                    <label class="form-check-label"	for="interest">登山</label>
                  </div>
                  <div class="form-check form-check-inline">
                    <input type="checkbox" class="form-check-input" name="interest"	value="健身" th:checked="${#strings.contains(user.interest,'健身')}">
                    <label class="form-check-label"	for="interest">健身</label>
                  </div>
                  <div class="form-check form-check-inline">
                    <input type="checkbox" class="form-check-input" name="interest"	value="上网" th:checked="${#strings.contains(user.interest,'上网')}">
                    <label class="form-check-label"	for="interest">上网</label>
                  </div>
                  <div class="form-check form-check-inline">
                    <input type="checkbox" class="form-check-input" name="interest"	value="游泳" th:checked="${#strings.contains(user.interest,'游泳')}">
                    <label class="form-check-label"	for="interest">游泳</label>
                  </div>
                </div>
              </div>
    
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="degree">学历</label>
                </div>
                <div class="col-md-6">
                  <select id="degree" name="degree" class="form-control">
                    <option value="0" selected>--请选择--</option>
                    <option value="1" th:selected="${user.degree}==1">高中</option>
                    <option value="2" th:selected="${user.degree}==2">专科</option>
                    <option value="3" th:selected="${user.degree}==3">本科</option>
                    <option value="4" th:selected="${user.degree}==4">研究生</option>
                  </select>
                </div>
              </div>
    
              <div class="form-group row">
                <div class="col-md-2">
                  <label for="intro">自我介绍</label>
                </div>
                <div class="col-md-6">
                  <textarea name="intro" rows="5" cols="20" class="form-control">[[${user.intro}]]</textarea>
                </div>
              </div>
            </div>
            <div class="modal-footer">
              <div class="form-group">
                <div class="text-center">
                  <button class="btn btn-primary" type="submit">确定</button>
                  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                  <button class="btn btn-secondary" type="reset">重置</button>
                </div>
              </div>
            </div>
          </form>
        </div>
      </div>
    </div>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186

    4、写修改功能的第一步的Mapper层代码:
    UserMapper.java(接口)的getUser()方法(抽象方法):

    User getUser(String userid);
    
    • 1

    写修改功能的第一步的Mapper层xml代码:
    UserMapper.xml(实现文件):

        <select id="getUser" resultType="User">
            select * from demo_users where userid=#{userid}
        </select>
    
    • 1
    • 2
    • 3

    5、写修改功能的第一步的Service层代码:
    UserService.java(接口)的 getUser()方法(抽象方法):

    User getUser(String userid);
    
    • 1

    写修改功能的第二步的Service层实现类代码:
    UserServiceImpl.java(实现类)的getUser()方法(具体方法):

        @Override
        public User getUser(String userid) {
            return mapper.getUser(userid);
        }
    
    • 1
    • 2
    • 3
    • 4

    6、最后写修改功能的控制层代码:
    UserAction.java的getUser()方法:

       //查询用户信息,弹出新页面edit.html
        @RequestMapping( "/getUser")
        public String getUser(String userid,Map<String,User> m) {
            System.out.println("getUser-----------------------:");
            //调用业务层方法(根据userid查找用户信息)
            User user= userService.getUser(userid);
            m.put("user",user);
            //返回跳转地址
            return "/user/edit";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7、写修改功能的第二步的Mapper层方法:
    UserMapper.java(接口)的updateUser方法(抽象方法):

    void updateUser(User user);
    
    • 1

    UserMapper.xml(实现文件):

        <update id="updateUser">
            update demo_users set username=#{username},password=#{password},realname=#{realname},
                birthdate=#{birthdate},gender=#{gender},interest=#{interest},
                degree=#{degree} ,intro=#{intro} where userid=#{userid}
        </update>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    8、写修改功能的第二步的业务层代码:
    UserService的 updateUser方法(抽象方法):

    boolean updateUser(User user);
    
    • 1

    UserServiceImpl的updateUser方法(具体方法):

        @Override
        public boolean updateUser(User user) {
            try{
                mapper.updateUser(user);
                return true;
            }catch (Exception e){
                e.printStackTrace();
                return false;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    9、最后在action里继续写updateUser方法

        @RequestMapping( "/updateUser")
        public String updateUser(User user, Map<String, String> m) {
            boolean f=userService.updateUser(user);
            if(f) {
                m.put("result", "yes" ) ;
                m.put("msg","恭喜您,修改成功");
            }else {
                m.put("result","no");
                m.put("msg","对不起,修改失败");
            }
            return "/user/result";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    页面显示:

    我们运行程序,输入注册信息后点击查看所有用户后,看到的显示用户表格页面
    在这里插入图片描述
    在这里插入图片描述
    显示:修改成功,再点击查看所有用户
    在这里插入图片描述
    在这里插入图片描述

    四、删除用户

    1、首先在UserList.html中加入删除按钮

    <a th:href="@{/user/deleteUser(userid=${user.userid}) }" onclick="return confirm('确认删除吗?')">删除</a>
    
    • 1

    2、写删除功能的Controller层代码:
    UserAction.java的deleteUser()方法:

    //删除用户信息
        @RequestMapping( "/deleteUser")
        public String deleteUser(String userid, Map<String,User> m) {
        
                return "/user/result";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、写删除功能的Mapper层代码:
    UserMapper.java(接口)的deleteUser()方法(抽象方法):

    void deleteUser(User user);
    
    • 1

    UserMapper.xml(实现文件):

        <delete id="deleteUser">
            delete from demo_users where userid=#{userid}
        </delete>
    
    • 1
    • 2
    • 3

    4、写删除功能的Service层代码:
    UserService.java(接口)的deleteUser()方法(抽象方法):

    boolean deleteUser(User user);
    
    • 1

    UserServiceImpl.java(实现类)的deleteUser()方法(具体方法):

        @Override
        public boolean deleteUser(User user) {
            try{
                mapper.deleteUser(user);
                return true;
            }catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5、回到action里面继续写删除逻辑

        //删除用户信息
        @RequestMapping( "/deleteUser")
        public String deleteUser(User user, Map<String,String> m) {
            boolean f=userService.deleteUser(user);
            if(f) {
                m.put("result", "yes" ) ;
                m.put("msg","恭喜您,用户删除成功");
            }else {
                m.put("result","no");
                m.put("msg","对不起,用户删除失败");
            }
            return "/user/result";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述
    然后会提示数据删除成功
    请添加图片描述
    数据没有了
    请添加图片描述


    源码获取:

    提示:此项目仅作为本博主的学习笔记记录,不作为商品售卖,文中某个方法或单词或许会因为马虎写错,但本文重点讲的是思路

    点击此处转到源码地址:
    基于Spring Boot框架的员工管理系统的设计与实现

    • Gitee提取地址:

    Springboot员工管理系统初始框架

    Springboot员工管理系统完整框架
    在这里插入图片描述

  • 相关阅读:
    Linux 设置cd后自动ls、快捷键自动跳转指定目录或操作
    以太网基础——DoIP报文类型
    使用HikariCP连接池常用配置讲解及注意事项
    < Python全景系列-7 > 提升Python编程效率:模块与包全面解读
    登录实现【Security(登录)+Oauth2(颁发授权码/Token)+JWT(加密Token)】
    软件测试/测试开发丨利用人工智能ChatGPT批量生成测试数据
    Ansible自动化运维工具(二)
    【牛客网面试必刷TOP101】链表篇(一)
    读书笔记 |余华 | 文城
    Couldn‘t terminate the existing process for xxx
  • 原文地址:https://blog.csdn.net/rej177/article/details/126863867