SpringBoot:員工管理系統(基本結構)


SpringBoot_staff

寫一個簡單的員工管理系統,來體驗 Spring Boot 開發的整個流程。

1、項目結構

  1. 創建 Spring Boot Web 項目:springboot_04_staff

  2. 導入依賴

    • 數據庫JDBCMySQL 連接、Druid 數據源、MyBatis
    • 模板引擎Thymeleaf
  3. 完善包結構

    • pojo
    • dao
    • service
    • controller
    • config
    • constant
    • utils
  4. 導入靜態資源

    • static 目錄:存放資源文件,如 CSSJS...
    • templates 目錄:存放 HTML 頁面

    image-20211018235047805

2、數據庫表、實體類

2.1、注意

2.1.1、編程規范

  1. ORM原則
  2. 命名風格
    • 數據庫:小寫字母,下划線命名;
    • 實體類:大駝峰命名;
  3. 實體類
    • 不需要邏輯主鍵,需要創建時間和更新時間;
    • 必須使用包裝數據類型;
    • 根據需要添加constructortoString()getter/setter,可以全部添加

2.1.2、注意事項

  1. 多對一關系:員工對部門

  2. 員工實體中對部門的表示

    • 數據庫- employee:部門ID——department_id
    • 實體類- Employee:部門——Department
  3. 映射問題

    • 命名風格映射;
    • department_idDepartment 的映射。
  4. 關於日期時間的屬性說明

    • 在數據庫,日期使用 date類型,時間使用 timestamp類型;
    • 在后端,日期和時間均使用 java.util.Date類型
    • 為了便於管理,通過后台代碼完成(Service層)有關日期時間的操作,而不是直接在數據庫端操作。

2.2、數據庫springboot_staff

數據庫表必備三字段阿里巴巴規范

  • id邏輯主鍵。bigint,無符號自增;
  • create_time創建時間。timestamp,非空(新增記錄時通過后端代碼生成)
  • update_time更新時間。timestamp,默認為空(更新記錄時通過后端代碼生成)

主鍵

  • 邏輯主鍵
    • 無實際含義,用於唯一標識數據庫表的每個記錄。
    • 是表的主鍵PK,即 id;
    • 僅在數據庫中體現,實體類不需要該屬性;
  • 業務主鍵
    • 有實際含義,用於標識不同的業務實體;
    • 是我們理解上的主鍵,如用戶的 user_id,游戲的 game_id等。

部門表department

  • department_id業務主鍵,部門ID

  • name:部門名

    image-20211127005111615

員工表employee

部門和員工是一對多的關系

  • employee_id業務主鍵,員工ID

  • name:員工名

  • email:郵箱

  • gender:性別

  • birthday:生日

  • department_id在員工數據庫表中,用 ID表示部門

    image-20211127010553757

2.3、實體類

部門類Department

public class Department {
    /**
     * 創建時間
     */
    private Date createTime;
    /**
     * 更新時間
     */
    private Date updateTime;
    /**
     * 部門ID
     */
    private String departmentId;
    /**
     * 部門名
     */
    private String name;
}

員工類Employee

  • 在員工實體類中,用實體類表示部門
public class Employee {
    /**
     * 創建時間
     */
    private Date createTime;
    /**
     * 更新時間
     */
    private Date updateTime;
    /**
     * 員工ID
     */
    private String employeeId;
    /**
     * 員工名
     */
    private String name;
    /**
     * 郵箱
     */
    private String email;
    /**
     * 性別
     */
    private Integer gender;
    /**
     * 生日
     */
    private Date birthday;
   
    /**
     * 部門
     */
    private Department department;
}

3、工具類

3.1、工具類

  • 返回當前時間戳
public class TimeUtils {
    /**
     * 返回當前時間戳
     *
     * @return 當前時間戳
     */
    public static Date getCurrentTime() {
        return new Date(System.currentTimeMillis());
    }
}

