springboot小项目(人员管理系统)

数据库准备

CREATE DATABASE /*!32312 IF NOT EXISTS*/`mybatis` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;

USE `mybatis`;

/*Table structure for table `department` */

CREATE TABLE `department` (
  `did` int NOT NULL AUTO_INCREMENT,
  `departmentName` varchar(20) NOT NULL,
  PRIMARY KEY (`did`)
) ENGINE=InnoDB AUTO_INCREMENT=106 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

/*Data for the table `department` */

insert  into `department`(`did`,`departmentName`) values (101,'教学部'),(102,'市场部'),(103,'教研部'),(104,'运营部'),(105,'后勤部');

/*Table structure for table `employee` */

CREATE TABLE `employee` (
  `id` int NOT NULL AUTO_INCREMENT,
  `lastName` varchar(20) NOT NULL,
  `email` varchar(20) NOT NULL,
  `gender` int NOT NULL,
  `birth` date DEFAULT NULL,
  `department` int NOT NULL,
  PRIMARY KEY (`id`),
  KEY `did` (`department`),
  CONSTRAINT `did` FOREIGN KEY (`department`) REFERENCES `department` (`did`)
) ENGINE=InnoDB AUTO_INCREMENT=1015 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

/*Data for the table `employee` */

insert  into `employee`(`id`,`lastName`,`email`,`gender`,`birth`,`department`) values (1001,'AA','121456qq.com',1,'2021-03-09',101),(1003,'BB','124561@qq.com',0,'2021-05-03',105),(1005,'zhangsan','1210418430@qq.com',1,'2021-07-04',102),(1006,'zhangsan','1210418430@qq.com',1,'2021-07-04',102),(1009,'zhangsans','a123456yy@qq.com',1,'2000-02-02',102),(1010,'20210704','14565430@qq.com',0,'2000-02-02',105),(1011,'djfihasf\'','1214546@qq.com',0,'2000-02-02',103),(1014,'sadasdsad','456430@qq.com',0,'2000-02-02',103);
/*Table structure for table `user` */

CREATE TABLE `user` (
  `id` int NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  `pwd` varchar(30) DEFAULT NULL,
  `perms` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `user` */

insert  into `user`(`id`,`name`,`pwd`,`perms`) values (1,'java','java','user:add'),(2,'1210','1210','user:add'),(3,'wsad','1210','user:add'),(5,'c++','1210','user:add'),(6,'张三','1210','user:update'),(7,'张思','1210','user:update'),(8,'李四','1210','user:update'),(9,'root','123','user:update');

基本环境搭建

新建一个Springboot项目,导入pom依赖

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.myproject</groupId>
    <artifactId>springbootproject01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springbootproject01</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <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.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.3</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>



    </dependencies>

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

</project>

建立基本结构和配置框架

 

application.properties

spring.thymeleaf.cache=false

spring.messages.basename=i18n.login

spring.mvc.format.date=yyyy-MM-dd
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

mybatis.type-aliases-package=com.myproject.pojo
mybatis.mapper-locations=classpath:mybatis/*.xml

package

com.myproject.config

  SecurityConfigTest

com.myproject.controller

  EmployeeController

com.myproject.mapper

  DepartmentMapper
  DepartmentMapperImpl
  EmployeeMapper
  EmployeeMapperImpl
  UserMapper
  UserMapperImpl

com.myproject.pojo

  Department
  Employee
  EmployeeWeb
  Users

com.myproject.service 

  DepartmentService
  DepartmentServiceImpl
  EmployeeService
  EmployeeServiceImpl
  MyUserDetailsService
  UserService
  UserServiceImpl

resources

mybatis

  DepartmentMapper.xml
  EmployeeMapper.xml
  UserMapper.xml

static(前端资源)

templates(前端资源)

安全管理框架(SpringSecurity)

MyUserDetailsService.java主要用接收传递用户名密码。

package com.myproject.service;

import com.myproject.mapper.UserMapper;

import com.myproject.pojo.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.List;
@Component
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
    /**
     *     实现UserDetailsService中的loadUserByUsername方法
     *     loadUserByUsername会从表单中获取name为"username"和"password"的字段,
     *     实现此方法会传入username来让我们验证,即我们从数据库中查询这个用户是否存在,
     *     然后将查询到的密码传给BCryptPasswordEncoder对象,这个对象会自动帮我们去验证密码正确
     *      BCryptPasswordEncoder采用SHA-256 +随机盐+密钥对密码进行加密,这个方法不能传入明文密码
     */
    
    @Autowired
    UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Users user = userMapper.queryUserByName(username);//从数据库获取User对象
        if (user==null){//如果用户并不存在则会抛出异常
            throw new UsernameNotFoundException("用户名不存在");
        }
        List<GrantedAuthority> role = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        //设置用户角色
        //   我们可以从User的构造器中看到,User中需要传入三个值,即用户名,加密的密码和用户角色
        //   public User(String username, String password, Collection<? extends GrantedAuthority> authorities)
        
        return new User(user.getName()
                ,new BCryptPasswordEncoder().encode(user.getPwd()),role);
        //这个User是package org.springframework.security.core.userdetails下的User,并不是我们的实体类对象。
        
    }
    
}

SecurityConfigTest.java主要设置用户权限,即授权。

package com.myproject.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import sun.security.util.Password;
@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
        //在 Spring Security 中,用来处理身份认证的类是 AuthenticationManager,我们也称之为认证管理器。
        //而AuthenticationManagerBuilder用来生成一个AuthenticationManager,
        //passwordEncoder需要一个BCryptPasswordEncoder,即下面这个方法生成一个BCryptPasswordEncoder返回给AuthenticationManagerBuilder
    }


    @Bean
    PasswordEncoder password(){
        return new BCryptPasswordEncoder();//生成一个BCryptPasswordEncoder创个上面的passwordEncoder
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/")//设置登录页面
                .loginProcessingUrl("/user/login")//表单传递的地址,即action
                .defaultSuccessUrl("/emps").permitAll()//登录成功跳转地址
                .and().authorizeRequests().antMatchers("/").permitAll()//放行的页面,一般登录页面需要放行
                .anyRequest().authenticated()//任何请求都必须经过身份验证,否则返回401响应
                .and().csrf().disable()//Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,
                    // 通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。为了防止跨站提交攻击,通常会配置csrf。但也会影响性能,可自由选择开启或关闭
        ;
        http.logout().logoutUrl("/user/logout")//注销
                .logoutSuccessUrl("/").permitAll();
    }
}

EmployeeController.java

package com.myproject.controller;

import com.myproject.mapper.DepartmentMapperImpl;
import com.myproject.pojo.Department;
import com.myproject.pojo.Employee;
import com.myproject.pojo.EmployeeWeb;
import com.myproject.service.DepartmentServiceImpl;
import com.myproject.service.EmployeeServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.*;

@Controller
public class EmployeeController {
    @Autowired
    private EmployeeServiceImpl employeeService;
    @Autowired
    private DepartmentServiceImpl departmentService;

    /**
     *
     * @param model
     * @return
     * 这个方法就是登录后要跳转的Servlet,这个方法会拿到全部的员工信息,然后返回给list.html页面。
     */
    @RequestMapping("/emps")
    public String list(Model model){
        List<Employee> employees = employeeService.queryAll();

           List<EmployeeWeb> list=new ArrayList();
        for (int i=0;i<employees.size();i++){

            EmployeeWeb employeeWeb=new EmployeeWeb();

            List<Department> depAll = departmentService.getDepAll();
            int department = employees.get(i).getDepartment();
            int id = employees.get(i).getId();
            String lastName = employees.get(i).getLastName();
            int gender = employees.get(i).getGender();
            String email = employees.get(i).getEmail();
            Date birth = employees.get(i).getBirth();
            for (int j=0;j<depAll.size();j++){

                int did = depAll.get(j).getDid();
                if (did==department){
                    employeeWeb.setDepartment(depAll.get(j));
                }
            }
            employeeWeb.setId(id);
            employeeWeb.setLastName(lastName);
            employeeWeb.setBirth(birth);
            employeeWeb.setEmail(email);
            employeeWeb.setGender(gender);
            list.add(employeeWeb);
        }

        model.addAttribute("emps",list);
        for (EmployeeWeb employeeWeb : list) {
            System.out.println(employees);
        }
        return "emp/list";
    }

    /**
     *
     * @param model
     * @return
     * 这个方法会获取获得所有的部门对象,然后传给add页面,因为部门选项需要所有的部门信息。
     */

        @GetMapping("/emp")
         public String toAllpage(Model model){
        List<Department> depList = departmentService.getDepAll();
        model.addAttribute("departments",depList);
        return "emp/add";
    }

    /**
     *
     * @param employee
     * @return
     * 这个方法会从add页面获取需要添加的员工信息,然后将数据传回数据库,完成后悔重定向到所有成员的列表页面。
     */
    @PostMapping("/emp")
    public String addEmp(Employee employee){

        System.out.println(employee);
        Boolean aBoolean = employeeService.saveEmp(employee);
        System.out.println(aBoolean);
        return  "redirect:/emps";
    }

    /**
     *
     * @param id
     * @param model
     * @return
     * 这个方法是更新员工信息跳转的Servlet,这个方法需要先得到需要更新的员工id,
     * 然后传回到更新页面,同时这个方法也需要查询出全部的部门信息,传回给跟新页面,
     * 同样是部门选项需要全部的部门信息,然后跳转到更新页面。
     */
    @GetMapping("/toUpdate/{id}")
    public String toUpdate(@PathVariable("id")Integer id, Model model){
        System.out.println("toUpdate");
        Employee employee = employeeService.queryById(id);

        model.addAttribute("employee",employee);
        //查询所有部门信息
        List<Department> depAll = departmentService.getDepAll();
        model.addAttribute("departments",depAll);
        return "emp/update";
    }

    /**
     *
     * @param employee
     * @return
     * 这个方法会从前端会的一个员工新的信息,完成员工的信息更新,然后重定向到所有成员的列表页面。
     */
    @PostMapping("/updateUser")
    public String Update(Employee employee){
        employeeService.saveEmp(employee);
        return  "redirect:/emps";
    }


    /**
     *
     * @param id
     * @return
     * 这个方法会从前端得到一个员工id,执行删除,然后重定向到所有成员的列表页面。
     */
    @GetMapping("/delemp/{id}")
    public String delemp(@PathVariable("id")Integer id){

        employeeService.deleteEmp(id);
        return  "redirect:/emps";
    }

    //如果登录的用户没有权限执行某个操作,则会跳转到此方法,该方法未完成。
    @RequestMapping("/noauth")
    @ResponseBody
    public String unauthorized(){
        return "未授权无法访问此页面";
    }

    //已被SpringSecurity解决
//    @RequestMapping("/user/logout")
//    public String logOut(HttpSession session){
//            session.invalidate();
//        return "redirect:/index.html";
//    }

}

页面

 

 

 

 

 

 总结

  这个项目是采用SpringBoot开发的,SpringBoot相较于Spring省略了很多配置,取而代之的是通过注解来完成IOC,极大地简化了开发过程,除了SpringBoot,这个项目还采用了SpringSecurity来完成用户登录的授权和认证。

项目链接:https://gitee.com/coopermini/employee-management-system

posted @ 2021-07-05 22:20  CooperMiNi  阅读(8730)  评论(0编辑  收藏  举报