笑看天下无敌手 发表于 2024-2-24 02:06:26

Spring Boot学习随笔- JSP小项目-员工管理系统(验证码生成、增删改查)

学习视频:【编程不良人】2021年SpringBoot最新最全教程
第十章、项目开发

实现一个登录注册,增删改查功能的系统
10.1 项目开发流程


[*]需求分析
分析用户主要需求 提取项目核心功能,根据核心功能构建页面原型
[*]库表设计:

[*]分析系统有哪些表
[*]分析表之间关联关系
[*]确定字段

[*]详细设计(流程图、伪代码):
验证库表准确性
[*]功能实现(编码)
环境搭建,具体功能实现
[*]功能测试,部署,上线,运维,维护
全栈式开发:前端+后端+运维
10.2 需求分析


[*]系统有哪些模块?
[*]每个模块功能有哪些?
[*]用户模块:登录、注册、验证码生成
[*]员工模块:查询、删除、更新、添加

10.3 库表设计

用户表:user
员工表:employee
表与表关系:user,employee 独立两张表
创建库表
create database ems;
use ems;
create TABLE user(
id int auto_increment,username VARCHAR(40) COMMENT '用户名' ,
realname VARCHAR(40) COMMENT '真实姓名' ,
`password` VARCHAR(50) COMMENT '密码',gender TINYINT(3) COMMENT '性别',
PRIMARY KEY (`id`)
);

create TABLE employee(
id int auto_increment,
name VARCHAR(40) COMMENT '姓名',
birthday datetime COMMENT '生日',
salary DOUBLE COMMENT '薪资',
gender TINYINT(3) COMMENT '性别',
PRIMARY KEY(id)
)10.5 编码环节

技术选型:SpringBoot + MyBatis + JSP + MySQL
环境搭建:Spring Boot + JSP + MyBatis
创建名为ems-jsp的项目,并引入web支持依赖,创建完成
https://img2023.cnblogs.com/blog/3321544/202312/3321544-20231218152436303-1062153954.png
环境搭建

pom.xml依赖导入
<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
   
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>

   
   
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.19</version>
    </dependency>
   
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
   
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>3.0.0</version>
    </dependency>

   
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>application.yml:
# 应用服务 WEB 访问端口
server:
port: 8989
servlet:
    context-path: /ems-jsp
    jsp:
      init-parameters:
      development: true # 开启jsp模板开发模式

# 配置jsp展示
spring:
mvc:
    view:
      prefix: /
      suffix: .jsp
datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ems?characterEncoding=UTF-8
    username: root
    password: 123456

# 配置mybatis
mybatis:
mapper-locations: classpath:com.baizhi/mapper/*.xml
type-aliases-package: com.baizhi.entity

# 配置日志
logging:
level:
    com.baizhi: debug添加dao包扫描
@SpringBootApplication
@MapperScan("com.baizhi.dao")
public class EmsJspApplication {
    public static void main(String[] args) {
      SpringApplication.run(EmsJspApplication.class, args);
    }

}10.6 验证码实现


[*]业务逻辑

[*]生成随机字符(依靠工具类VerifyCode)
[*]放入session(与前端传过来的验证码进行比对),放进map(传给前端)
[*]生成图片响应

[*]register.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Registration Page</title>
    <link rel="stylesheet" type="text/css" href="css/register.css">
</head>
<body>

<h2>用户注册</h2>

    <h3 >${param.msg}</h3>
    <form action="${pageContext.request.contextPath}/user/register" method="post">
      用户名: <input type="text"name="username"><br>
      真实姓名: <input type="text" name="realname" ><br>
      密码: <input type="password" name="password" ><br>
<%--      确认密码: <input type="password" name="confirmPassword"><br>--%>
      性别:
      <select name="gender" >
            <option value="1">男</option>
            <option value="0">女</option>
      </select><br>
      
      <label for="verifyCode">验证码:</label><br>
      <img id="verifyCode" src="" alt="Captcha Image">
      <a target="_blank" href="https://www.cnblogs.com/javascript:" id="refresh">换一张</a>
      <input type="text"name="code"><br>
      <input type="submit" value="注册">
    </form>





</body>
</html>
[*]css
body {
    font-family: 'Arial', sans-serif;
    margin: auto;
    justify-content: center;
    align-items: center;
    width: 500px;
    height: 800px;
    /*border: 1px solid red;*/
}

.container {
    padding: 30px;
    background-color: #ffffff;
    border-radius: 8px;
    box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
    /*border: 1px solid red;*/
}

h2 {
    text-align: center;
}

input,
input,
input,
select {
    width: calc(100% - 20px);
    margin-bottom: 15px;
    padding: 10px;
    border: 1px solid #dddddd;
    border-radius: 5px;
    transition: border-color 0.3s ease-in-out;
}

input:focus,
input:focus,
select:focus {
    outline: none;
    border-color: #66afe9;
}

input {
    background-color: #4CAF50;
    color: white;
    border: none;
    cursor: pointer;
    transition: background-color 0.3s ease-in-out;
}

input:hover {
    background-color: seagreen;
}
[*]验证码 实现类
package com.baizhi.utils;
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

public class VerifyCode {
    private int width = 100;// 定义图片的width
    private int height = 40;// 定义图片的height
    private int codeCount = 4;// 定义图片上显示验证码的个数
    private int lineCount = 20;// 定义图片上显示干扰线的条数
    private String code = null;// 定义用于保存验证码的字符串
    private BufferedImage buffImg = null;// 定义图片Buffer

    private char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R',
            'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

    public VerifyCode() {
      this.createCode();
    }

    /**
   * @param width
   *            图片宽
   * @param height
   *            图片高
   */
    public VerifyCode(int width, int height) {
      this.width = width;
      this.height = height;
      this.createCode();
    }

    /**
   * @param width
   *            图片宽
   * @param height
   *            图片高
   * @param codeCount
   *            字符个数
   * @param lineCount
   *            干扰线条数
   */
    public VerifyCode(int width, int height, int codeCount, int lineCount) {
      this.width = width;
      this.height = height;
      this.codeCount = codeCount;
      this.lineCount = lineCount;
      this.createCode();
    }

    public void createCode() {
      int x = 0, fontHeight = 0, codeY = 0;
      int red = 0, green = 0, blue = 0;

      x = width / (codeCount + 2);// 每个字符的宽度
      fontHeight = height - 2;// 字体的高度
      codeY = height - 4;

      // 图像buffer
      buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
      Graphics g = buffImg.createGraphics();
      // 创建一个随机数生成器类
      Random random = new Random();
      // 将图像填充为白色
      g.setColor(Color.WHITE);
      g.fillRect(0, 0, width, height);
      // 创建字体,字体的大小应该根据图片的高度来定。
      Font font = new Font("Fixedsys", Font.PLAIN, fontHeight);
      // 设置字体。
      g.setFont(font);

      for (int i = 0; i < lineCount; i++) {
            // 设置随机开始和结束坐标
            int xs = random.nextInt(width);// x坐标开始
            int ys = random.nextInt(height);// y坐标开始
            int xe = xs + random.nextInt(width / 8);// x坐标结束
            int ye = ys + random.nextInt(height / 8);// y坐标结束

            // 生成随机颜色
            red = random.nextInt(255);
            green = random.nextInt(255);
            blue = random.nextInt(255);
            g.setColor(new Color(red, green, blue));
            g.drawLine(xs, ys, xe, ye);
      }

      // randomCode记录随机产生的验证码
      StringBuffer randomCode = new StringBuffer();
      // 随机产生codeCount个字符的验证码。
      for (int i = 0; i < codeCount; i++) {
            // 得到随机产生的验证码数字。
            String strRand = String.valueOf(codeSequence);
            // 用随机产生的颜色将验证码绘制到图像中。
            red = random.nextInt(255);
            green = random.nextInt(255);
            blue = random.nextInt(255);
            g.setColor(new Color(red, green, blue));
            g.drawString(strRand, (i + 1) * x, codeY);
            // 将产生的四个随机数组合在一起。
            randomCode.append(strRand);
      }
      // 将四位数字的验证码保存到Session中。
      code = randomCode.toString();
    }

    public void write(String path) throws IOException {
      OutputStream sos = new FileOutputStream(path);
      this.write(sos);
    }

    public void write(OutputStream sos) throws IOException {
      ImageIO.write(buffImg, "png", sos);
      sos.close();
    }

    public BufferedImage getBuffImg() {
      return buffImg;
    }

    public String getCode() {
      return code;
    }
}
[*]验证码生成 请求
@Controller
@RequestMapping("user")
public class UserController {

    /**
   * 生成验证码
   */
                @ResponseBody
    @RequestMapping("verifyCode")
    public Map<String, String> verifyCode(HttpServletRequest request) throws IOException {
      Map<String,String> map = new HashMap<>();
      // 1.使用工具类生成验证码
      VerifyCode vc = new VerifyCode(120, 40, 4, 100);
      String code = vc.getCode();
      map.put("code", code);
      // 2. 获取验证码的BufferedImage对象
      BufferedImage captchaImage = vc.getBuffImg();
      //4.将图片转为base64 [放入src,可以直接显示图片]
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      ImageIO.write(captchaImage, "png", outputStream);
      byte[] imageBytes = outputStream.toByteArray();
      String image = "data:image/png;base64," + Base64Utils.encodeToString(imageBytes);
      map.put("image", image);
      return map;
    }
}
10.7 注册实现


[*]业务逻辑
https://img2023.cnblogs.com/blog/3321544/202312/3321544-20231218152450932-1115151471.png
[*]Service
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void register(User user) {
      User userDB = userDao.findByUserName(user.getUsername());
      if (!ObjectUtils.isEmpty(userDB)) {
            throw new RuntimeException("用户名已存在");
      }
      // 注册之前给密码进行加密
      String passwordSecret = DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8));
      user.setPassword(passwordSecret);
      userDao.save(user);

    }
}
[*]mapper语句
<select id="findByUserName" resultType="com.baizhi.entity.User">
    select id,username,realname,password,gender from `user`
    where username = #{username}
</select>
[*]api
@Autowired
private UserService userService;

@RequestMapping("register")
public String register(User user, String code, HttpSession session) {
    log.debug("接受的验证码:{}", code);
    log.debug("User:{}", user);
    // 比较验证
    try {
      String sessionCode = session.getAttribute("code").toString();
      if (!sessionCode.equalsIgnoreCase(code)) {
            throw new RuntimeException("验证码输入错误!!!");
      }
      userService.register(user);
    } catch (RuntimeException e) {
      e.printStackTrace();
      return "redirect:/register.jsp?msg=" + UriEncoder.encode(e.getMessage());
    }
    return "redirect:/login.jsp";
}
10.8用户登录

https://img2023.cnblogs.com/blog/3321544/202312/3321544-20231218152514844-306036312.png

[*]login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Login Page</title>
    <link rel="stylesheet" href="css/register.css">
</head>
<body>
<h2>用户登录</h2>
<h3 >${param.msg}</h3>
<form action="${pageContext.request.contextPath}/employee/list" method="post">
    <label for="username">用户名:</label><br>
    <input type="text" id="username" name="username"><br>
    <label for="password">密码:</label><br>
    <input type="password" id="password" name="password"><br>
    <input type="submit" value="登录">
    <input type="button" onclick="window.location.href='register.jsp'"value="注册">
</form>
</body>
</html>
[*]ServiceImpl
@Override
public User login(String username, String password) {
    //1. 根据用户名查询数据库是否存在
    User user = userDao.findByUserName(username);
    //2.判断对象是否存在
    if (ObjectUtils.isEmpty(user)) {
      throw new RuntimeException("用户名输入错误!");
    }
    //3.判断密码正确性
    String digestPassword = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
    if (!user.getPassword().equals(digestPassword)) {
      throw new RuntimeException("密码错误!");
    }
    return user;
}
[*]UserController
@RequestMapping("login")
public String login(String username, String password,HttpSession session) throws UnsupportedEncodingException {
    log.debug("接受到的用户名:{},接收到的密码:{}", username, password);
    try {
      // 1.执行登录业务逻辑
      User user = userService.login(username, password);
      // 2.登录成功,保存用户信息
      session.setAttribute("user", user);
    } catch (Exception e) {
      e.printStackTrace();
      return "redirect:/login.jsp?msg=" + UriEncoder.encode(e.getMessage());
    }
    return "redirect:/emplist.jsp";
}
10.9 员工列表展示


[*]在数据库查询所有员工信息
[*]在页面中进行展示


[*]emplist.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>用户列表</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/emplist.css">
</head>
<body>
   
      <h2>用户列表</h2>
      <table>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>性别</th>
                <th>薪水</th>
                <th>生日</th>
                <th>操作</th>
            </tr>
            <c:forEach var="employee" items="${requestScope.employees}">
                <tr>
                  <td>${employee.id}</td>
                  <td>${employee.name}</td>
                  <td>${employee.gender?'男':'女'}</td>
                  <td>${employee.salary}</td>
                  <td><fmt:formatDate value="${employee.birthday}" pattern="yyyy-MM-dd"/></td>
                     <td>
                        <a target="_blank" href="https://www.cnblogs.com/javascript:;">删除</a>
                        <a target="_blank" href="https://www.cnblogs.com/javascript:;">修改</a>
                  </td>
                </tr>
            </c:forEach>
      </table>
      <a target="_blank" href="https://www.cnblogs.com/javascript:;">添加员工信息</a>
   

</body>
</html>
[*]emplist.css
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}

#container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
}

h2 {
    text-align: center;
}
table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 20px;
}

th, td {
    padding: 10px;
    text-align: left;
    border: 1px solid #ccc;
}

thead {
    background-color: #f2f2f2;
}

div > button {
    margin: 5px;
    padding: 5px 10px;
    border: none;
    background-color: #007bff;
    color: #fff;
    cursor: pointer;
}

div > button:hover {
    background-color: #0056b3;
}

select, button {
    padding: 5px;
}

div > span {
    margin: 0 10px;
    font-weight: bold;
}

label {
    font-weight: bold;
}
[*]Service
@Service
@Transactional
public class EmployeeServiceImpl implements EmployeeService {

    private final EmployeeDao employeeDao;

    @Autowired
    public EmployeeServiceImpl(EmployeeDao employeeDao) {
      this.employeeDao = employeeDao;
    }

    @Override
    public List<Employee> list() {
      return employeeDao.list();
    }
}
[*]EmployeeController
@Controller
@RequestMapping("employee")
public class EmployeeController {

    private EmployeeService employeeService;

    @Autowired
    public EmployeeController(EmployeeService employeeService) {
      this.employeeService = employeeService;
    }

    /**
   * 员工列表
   *
   * @return
   */
    @RequestMapping("list")
    public String listEmployee(HttpServletRequest request, Model model) {
      //1. 获取员工列表
      List<Employee> employees = employeeService.list();
//      request.setAttribute("employees", employees);
      model.addAttribute("employees", employees);
      return "emplist";
    }
}
10.10 添加员工信息


[*]在EmplyeeController开发一个添加方法
[*]接收员工信息
[*]将员工信息保存到数据库
[*]跳转到员工列表展示数据


[*]addEmp.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>添加员工</title>
    <link rel="stylesheet" href="css/addEmp.css">
</head>
<body>
    <h2>添加员工</h2>
   
      <form action="${pageContext.request.contextPath}/employee/add" method="post">
            <table>
                <tr>
                  <td>姓名:</td>
                  <td><input type="text" id="name" name="name"></td>
                </tr>
                <tr>
                  <td>薪水:</td>
                  <td><input type="text" id="salary" name="salary"></td>
                </tr>
                <tr>
                  <td>生日:</td>
                  <td><input type="text" id="birthday" name="birthday"></td>
                </tr>
                <tr>
                  <td>性别:</td>
                  <td>
                        <select name="gender" >
                            <option value="1">男</option>
                            <option value="0">女</option>
                        </select>
                  </td>
                </tr>
                <tr>
                  <td colspan="2"><input type="submit" value="添加"></td>
                </tr>
            </table>
      </form>
   

</body>
</html>
[*]addEmp.css
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}
#container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
}

h2 {
    text-align: center;
}
table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 20px;
    color: #212529;
}
td, th {
    vertical-align: top;
    padding: 10px;
    text-align: left;
    border: 1px solid #ccc;
}
input, input, select {
    width: 60%;
    padding: .375rem .75rem;
    border: 1px solid #ced4da;
    border-radius: .25rem;
}
input {
    color: #fff;
    background-color: #007bff;
    border-color: #007bff;
    padding: .375rem .75rem;
    border-radius: .25rem;
}
[*]EmployeeDaomapper.xml
<insert id="add" parameterType="Employee" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO `ems`.`employee`(`id`, `name`, `birthday`, `salary`, `gender`) VALUES (#{id},#{name},#{birthday},#{salary},#{gender});
</insert>
[*]EmployeeServiceImpl
public void addEmployee(Employee employee) {
    employeeDao.add(employee);
}
[*]Controller
@RequestMapping("add")
public String addEmployee(Employee employee) {
    log.debug("员工信息:{}", employee);
    //1. 保存员工信息
    employeeService.addEmployee(employee);
    return "redirect:/employee/list";
}
10.11 更新员工信息


[*]显示员工信息

[*]根据id查询员工信息
[*]将对象放进作用域
[*]跳转到更新页面

[*]UpdateEmp.jsp
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>修改员工信息</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/updateEmp.css">
</head>
<body>
   
      <h2>修改员工信息</h2>
      <form action="${pageContext.request.contextPath}/employee/update" method="post">
            <input type="text" id="id" name="id" value="${employee.id}" >
            <label for="name">姓名:</label><br>
            <input type="text" id="name" name="name" value="${employee.name}"><br>
            <label for="gender">性别:</label><br>
            <select id="gender" name="gender">
                <option value="1" ${employee.gender?'selected':''}>男</option>
                <option value="0" ${!employee.gender?'selected':''}>女</option>
            </select><br>
            <label for="salary">薪水:</label><br>
            <input type="text" id="salary" name="salary" value="${employee.salary}"><br>
            <label for="birthday">生日:</label><br>
            <input type="text" id="birthday" name="birthday" value="<fmt:formatDate value='${employee.birthday}' pattern='yyyy/MM/dd'/>"/><br>
            <input type="submit" value="提交">
      </form>
   
</body>
</html>
[*]UpdateEmp.css
body {
    font-family: Arial, sans-serif;
}

#container {
    width: 300px;
    margin: 0 auto;
    padding: 20px;
    border: 1px solid #ccc;
    border-radius: 5px;
    background-color: #f8f8f8;
}

h2 {
    text-align: center;
    color: #333;
}

label {
    font-weight: bold;
    color: #555;
}

input, input,select {
    width: 70%;
    padding: 10px;
    margin: 5px 0 15px;
    border: 1px solid #ccc;
    border-radius: 3px;
}

input {
    width: 100%;
    padding: 10px;
    color: white;
    background-color: #007BFF;
    border: none;
    border-radius: 3px;
    cursor: pointer;
}

input:hover {
    background-color: #0056b3;
}
[*]Controller
@RequestMapping("detail")
public String detailEmployee(Integer id, Model model) {
    log.debug("接收的id:{}",id);
    Employee employee = employeeService.idByEmployee(id);
    model.addAttribute("employee", employee);
    return "updateEmp";
}
[*]更改员工信息

[*]获取更新后的员工信息
[*]更新数据库

[*]Controller
@RequestMapping("update")
public String updateEmployee(Employee employee) {
    log.debug("修改的员工信息:{}", employee);
    employeeService.updateEmployee(employee);
    return "redirect:/employee/list";
}
10.12 删除员工


[*]传递id给后端进行数据库删除
[*]返回employee/list重新查数据库刷新


[*]emplist.jsp
<a target="_blank" href="https://www.cnblogs.com/javascript:;" onclick="deleteEmployee()">删除</a>

[*]Controller
@RequestMapping("delete")
public String deleteEmployee(Integer id) {
    log.debug("接收的id:{}", id);
    employeeService.deleteEmployee(id);
    return "redirect:/employee/list";
}
[*]mapper
<delete id="deleteEmployee">
    delete from `employee`where id =#{id}
</delete>

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: Spring Boot学习随笔- JSP小项目-员工管理系统(验证码生成、增删改查)