3.2、常量類

  • 當前時間
  • 員工登錄Session
  • 有需要可以添加枚舉類:xxxEnum
public class CommonConstant {
    /**
     * 當前時間
     */
    public static final Date CURRENT_TIME = MyDateUtils.getCurrentTime();
}

public class EmployeeConstant {
    /**
     * 員工登錄Session
     */
    public static final String LOGIN_EMPLOYEE = "loginEmployee";
}

4、整合MyBatis

即整合了 MyBatis后的 DAO層10.3、整合 MyBatis

4.1、導入依賴

<!-- JDBC -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MySQL連接 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- Druid數據源 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
</dependency>
<!-- SpringBoot整合MyBatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>
<!-- log4j日志 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

4.2、數據庫配置文件

  • JDBC 數據庫配置
  • Druid 數據源
  • MyBatis

application.yaml

spring:
  datasource:
    username: root
    password: 密碼
    url: jdbc:mysql://主機地址/數據庫名?useUnicode=true&characterEncoding=utf8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    
    # Druid數據源
    type: com.alibaba.druid.pool.DruidDataSource
    # Druid數據源配置
    initialSize: 5
    maxActive: 20
    minIdle: 5
    maxWait: 60000
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    validationQuery: SELECT 1 FROM DUAL
    testOnBorrow: false
    testOnReturn: false
    testWhileIdle: true
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    # filters:stat監控統計、log4j日志記錄(需要導入log4j依賴)、wall防御sql注入
    filters: stat,wall,log4j
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
    
# 整合MyBatis配置
mybatis:
  type-aliases-package: indi.jaywee.pojo
  # Mapper.xml放在resources目錄下與mapper同名的包下
  mapper-locations: classpath:indi/jaywee/mapper/*.xml
  # 自動映射:數據庫下划線命名<-->實體類駝峰命名
  configuration:
    map-underscore-to-camel-case: true

5、DAO、service層

5.1、Mapper

  1. Mapper 類上方添加@Mapper注解;
  2. 插入語句:需要添加 create_time,該屬性由 service層為對象設置,DAO層負責編寫相關的SQL語句即可;
  3. 更新語句
    • 以實體類作為參數,對象中存放業務主鍵需要修改的新屬性值(具體見EmployeeMapper);
    • 需要修改 update_time,該屬性由 service層為對象設置,DAO層負責編寫相關的SQL語句即可。
  4. 先編寫基本的CRUD,后面再根據需求來添加方法;

DepartmentMapper

@Mapper
public interface DepartmentMapper {
    /**
     * 根據ID查詢部門
     *
     * @param departmentId 部門ID
     * @return 查詢部門
     */
    Department getDepartment(String departmentId);

    /**
     * 查詢所有部門
     *
     * @return 部門列表
     */
    List<Department> listDepartments();
}

EmployeeMapper

更新語句:改名

  • 以Employee實體類作為參數
    • 對象中存放業務主鍵employeeId和新名稱name;
    • 具體實現:只需要臨時創建一個員工,為該員工設置employeeId和name兩個屬性即可;
  • update_time由 service層為上述臨時員工設置,DAO層負責編寫相關的SQL語句即可。
/**
 * 添加員工
 *
 * @param employee 待添加員工
 * @return 受影響行數
 */
int insertEmployee(Employee employee);

/**
 * 刪除員工
 *
 * @param employeeId 員工ID
 * @return 受影響行數
 */
int deleteEmployee(String employeeId);

/**
 * 更新員工:改名
 *
 * @param employee 待更新員工:主要用到員工ID和新名稱
 * @return 受影響行數
 */
int updateEmployee(Employee employee);

/**
 * 根據ID查詢員工
 *
 * @param employeeId 員工ID
 * @return 待查詢員工
 */
Employee getEmployee(String employeeId);

/**
 * 查詢所有員工
 *
 * @return 員工列表
 */
List<Employee> listEmployees();

