springboot_员工管理系统案例
准备工作
1、创建一个干净的springboot项目
2、导入需要的依赖,如thymeleaf
,web
,devtools
,lombok
,test
3、导入静态资源,页面放在/templates,资源放在/static
4、pojo,实体类Department,Employee
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private Integer id;
private String lastname;
private String email;
private Integer gender; // 0:女 1:男
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();
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department {
private Integer id;
private String departmentName;
}
5、dao层模拟数据库数据
@Repository
public class DepartmentDao {
//模拟数据
private static Map<Integer, Department> map=null;
static {
map = new HashMap<>();
map.put(101,new Department(101,"教学部"));
map.put(102,new Department(102,"市场部"));
map.put(103,new Department(103,"教研部"));
map.put(104,new Department(104,"运营部"));
map.put(105,new Department(105,"后勤部"));
}
//获得所有部门信息
public Collection<Department> getDepartments(){
return map.values();
}
//通过id的到部门
public Department getDepartmentById(Integer id){
return map.get(id);
}
}
@Repository
public class EmployeeDao {
//模拟数据库中的数据
private static Map<Integer,Employee> map=null;
@Autowired
private DepartmentDao departmentDao;
static {
map = new HashMap<>();
map.put(1,new Employee(1,"A","a@qq,com",0,new Department(101,"教学部")));
map.put(2,new Employee(2,"B","b@qq,com",1,new Department(102,"市场部")));
map.put(3,new Employee(3,"C","b@qq,com",0,new Department(103,"教研部")));
map.put(4,new Employee(4,"D","d@qq,com",1,new Department(104,"运营部")));
map.put(5,new Employee(5,"E","e@qq,com",0,new Department(105,"后勤部")));
}
//id主键自增
private static Integer initId =6;
public void addEmployee(Employee employee){
if(employee.getId()==null){
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
map.put(employee.getId(),employee);
}
public Collection<Employee> getAllEmployee(){
return map.values();
}
public Employee getEmployeeById(Integer id){
return map.get(id);
}
public void deleteEmployee(Integer id){
map.remove(id);
}
}
首页实现
在config包下配置扩展SpirngMVC。修改前端html资源,使其被thyemleaf接管
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
国际化。中英语言切换
1、安装Resource Bundle Editor插件
2、配置i18n文件
3、在.yaml配置文件下修改message真实文件位置
## 配置文件真实位置
spring:
messages:
basename: i18n.login
4、config包下自定义一个国际化组件 LocaleResolver
package com.fan.config;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request) {
// 获取请求中的语言参数
String language = request.getParameter("lang");
Locale locale = Locale.getDefault();//如果没有,则使用默认的
System.out.println(language);
if(!StringUtils.isEmpty(language)){//如果请求携带的lang参数不为空
String[] split = language.split("_");
// 国家,地区
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
5、将国际化组件配置的spring容器中
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
//自定义的国际化组件交给spring托管
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
}
6、修改index.html
<a class="btn btn-sm" th:href="@{/index.html(lang='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(lang='en_US')}">English</a>
有个问题暂时不理解,我在MyLocaleResolver类中只写了一句输出语句,但却一次请求输出两次,它背后的执行流程到底是怎么样的呢?
登录功能
1、controller实现
@Controller
public class LoginController {
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Model model, HttpSession session){
if(!StringUtils.isEmpty(username)&& password.equals("1")){
session.setAttribute("UserSession",username);
return "redirect:/main.html";
}else {
model.addAttribute("info","用户名或者密码错误");
return "index";
}
}
}
2、在MyMvcConfig下配置路径映射
registry.addViewController("/main.html").setViewName("dashboard");
3、在index.html下添加消息提示
<p style="color: red" th:text="${info}" th:if="${not #strings.isEmpty(info)}"></p>
登录拦截器
1、在Config包下新建LoginHandInterceptor
类
public class LoginHandInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object session = request.getSession().getAttribute("UserSession");
if(session==null){
request.setAttribute("info","没有权限,请先登录!");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}else{
return true;
}
}
}
2、LoginController中login()添加session
session.setAttribute("UserSession",username);
3、在MyMvcConfig下添加拦截器映射
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/index.html","/","/user/login","/css/*","/img/*","/js/*");
}
4、修改dashboard.html,使其显示登录者用户名
员工列表CRUD
1、编写EmployeeController
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao;
@Autowired
DepartmentDao departmentDao;
@RequestMapping("/employees")
public String list(Model model){
Collection<Employee> allEmployee = employeeDao.getAllEmployee();
model.addAttribute("lists",allEmployee);
return "list";
}
@RequestMapping("/toAdd")
public String toAddPage(Model model){
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "addList";
}
@RequestMapping("/add")
public String addList(Model model,Employee employee){
System.out.println("DEBUG==>"+employee);
employeeDao.addEmployee(employee);
return "redirect:/employees";
}
@RequestMapping("/toUpdate")
public String toUpdatePage(Integer id,Model model){
Employee employeeById = employeeDao.getEmployeeById(id);
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
model.addAttribute("employee",employeeById);
return "updateList";
}
@RequestMapping("/toDelete")
public String toDeletePage(Integer id,Model model){
employeeDao.deleteEmployee(id);
return "redirect:/employees";
}
}
2、CRUD的html修改,使用thymeleaf格式
404页面和前端公共代码提取
1、404页面springboot已经封装好了,现在只需要在template文件下添加error文件夹,在error下直接添加404.html即可
2、使用thymeleaf提取前端公共代码
要抽取侧边栏和顶部作为公共页面 ,使用th:fragment=""
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!--头部导航栏-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" th:text="${session.UserSession}"></a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">注销</a>
</li>
</ul>
</nav>
<!--侧边栏-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a th:class="${active == 'main.html' ? 'nav-link active': 'nav-link'}" th:href="@{/main.html}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
首页 <span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
<polyline points="13 2 13 9 20 9"></polyline>
</svg>
Orders
</a>
</li>
<li class="nav-item">
<a th:class="${active == 'list.html'?'nav-link active': 'nav-link'}" th:href="@{/employees}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
员工管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bar-chart-2">
<line x1="18" y1="20" x2="18" y2="10"></line>
<line x1="12" y1="20" x2="12" y2="4"></line>
<line x1="6" y1="20" x2="6" y2="14"></line>
</svg>
Reports
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layers">
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</svg>
Integrations
</a>
</li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Saved reports</span>
<a class="d-flex align-items-center text-muted" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
</a>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Current month
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Last quarter
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Social engagement
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Year-end sale
</a>
</li>
</ul>
</div>
</nav>
</html>
向某个html添加使用th:replace="~{}"
<div th:replace="~{commons/commons::topbar}"></div>
<div th:replace="~{commons/commons::sidebar(active='list.html')}"></div>