springBoot员工管理系统
员工管理系统
1、准备工作
静态资源:链接:https://pan.baidu.com/s/1qtUDuJNVupr872kVDO-veg
提取码:fabo
gitee:https://gitee.com/planting-trees-chen/spring-boot
新建springboot项目
导入jar包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.9.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
</dependencies>
添加静态资源
数据库文件,模拟
实体类Department部门
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department {
private Integer id;
private String departmentName;
}
实体类,员工Employee
@Data
@NoArgsConstructor
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;
private Department department;
private Date birth;
public Employee(Integer id, String lastName, String email, Integer gender, Department department) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.department = department;
this.birth = new Date();
}
}
dao层
//部门dao
@Repository
public class DepartmentDao {
//模拟数据库数据
private static Map<Integer, Department> departments = null;
static {
departments = new HashMap<>();
departments.put(101, new Department(101, "教学部"));
departments.put(102, new Department(102, "市场部"));
departments.put(103, new Department(103, "教研部"));
departments.put(104, new Department(104, "运营部"));
departments.put(105, new Department(105, "后勤部"));
}
//获得所有部门信息
public Collection<Department> getDepartment() {
return departments.values();
}
//通过ID的到部门
public Department getDepartmentById(Integer id) {
return departments.get(id);
}
}
//员工dao
@Repository
public class EmployeeDao {
private static Map<Integer, Employee> employees = null;
//员工所属部门
@Autowired
private DepartmentDao departmentDao;
static {
employees = new HashMap<>(); //创建部门表
employees.put(1001, new Employee(1001, "AA", "aaa@qq.com", 1, new Department(101, "教学部")));
employees.put(1002, new Employee(1002, "BB", "aaa@qq.com", 0, new Department(102, "市场部")));
employees.put(1003, new Employee(1003, "CC", "aaa@qq.com", 1, new Department(103, "教研部")));
employees.put(1004, new Employee(1004, "DD", "aaa@qq.com", 0, new Department(104, "运营部")));
employees.put(1005, new Employee(1005, "EE", "aaa@qq.com", 1, new Department(105, "后勤部")));
}
//主键自增
private static Integer initId = 1006;
//添加员工
public void save(Employee employee) {
if (employee.getId() == null) {
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
employees.put(employee.getId(), employee);
}
//查询全部员工信息
public Collection<Employee> getAll() {
return employees.values();
}
//通过id查询
public Employee getEmployeeById(Integer id) {
return employees.get(id);
}
//删除
public void delete(Integer id) {
employees.remove(id);
}
}
MyMvcConfig配置视图
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//添加视图控制
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
启动测试,可能找不到符号
2、主页
index.html添加头文件,thymeleaf
<html lang="en" xmlns:th="http://www.thymeleaf.org">
所有文件使用thymleaf模板
<link th:href="@{css/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{css/signin.css}" rel="stylesheet">
application.properties关闭模板缓存
#关闭模板缓存
spring.thymeleaf.cache=false
自定义路径,localhost:8080/wgg
server.servlet.context-path=/wgg
3、页面国际化
确保都是utf-8编码
在i18n文件夹下新建
这里是login.xxx,就是你想要设置的关键字
填写对应的语言
login.properties中
login.btn=登录
login.tip=请登录
login.password=密码
login.username=用户名
login.remember=记住我
在MessageSourceAutoConfiguration中配置,MessageSourceProperties中包含basename属性
application.properties中手动配置basename
spring.messages.basename=i18n.login
index.html中替换成
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<label class="sr-only">Username</label>
<input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
<label class="sr-only">Password</label>
<input type="password" class="form-control" th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me">[[#{login.remember}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">[[#{login.btn}]]</button>
WebMvcAutoConfiguration类中
国际化解析
index.html中中英文切换,携带参数,请求跳转
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
config包下自定义国际化解析,参照resolveLocale()
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request) {
//获取请求参数
String language = request.getParameter("l");
Locale locale = Locale.getDefault(); //如果没有就使用默认的
//如果请求的链接携带了国际化的参数,l=zh_CN/l=en_US
if (!StringUtils.isEmpty(language)){
String[] split = language.split("_");
//国家,地区
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
在MyMvcConfig类中将自定义组件注册到spring容器中
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//添加视图控制
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
//自定义的国际化组件
@Bean
public LocaleResolver localeResolver() {
return new MyLocaleResolver();
}
}
完成中英文切换
4、登录功能实现
index.html,表单提交地址
<form class="form-signin" th:action="@{/user/login}">
controller包下LoginController登录控制,处理业务
@Controller
public class LoginController {
@RequestMapping("/user/login")
@ResponseBody
public String login(){
return "OK";
}
}
indext.html中添加name属性
<input type="text" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
<input type="password" name="password" class="form-control" th:placeholder="#{login.password}" required="">
处理登录业务
@Controller
public class LoginController {
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) {
//如果用户名不为空,密码123456,登录成功
if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
return "dashboard";
} else { //登录失败
model.addAttribute("msg", "用户名或密码错误");
return "index";
}
}
}
h1标签下添加错误提示标签
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<!--判断msg是否为空,输出错误提示-->
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
MyMvcConfig添加地址映射
registry.addViewController("/main.html").setViewName("dashboard");
重定向,为了隐藏url参数
if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
return "redirect:/main.html";
5、登录拦截器
登录成功用户有session,添加session
LoginController中,添加session形参,设置session
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model, HttpSession session) {
//如果用户名不为空,密码123456,登录成功
if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
session.setAttribute("loginUser",username);
return "redirect:/main.html";
} else { //登录失败
model.addAttribute("msg", "用户名或密码错误");
return "index";
}
}
config包下,自定义拦截器,false拦截
//拦截器
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取session
Object loginUser = request.getSession().getAttribute("loginUser");
if (loginUser==null){
request.setAttribute("msg","请先登录");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}else {
return true;
}
}
}
MyMvcConfig类中注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login","/css/**","/js/**","/img/**");
}
修改compony name获取登录成功的用户名,dashboard.html中
6、员工列表显示
修改dashboard.html和list.html中员工管理
EmployeeController
@Controller
public class EmployeeController {
//直接调用dao
@Autowired
EmployeeDao employeeDao;
@RequestMapping("/emps")
public String list(Model model) {
Collection<Employee> employees = employeeDao.getAll();
model.addAttribute("emps", employees);
return "emp/list";
}
}
提取相同页面
在list.html和dashboard.html中进行替换
判断高亮,使用括号传递参数
commons.html中判断是否active==main.html
接收后台的emps遍历输出,无法使用行内<td>[[${emp.getLastName}]]</td>
不知道为啥
<table class="table table-striped table-sm">
<thead>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>department</th>
<th>birth</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getLastName()}"></td>
<td th:text="${emp.getEmail()}"></td>
<td th:text="${emp.getGender()}"></td>
<td th:text="${emp.getDepartment().getDepartmentName()}"></td>
<td th:text="${emp.getBirth()}"></td>
</tr>
</tbody>
</table>
添加按钮,修改
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getLastName()}"></td>
<td th:text="${emp.getEmail()}"></td>
<td th:text="${emp.getGender()==0?'女':'男'}"></td>
<td th:text="${emp.getDepartment().getDepartmentName()}"></td>
<td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td>
<td>
<button class="btn btn-sm btn-primary">编辑</button>
<button class="btn btn-sm btn-danger">删除</button>
</td>
</tr>
</tbody>
7、添加员工
按钮提交
跳转到添加页面
@GetMapping("/emp")
public String toAddPage(){
return "emp/add";
}
复制list.html,修改main
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<form action="">
<div class="form-group">
<label>LastName</label>
<input type="text" class="form-control" placeholder="姓名">
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" placeholder="邮箱">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="1">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="0">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<select name="" id="" class="form-control">
<option value="">1</option>
<option value="">2</option>
<option value="">3</option>
<option value="">4</option>
<option value="">5</option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<input type="text" class="form-control" placeholder="生日">
</div>
<button type="submit" class="btn btn-primary">添加</button>
</form>
</main>
所有属性加name
employeeController查询所有部门跳转到add页面
@GetMapping("/emp")
public String toAddPage(Model model){
//查处所有部门信息,返回到add.html
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "emp/add";
}
add.html遍历部门
<select name="department" id="" class="form-control">
<option value="" th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
表单提交
<form th:action="@{/emp}" method="post">
保存员工,返回员工列表
@PostMapping("/emp")
public String addEmp(){
return "redirect:/emps";
}
ThymeleafViewResolver–>createView()中定制了视图解析,redirect和forward
@PostMapping("/emp")
public String addEmp(Employee employee){
//添加员工的操作
employeeDao.save(employee);
return "redirect:/emps";
}
name改成department.id
<select name="department.id" id="" class="form-control">
<option value="" th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
使用-分隔
#时间日期格式化
spring.mvc.format.date=yyyy-MM-dd
8、编辑员工
提交参数,跳转路径
<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.getId()}">编辑</a>
跳转到update.html
//查询要修改的员工,跳转到修改页面
@GetMapping("/emp/{id}")
public String toUpdateEmp(@PathVariable("id") Integer id,Model model){
Employee employee = employeeDao.getEmployeeById(id);
model.addAttribute("emp",employee);
return "emp/update";
}
复制add.html
获取LastName等员工属性
<input th:value="${emp.getLastName()}"
<input th:value="${emp.getEmail()}"
<input th:checked="${emp.getGender()==1}"
<input th:checked="${emp.getGender()==0}"
<option th:selected="${dept.getId()==emp.getDepartment().getId()}"
<input th:value="${#dates.format(emp.getBirth(),'yyyy-MM-dd')}"
返回部门
//查询要修改的员工,跳转到修改页面
@GetMapping("/emp/{id}")
public String toUpdateEmp(@PathVariable("id") Integer id,Model model){
//查询要修改的员工
Employee employee = employeeDao.getEmployeeById(id);
model.addAttribute("emp",employee);
//查处所有部门信息,返回到update.html
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "emp/update";
}
修改form表但提交地址
<form th:action="@{/updateEmp}" method="post">
执行修改员工
//修改员工
@PostMapping("/updateEmp")
public String updateEmp(Employee employee){
employeeDao.save(employee);
return "redirect:/emps";
}
添加隐藏域,携带id
9、删除员工
//删除
@GetMapping("/delemp/{id}")
public String deleteEmp(@PathVariable("id")int id){
employeeDao.delete(id);
return "redirect:/emps";
}
10、404页面
注销
commons.html中topbar
//注销
@RequestMapping("/user/logout")
public String logout(HttpSession session){
session.invalidate();
return "redirect:/index.html";
}
上一篇: Spring AOP的理解
下一篇: AOP