5.2、Mapper.xml(!)

  1. 綁定對應接口namespace="xxx"
  2. 命名映射配置下划線命名和駝峰命名的自動映射
  3. SQL語句注意
    1. 區分命名風格:數據庫字段用下划線,實體類屬性用駝峰命名;
    2. 區分主鍵:邏輯主鍵id無實際含義,業務主鍵有業務邏輯含義;
    3. 不要使用select *,要將需要查詢的字段全寫出來(即使是所有字段);
  4. 難點Employee 的部門字段的映射

DepartmentMapper.xml

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 接口綁定 -->
<mapper namespace="indi.jaywee.mapper.DepartmentMapper">
    <!-- 根據ID查詢部門 -->
    <select id="getDepartment" resultType="department">
        SELECT create_time,
               update_time,
               department_id,
               name
        FROM springboot_staff.department
        WHERE department_id = #{departmentId}
    </select>
    <!-- 查詢所有部門 -->
    <select id="listDepartments" resultType="department">
        SELECT create_time,
               update_time,
               department_id,
               name
        FROM springboot_staff.department
    </select>
</mapper>

EmployeeMapper.xml(!)

  1. insert
    • 需要插入 create_time,不需要插入 update_time;
    • 要求實體類Employee 具有 getDepartmentId() 方法,否則無法獲取並插入departmentId;
  2. select
    1. 使用 resultMap 處理結果集映射
    2. 使用 association + 子查詢,來映射部門字段(有關說明見MyBatis的多對一和一對多
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 接口綁定 -->
<mapper namespace="indi.jaywee.mapper.EmployeeMapper">

    <!-- 添加員工 -->
    <insert id="insertEmployee">
        INSERT INTO springboot_staff.employee(create_time, employee_id,
                                              name, email, gender, birthday, department_id)
        VALUES (#{createTime}, #{employeeId},
                #{name}, #{email}, #{gender}, #{birthday}, #{departmentId})
    </insert>

    <!-- 更新員工:改名 -->
    <update id="updateEmployee">
        UPDATE springboot_staff.employee
        SET update_time = #{updateTime},
            name        = #{name}
        WHERE employee_id = #{employeeId}
    </update>

    <!-- 刪除員工 -->
    <delete id="deleteEmployee">
        DELETE
        FROM springboot_staff.employee
        WHERE employee_id = #{employeeId}
    </delete>

    <!-- 查詢員工 -->
    <select id="getEmployee" resultMap="employeeMap">
        SELECT create_time,
               update_time,
               employee_id,
               name,
               email,
               gender,
               birthday,
               department_id
        FROM springboot_staff.employee
        WHERE employee_id = #{employeeId}
    </select>

    <!-- 查詢所有員工-->
    <select id="listEmployees" resultMap="employeeMap">
        SELECT create_time,
               update_time,
               employee_id,
               name,
               email,
               gender,
               birthday,
               department_id
        FROM springboot_staff.employee
    </select>

    <!-- 結果映射:數據庫department_id與實體類Department -->
    <resultMap id="employeeMap" type="employee">
        <association property="department" column="department_id" javaType="Department" select="getDepartment"/>
    </resultMap>
    <select id="getDepartment" resultType="department">
        SELECT create_time, update_time, name, department_id
        FROM springboot_staff.department
        WHERE department_id = #{department_id}
    </select>
</mapper>

5.3、service

  1. 接口類
    • 不需要添加注解;
    • 方法通常和相應的Mapper接口方法相同;
  2. 接口實現類
    • 使用@Service注解,將Service實現類注冊到容器中;
    • 注入相應的Mapper接口類,用於調用DAO層方法;
    • 處理時間屬性
      • 新增:設置 create_time屬性;
      • 更新:設置 update_time屬性;

DepartmentService

  • 不需要添加注解;
  • 接口方法:同DepartmenMapper。
public interface DepartmentService {
    /**
     * 根據ID查詢部門
     *
     * @param departmentId 部門ID
     * @return 查詢部門
     */
    Department getDepartment(String departmentId);

    /**
     * 查詢所有部門
     *
     * @return 部門列表
     */
    List<Department> listDepartments();

EmployeeService

  • 不需要添加注解;
  • 接口方法:同DepartmenMapper。
/**
 * 添加員工
 *
 * @param employee 待添加員工
 * @return 受影響行數
 */
int insertEmployee(Employee employee);

/**
 * 刪除員工
 *
 * @param employeeId 員工ID
 * @return 受影響行數
 */
int deleteEmployee(String employeeId);

/**
 * 更新員工:改名
 *
 * @param employee 待更新員工:主要用到員工ID和新名稱
 * @return 受影響行數
 */
int updateEmployee(Employee employee);

/**
 * 根據ID查詢員工
 *
 * @param employeeId 員工ID
 * @return 待查詢員工
 */
Employee getEmployee(String employeeId);

/**
 * 查詢所有員工
 *
 * @return 員工列表
 */
List<Employee> listEmployees();

5.4、serviceImpl

DepartmentServiceImpl

  • 使用@Service注解,將Service實現類注冊到容器中
  • 注入DepartmentMapper,用於調用DAO層方法;
@Service
public class DepartmentServiceImpl implements DepartmentService {
    /**
     * Service層調用DAO層方法
     */
    @Resource
    DepartmentMapper departmentMapper;


    @Override
    public Department getDepartment(String departmentId) {
        return departmentMapper.getDepartment(departmentId);
    }

    @Override
    public List<Department> listDepartments() {
        return departmentMapper.listDepartments();
    }
}

EmployeeServiceImpl

  • 使用@Service注解,將Service實現類注冊到容器中;
  • 注入EmployeeMapper,用於調用DAO層方法;
  • 處理時間屬性
    • 新增:設置 create_time屬性;
    • 更新:設置 update_time屬性;
@Service
public class EmployeeServiceImpl implements EmployeeService {
    /**
     * Service層調用DAO層方法
     */
    @Resource
    EmployeeMapper employeeMapper;

    @Override
    public int insertEmployee(Employee employee) {
        employee.setCreateTime(CommonConstant.CURRENT_TIME);

        return employeeMapper.insertEmployee(employee);
    }

    @Override
    public int deleteEmployee(String employeeId) {
        return employeeMapper.deleteEmployee(employeeId);
    }

    @Override
    public int updateEmployee(Employee employee) {
        employee.setUpdateTime(CommonConstant.CURRENT_TIME);
        
        return employeeMapper.updateEmployee(employee);
    }

    @Override
    public Employee getEmployee(String employeeId) {
        return employeeMapper.getEmployee(employeeId);
    }

    @Override
    public List<Employee> listEmployees() {
        return employeeMapper.listEmployees();
    }

}

編寫完 Service層后,創建相應的 ServiceTest 類,測試是否能正常運行

6、首頁和錯誤頁面

6.1、模板引擎

  • 導入 Thymeleafstarterspring-boot-starter-thymeleaf
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

6.2、首頁:視圖控制器

SpringBoot 8.3、歡迎頁面

  • 默認啟動 Spring Boot 項目時,在沒有設置首頁的情況下,打開的是錯誤頁面 Whitelabel Error Page
  • 由於使用 Thymeleaf 模板引擎,只能映射 template 目錄下的頁面,因此需要顯式地設置首頁的視圖控制器

自定義SpringMVC

:創建自定義 SpringMVC 配置類

  • 實現WebMvcConfigurer接口的@Configuration
  • 添加視圖控制器:訪問//index.html,會映射到 template 目錄下的index.html
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 歡迎頁面
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
    }
}

image-20211022151033594

6.3、錯誤頁面:error

  1. template 目錄下新建 error 目錄
  2. 創建錯誤頁面:404、500

image-20211111153556527


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM