基於 springboot + thymeleaf + mybatis 的員工管理系統 —— 登錄與註冊功能

Github地址:https://github.com/szluyu99/ems_thymeleaf

創建項目

利用 Spring Initializr 快速創建一個項目:
在這裏插入圖片描述
這裏填寫一些項目名、描述、組織、包結構等;
在這裏插入圖片描述
這裏主要是選擇要引入的依賴,不選也可以,後面複製我的 pom.xml 代碼即可。
在這裏插入圖片描述
創建完項目以後,刪除一些用不上的文件(比如 test 目錄下的文件),項目結構如下:
在這裏插入圖片描述

pom.xml

然後檢查一下 pom.xml 中的依賴:按上面的選擇應該和我的 pom.xml 差不多,但是我做了一些刪減,把用不上的去掉了。可以直接複製我的 pom.xml,複製後一定要刷新 Maven 項目!

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.yusael</groupId>
	<artifactId>ems</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>ems</name>
	<description>springboot + mybatis + thymeleaf 的 ems</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<!--繼承springboot父項目-->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.7.RELEASE</version>
	</parent>
	
	<dependencies>
		<!--引入springboot的web支持-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!--thymeleaf-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<!--mybatis-->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.1.2</version>
		</dependency>
		<!--mysql-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.43</version>
			<scope>runtime</scope>
		</dependency>
		<!--druid-->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.12</version>
		</dependency>
		<!--lombok-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

數據庫表設計和環境準備

需求分析:

  • 既然做的員工管理系統,那肯定需要一個員工表(t_emp)來存儲員工的信息
    表的具體內容需要根據業務需求來決定,我們這裏就做一個簡易的管理系統,設的較爲簡單。
  • 由於我們要做登錄功能,因此我們需要一個用戶表(t_user)來存儲用戶信息。

建表SQL

員工表的SQL:

CREATE TABLE `t_emp` (
  `id` varchar(40) NOT NULL,
  `name` varchar(60) DEFAULT NULL,
  `salary` double(7,2) DEFAULT NULL,
  `age` int(3) DEFAULT NULL,
  `bir` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

用戶表的SQL:

CREATE TABLE `t_user` (
  `id` varchar(40) NOT NULL,
  `username` varchar(40) DEFAULT NULL,
  `realname` varchar(40) DEFAULT NULL,
  `password` varchar(40) DEFAULT NULL,
  `sex` varchar(8) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

application.properties

數據庫建完表以後,還需要在 application.properties 中配置:

server.port=8989
server.servlet.context-path=/ems

##mysql配置
#指定連接池類型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#指定驅動
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#指定url
spring.datasource.url=jdbc:mysql://localhost:3306/ems?characterEncoding=UTF-8
#指定用戶名
spring.datasource.username=root
#指定密碼
spring.datasource.password=1234

##配置thymleaf(下面註釋的是默認配置, 可以不設置)
#spring.thymeleaf.prefix=classpath:/templates/
#spring.thymeleaf.suffix=.html
#spring.thymeleaf.encoding=UTF-8
#spring.thymeleaf.cache=false # 想讓熱部署生效必須配置這個
#spring.thymeleaf.servlet.content-type=text/html
# 默認無法直接訪問templates下的頁面, 需要設置
spring.resources.static-locations=classpath:/templates/, classpath:/static/

#指定mapper配置文件位置
mybatis.mapper-locations=classpath:/com/yusael/mapper/*.xml
#指定起別名了的類
mybatis.type-aliases-package=com.yusael.entity

由於配置了mapper文件的位置,在啓動類中加上 @MapperScan("com.yusael.dao") 掃描該目錄。

package com.yusael;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.yusael.dao")
public class EmsApplication {

	public static void main(String[] args) {
		SpringApplication.run(EmsApplication.class, args);
	}

}

用戶註冊與登錄功能

MVC 的模式開發項目,包的結構如下:
在這裏插入圖片描述

entity

先在 com.yusael.entity 包下創建與數據庫表對應的實體類 User.java

package com.yusael.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
    private String id;
    private String username;
    private String realname;
    private Double password;
    private Date sex;
}

dao

com.yusael.dao 包下開發 UserDAO.java

package com.yusael.dao;

import com.yusael.entity.User;
import org.apache.ibatis.annotations.Param;

public interface UserDAO {
    void save(User user);
    User login(@Param("username") String name, @Param("password")String password);
}

resources/com/yusael/mapper 下創建 UserDAOMapper.xml,這裏的路徑要與 application.properties 中配置的一致。
在這裏插入圖片描述

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yusael.dao.UserDAO">
    <!--註冊-->
    <insert id="save" parameterType="User">
        insert into t_user values (#{id}, #{username}, #{realname}, #{password}, #{sex})
    </insert>

    <!--登錄-->
    <select id="login" parameterType="User" resultType="User">
        select select id, username, realname, password, sex from t_user
        where username=#{username} and password=#{password}
    </select>

</mapper>

service

com.yusael.service 包下開發接口 UserService.java

package com.yusael.service;

import com.yusael.entity.User;

public interface UserService {
    void register(User user);
    User login(String username, String password);
}

com.yusael.service 包下開發 UserServiceImpl.java

package com.yusael.service;

import com.yusael.dao.UserDAO;
import com.yusael.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;

    @Override
    public void register(User user) {
        user.setId(UUID.randomUUID().toString());
        userDAO.save(user);
    }

    @Override
    public User login(String username, String password) {
        return userDAO.login(username, password);
    }
}

生成驗證碼的工具

在開發 com.yusael.controller 包的內容前,我們需要引入一個驗證碼功能的代碼,將它放到 com.yusael.utils 下作爲一個工具類:這個不需要我們自己寫,直接拿過來用就可以了。

package com.yusael.utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;

public class ValidateImageCodeUtils {
    /**
     * 驗證碼難度級別 Simple-數字 Medium-數字和小寫字母 Hard-數字和大小寫字母
     */
    public enum SecurityCodeLevel {
        Simple, Medium, Hard
    };
    /**
     * 產生默認驗證碼,4位中等難度
     *
     * @return
     */
    public static String getSecurityCode() {
        return getSecurityCode(4, SecurityCodeLevel.Medium, false);
    }
    /**
     * 產生長度和難度任意的驗證碼
     *
     * @param length
     * @param level
     * @param isCanRepeat
     * @return
     */
    public static String getSecurityCode(int length, SecurityCodeLevel level, boolean isCanRepeat) {
        // 隨機抽取len個字符
        int len = length;
        // 字符集合(--除去易混淆的數字0,1,字母l,o,O)
        char[] codes = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
        };
        // 根據不同難度截取字符串
        if (level == SecurityCodeLevel.Simple) {
            codes = Arrays.copyOfRange(codes, 0, 10);
        } else if (level == SecurityCodeLevel.Medium) {
            codes = Arrays.copyOfRange(codes, 0, 36);
        }
        // 字符集和長度
        int n = codes.length;
        // 拋出運行時異常
        if (len > n && isCanRepeat == false) {
            throw new RuntimeException(String.format("調用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出現異常," + "當isCanRepeat爲%3$s時,傳入參數%1$s不能大於%4$s", len, level, isCanRepeat, n));
        }
        // 存放抽取出來的字符
        char[] result = new char[len];
        // 判斷能否出現重複字符
        if (isCanRepeat) {
            for (int i = 0; i < result.length; i++) {
                // 索引0 and n-1
                int r = (int) (Math.random() * n);
                // 將result中的第i個元素設置爲code[r]存放的數值
                result[i] = codes[r];
            }
        } else {
            for (int i = 0; i < result.length; i++) {
                // 索引0 and n-1
                int r = (int) (Math.random() * n);
                // 將result中的第i個元素設置爲code[r]存放的數值
                result[i] = codes[r];
                // 必須確保不會再次抽取到那個字符,這裏用數組中最後一個字符改寫code[r],並將n-1
                codes[r] = codes[n - 1];
                n--;
            }
        }
        return String.valueOf(result);
    }
	/**
     * 生成驗證碼圖片

     * @param securityCode

     * @return

     */
    public static BufferedImage createImage(String securityCode){

        int codeLength = securityCode.length();//驗證碼長度

        int fontSize = 18;//字體大小

        int fontWidth = fontSize+1;

        //圖片寬高

        int width = codeLength*fontWidth+6;
        int height = fontSize*2+1;
        //圖片

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = image.createGraphics();

        g.setColor(Color.WHITE);//設置背景色

        g.fillRect(0, 0, width, height);//填充背景

        g.setColor(Color.LIGHT_GRAY);//設置邊框顏色

        g.setFont(new Font("Arial", Font.BOLD, height-2));//邊框字體樣式

        g.drawRect(0, 0, width-1, height-1);//繪製邊框

        //繪製噪點

        Random rand = new Random();

        g.setColor(Color.LIGHT_GRAY);

        for (int i = 0; i < codeLength*6; i++) {

            int x = rand.nextInt(width);

            int y = rand.nextInt(height);

            g.drawRect(x, y, 1, 1);//繪製1*1大小的矩形

        }

        //繪製驗證碼

        int codeY = height-10;

        g.setColor(new Color(19,148,246));

        g.setFont(new Font("Georgia", Font.BOLD, fontSize));
        for(int i=0;i<codeLength;i++){
        	double deg=new Random().nextDouble()*20;
        	g.rotate(Math.toRadians(deg), i*16+13,codeY-7.5);
            g.drawString(String.valueOf(securityCode.charAt(i)), i*16+5, codeY);
            g.rotate(Math.toRadians(-deg), i*16+13,codeY-7.5);
        }
       
        g.dispose();//關閉資源
        return image;
    }

    public static void main(String[] args) throws IOException {
        String securityCode = ValidateImageCodeUtils.getSecurityCode();
        System.out.println(securityCode);

        BufferedImage image = ValidateImageCodeUtils.createImage(securityCode);
        ImageIO.write(image,"png",new FileOutputStream("aa.png"));
    }
    
}

controller

IndexController

我們知道,resources/templates 下面放的是我們的頁面文件(html),如果我們直接訪問 templates 下的靜態頁面是無法獲取 static 中的樣式的。

我們需要用控制器進行去訪問,該控制器沒有其他作用,只是爲了訪問界面而已

com.yusael.controller 下創建一個 IndexController.java

package com.yusael.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

// 直接訪問templates下的靜態頁面是無法獲取static中的樣式的
// 用該控制器進行去訪問, 該控制器沒有其他作用, 只是爲了訪問界面而已
@Controller
public class IndexController {

    @GetMapping("index")
    public String toIndex() {
        return "ems/login"; // ems下的login.html
    }

    @GetMapping("toRegister")
    public String toRgsiter() {
        return "ems/regist"; // ems下的regist.html
    }
    }

    @GetMapping("toSave")
    public String toSaave() {
        return "ems/addEmp"; // ems下的addEmp.html
    }
}

UserController

com.yusael.controller 下開發 UserController.java

package com.yusael.controller;

import com.yusael.entity.User;
import com.yusael.service.UserService;
import com.yusael.utils.ValidateImageCodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    // 登錄方法
    @PostMapping("/login")
    public String login(String username, String password, HttpSession session) {
        User login = userService.login(username, password);
        if (login != null) {
            session.setAttribute("user", login);
            return "redirect:/emp/findAll"; // 跳轉到查詢所有
        } else {
            return "redirect:/index"; // 跳轉回到登錄
        }
    }

    @PostMapping("/register")
    public String register(User user, String code, HttpSession session) {
        String sessionCode = (String)session.getAttribute("code"); // 生成的驗證碼
        // 忽略大小寫, 比較用戶輸入的驗證碼與生成的驗證碼
        if (sessionCode.equalsIgnoreCase(code)) { // 輸入正確
            userService.register(user); // 註冊
            return "redirect:/index"; // 註冊成功跳轉到登錄界面
        } else { // 輸入錯誤
            return "redirect:/toRegister"; // 註冊失敗跳轉到註冊界面
        }
    }

    @GetMapping("/code")
    public void getImage(HttpSession session, HttpServletResponse response) throws IOException {
        // 生成驗證碼
        String securityCode = ValidateImageCodeUtils.getSecurityCode();
        BufferedImage image = ValidateImageCodeUtils.createImage(securityCode);
        // 存入session作用域中
        session.setAttribute("code", securityCode);
        // 響應圖片
        ServletOutputStream os = response.getOutputStream();
        ImageIO.write(image, "png", os);
    }
}

前端頁面

這裏就把 登陸頁面login.html 和 註冊頁面regist.html 的文件放出來(能體會到後端效果即可),完整項目可以去 https://github.com/szluyu99/ems_thymeleaf

login.htmlregist.html 放到 resources/templates/ems 下:(css、img這些請去GitHub獲取,沒有這些不影響項目功能)
在這裏插入圖片描述
login.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
    <title>login</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <link rel="stylesheet" type="text/css" th:href="@{/css/style.css}"/>
</head>

<body>
<div id="wrap">
    <div id="top_content">
        <div id="header">
            <div id="rightheader">
                <p>
                    2009/11/20
                    <br/>
                </p>
            </div>
            <div id="topheader">
                <h1 id="title">
                    <a href="#">main</a>
                </h1>
            </div>
            <div id="navigation">
            </div>
        </div>
        <div id="content">
            <p id="whereami">
            </p>
            <h1>
                login
            </h1>
            <form th:action="@{/user/login}" method="post">
                <table cellpadding="0" cellspacing="0" border="0"
                       class="form_table">
                    <tr>
                        <td valign="middle" align="right">
                            username:
                        </td>
                        <td valign="middle" align="left">
                            <input type="text" class="inputgri" name="username"/>
                        </td>
                    </tr>
                    <tr>
                        <td valign="middle" align="right">
                            password:
                        </td>
                        <td valign="middle" align="left">
                            <input type="password" class="inputgri" name="password"/>
                        </td>
                    </tr>
                </table>
                <p>
                    <input type="submit" class="button" value="Submit &raquo;"/>
                    <input type="button" class="button" onclick="location.href='/ems/toRegister'" value="Regist &raquo;"/>
                </p>
            </form>
        </div>
    </div>
    <div id="footer">
        <div id="footer_bg">
            [email protected]
        </div>
    </div>
</div>
</body>
</html>

regist.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<title>regist</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<link rel="stylesheet" type="text/css" href="css/style.css" />
	</head>
	<body>
		<div id="wrap">
			<div id="top_content">
					<div id="header">
						<div id="rightheader">
							<p>
								2009/11/20
								<br />
							</p>
						</div>
						<div id="topheader">
							<h1 id="title">
								<a href="#">main</a>
							</h1>
						</div>
						<div id="navigation">
						</div>
					</div>
				<div id="content">
					<p id="whereami">
					</p>
					<h1>
						註冊
					</h1>
					<form th:action="@{/user/register}" method="post">
						<table cellpadding="0" cellspacing="0" border="0"
							class="form_table">
							<tr>
								<td valign="middle" align="right">
									用戶名:
								</td>
								<td valign="middle" align="left">
									<input type="text" class="inputgri" name="username" />
								</td>
							</tr>
							<tr>
								<td valign="middle" align="right">
									真實姓名:
								</td>
								<td valign="middle" align="left">
									<input type="text" class="inputgri" name="realname" />
								</td>
							</tr>
							<tr>
								<td valign="middle" align="right">
									密碼:
								</td>
								<td valign="middle" align="left">
									<input type="password" class="inputgri" name="password" />
								</td>
							</tr>
							<tr>
								<td valign="middle" align="right">
									性別:
								</td>
								<td valign="middle" align="left"><input type="radio" class="inputgri" name="sex" value="" checked="checked"/><input type="radio" class="inputgri" name="sex" value=""/>
								</td>
							</tr>
							
							<tr>
								<td valign="middle" align="right">
									驗證碼:
									<img id="num" th:src="@{/user/code}" />
									<a href="javascript:;" onclick="document.getElementById('num').src = '/ems/user/code?'+(new Date()).getTime()">換一張</a>
								</td>
								<td valign="middle" align="left">
									<input type="text" class="inputgri" name="code" />
								</td>
							</tr>
						</table>
						<p>
							<input type="submit" class="button" value="Submit &raquo;" />
						</p>
					</form>
				</div>
			</div>
			<div id="footer">
				<div id="footer_bg">
				[email protected]
				</div>
			</div>
		</div>
	</body>
</html>

啓動項目

運行 EmsApplcation.java,瀏覽器中輸入:http://localhost:8989/ems/index,進入登陸界面:
在這裏插入圖片描述
進入登陸界面,但是此時我們數據庫中還沒有信息,我們點擊 Regist,先去註冊一個賬號。
點擊 Regist,可以發現網址變爲:http://localhost:8989/ems/toRegister,來到了註冊界面。
我們輸入要註冊的賬號的信息,點擊 Submit。
在這裏插入圖片描述

我們在 UserController.java 中設置的是註冊成功跳回登陸界面,成功跳回登陸界面則說明註冊成功。
數據庫中也成功插入了數據。
在這裏插入圖片描述

此時我們就可以登錄了,登錄後應當跳到後臺管理界面,但是我們還沒有做,因此會報錯。
在這裏插入圖片描述
在這裏插入圖片描述
我們可以在 UserController.javaregisterlogin 方法中分別加一句輸出,可以驗證我們註冊和登錄成功。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章