Spring Boot(九)--------员工管理系统
18、员工管理系统
18.1 准备工作
18.1.1 前端页面
- 将html页面放入
templates
文件夹 - 将css,js,img放入
static
文件夹
- Department
public class Department {
private Integer id;
private String departmentName;
public Department() {}public Department(Integer id, String departmentName) {
this.id = id;
this.departmentName = departmentName;
}public Integer getId() {
return id;
}public void setId(Integer id) {
this.id = id;
}public String getDepartmentName() {
return departmentName;
}public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}@Override
public String toString() {
return "Department{" +
"id=" + id +
", departmentName='" + departmentName + '\'' +
'}';
}
}
- Employee
import java.util.Date;
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() {
}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();
}
...
}
18.1.3 Dao层模拟数据库
- DepartmentDao
public class DepartmentDao {
//模拟数据库中的数据
private static Map 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 getDepartments(){
return departments.values();
}//根据id得到部门
public Department getDepartmentById(Integer id){
return departments.get(id);
}
}
- EmployeeDao
public class EmployeeDao {
//模拟数据库中的数据
private static Map employees = null;
//员工所属部门
private DepartmentDao departmentDao;
static {
//创建一个员工表
employees = new HashMap();
employees.put(1001, new Employee(1001, "zzz", "23656@qq.com", 1, new Department(101, "后勤部")));
employees.put(1002, new Employee(1002, "mmm", "12345@qq.com", 0, new Department(102, "市场部")));
employees.put(1003, new Employee(1003, "ttt", "67890@qq.com", 1, new Department(103, "教研部")));
employees.put(1004, new Employee(1004, "aaa", "98765@qq.com", 0, new Department(101, "后勤部")));
employees.put(1005, new Employee(1005, "bbb", "43210@qq.com", 1, new Department(102, "市场部")));
employees.put(1006, new Employee(1006, "ccc", "00000@qq.com", 0, new Department(101, "后勤部")));
}
//增加一个员工,主键自增
private static Integer initId = 1007;
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 getAll(){
return employees.values();
}//通过Id查询员工
public Employee getEmployeeById(Integer id){
return employees.get(id);
}//删除员工
public void delete(Integer id){
employees.remove(id);
}
}
18.1.4 pom.xml
- 添加
themeleaf
的依赖
4.0.0 org.springframework.boot
spring-boot-starter-parent
2.6.4
com.zmt
springboot-03-web02
0.0.1-SNAPSHOT
springboot-03-web02
Demo project for Spring Boot 1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
>test
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-maven-plugin
18.1.5 目录结构
文章图片
18.2 首页实现
18.2.1 第一种方式
- 创建一个
IndexController
,不建议使用
@Controller
public class IndexController {
@RequestMapping({"/","/index.html"})
public String index(){
return "index";
}
}
18.2.2 第二种方式
- 创建
config
,新建MyMvcConfig
类,重写addViewControllers()
方法
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
18.3 加载静态资源
- 导入thymeleaf包
- 将所有页面的静态资源使用thymeleaf接管
文章图片
type="text/javascript" th:src="https://www.it610.com/article/@{/js/jquery-3.2.1.slim.min.js}">
type="text/javascript" th:src="https://www.it610.com/article/@{/js/popper.min.js}">
type="text/javascript" th:src="https://www.it610.com/article/@{/js/bootstrap.min.js}">type="text/javascript" th:src="https://www.it610.com/article/@{/js/feather.min.js}">type="text/javascript" th:src="https://www.it610.com/article/@{/js/Chart.min.js}">
- 静态资源目录
文章图片
18.4 页面国际化
- 很多时候,网站会涉及多语言切换,所以需要学习页面国际化
- 在IDEA中统一设置
properties
的编码问题
文章图片
18.4.2 配置文件编写
- 在
resources
文件夹下新建一个i18n
文件夹,用于存放国际化配置文件
- i18n:
internationalization
,从开头字母i
到结尾字母n
中间有18个字母
- 新建一个
login.properties
文件和login_zh_CN.properties
。发现IDEA自动世界了我们要做国际化的操作,文件夹发生了变化,自动生成了一个文件夹
文章图片
- 可以继续添加其他语言的配置文件,右键生成的文件夹
文章图片
- 添加步骤
文章图片
- IDEA中有一种方式:
Resource Bundle
,点击可以进行可视化配置,即配置该登录页面所有方式的多语言模式
文章图片
- 添加之后,可以看到
login.properties
文件中出现login.tip=请登录
文章图片
- 继续添加其他内容,包括页面提示,页面按钮等
文章图片
- 查看此时的配置文件
login.properties
,其中为打开页面的默认值
login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名
- 查看英文配置文件
login_en_US.properties
login.btn=Sign in
login.password=password
login.remember=remember me
login.tip=please sign in
login.username=username
- 查看中文配置文件
login_zh_CN.properties
login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名
- 完成页面国际化配置
- 查看Spring Boot源码中对国际化的自动配置,查看类
MessageSourceAutoConfiguration
- 其中的
messageSource()
方法,获取了properties传递过来的值
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) {
messageSource.setBasenames(StringUtils
.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
}
if (properties.getEncoding() != null) {
messageSource.setDefaultEncoding(properties.getEncoding().name());
}
messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
Duration cacheDuration = properties.getCacheDuration();
if (cacheDuration != null) {
messageSource.setCacheMillis(cacheDuration.toMillis());
}
messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
return messageSource;
}
- 我们放在了i18n目录下,在
application.properties
文件中配置对应的message路径
spring.messages.basename=i18n.login
18.4.5 配置页面国际化
- 查看页面代码,找到对应的
message
取值操作,修改为#{...}
- 例如:
Please sign in
- 修改后页面的乱码,多语言问题都解决了
文章图片
18.4.6 配置国际化源码探究
- 现在需要探究,如何可以点击按钮实现双语切换
- 打开
WebMvcAutoConfig
类,找到localeResolver()
方法
public LocaleResolver localeResolver() {
if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.webProperties.getLocale());
}
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.webProperties.getLocale());
return localeResolver;
}
- 其中,如果手动配置了本地区域化,就返回用户配置的信息,如果没有手动配置,返回默认的配置信息,默认配置信息在
AcceptHeaderLocaleResolver
类中,其中有一个resolveLocale()
方法
@Override
public Locale resolveLocale(HttpServletRequest request) {
Locale defaultLocale = getDefaultLocale();
if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
return defaultLocale;
}
Locale requestLocale = request.getLocale();
List supportedLocales = getSupportedLocales();
if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) {
return requestLocale;
}
Locale supportedLocale = findSupportedLocale(request, supportedLocales);
if (supportedLocale != null) {
return supportedLocale;
}
return (defaultLocale != null ? defaultLocale : requestLocale);
}
- 需要自己建立一个国际化解析器,来让刚才写的配置文件生效
- 先修改一下前端页面的跳转链接
中文
English
- 新建
MyLocaleResolver
组件类
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request) {
//获取请求中的语言参数
String language = request.getParameter("l");
//如果为空就使用默认
Locale locale = Locale.getDefault();
//如果请求的链接携带了国际化的参数,进行判断
if(!StringUtils.isEmpty(language)){
//zh_CN,通过_来分割
String[] split = language.split("_");
//数组包括,国家,地区
locale = new Locale(split[0],split[1]);
}
return locale;
}@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {}
}
- 在我们自己写的
MyMvcConfig
中添加bean,使这个组件生效
//把自定义的国际化组件放进来
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
- 实现了可以根据自己的需求,来切换中英文
文章图片
文章图片
18.4.7 小结
- 首页配置:注意点,所有的静态资源页面都需要用
@thymeleaf
接管,url:@{} - 页面国际化
- 需要配置i18n文件夹
- 如果需要在项目中进行按钮自动切换,需要自定义一个组件
LocaleResolver
- 将自己写的组件配置到Spring容器
@Bean
- #{}
- 新建
LoginController
登录验证
@Controller
public class LoginController {
@RequestMapping("/user/login")
@ResponseBody
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";
}
}
}
- 修改首页表单,增加登录失败时的信息显示,p标签
- 此时,页面并不友好,在地址栏可以看到你的账号和密码,解决密码泄露问题
- 在
MyMvcConfig
类中,添加main
映射
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
registry.addViewController("/main.html").setViewName("dashboard");
}
- 修改
LoginController
的跳转页面(redirect跳转)
@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 "redirect:/main.html";
}else{
//告诉用户你登录失败了
model.addAttribute("msg","用户名或密码错误");
return "index";
}
}
}
- 此时输入
localhost:8080/main.html
就可以直接进入页面了,需要使用拦截器阻止直接访问
- 在
LoginController
中添加一个session
进行判断
@Controller
public class LoginController {
@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
文件夹下新建一个LoginHandlerInterceptor
拦截器
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/**");
}
- 在
dashboard.html
页面中修改登录信息为[[ ${session.loginUser} ]]
,这样登录后会显示用户名
[[ ${session.loginUser} ]]
- 使用try用户名登录成功,可以看到用户名显示在左上角
文章图片
- 密码错误登录失败时
文章图片
18.7 员工列表展示
18.7.1 提取公共页面
- 前端页面中,有一部分是多个页面公共使用的,可以抽取公共代码方便调用,在
list.html
和dashboard.html
中抽取公共部分代码
- 发现页面公共部分为顶部导航栏和侧边栏
- 提取公共代码,在
templates
目录下创建commons
目录,在该目录下创建commons.html
用于存放公共页面代码
dashboard.html
和list.html
可以直接调用公共部分代码显示页面
- 注:replace和insert效果一样,但是insert会多套一层div标签
- 在
dashboard.html
和list.html
页面中侧边栏传参
- 在
commons.html
中接收参数并判断
18.7.3 后台编写
- 新建
EmployController
员工管理后台
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao;
@RequestMapping("/emps")
public String list(Model model){
Collection employees = employeeDao.getAll();
model.addAttribute("emps",employees);
return "emp/list";
}
}
- 注意:如果
employeeDao
爆红,去EmployeeDao
类中,加上注解@Repository
- 修改前端公共页面页面中的链接
@{/emps
}`
18.7.4 列表循环展示
- 在
list.html
添加,自己的数据循环
Section title
id
lastName
email
gender
department
birth
操作
- 此时项目结构
文章图片
- 页面展示
文章图片
18.8 添加员工信息
18.8.1 提交按钮
- 在
list.html
页面添加提交按钮
添加员工
18.8.2 跳转添加页面
- 点击添加按钮,跳转到添加信息页面
-
add.html
页面编写,其余部分代码和list.html
相同,只需修改main
标签中的代码
- 在
EmployeeController
中编写跳转到添加页的toAddPage()
方法
@GetMapping("/emp")
public String toAddPage(Model model){
//查出所有部门的信息
Collection department = departmentDao.getDepartments();
model.addAttribute("departments",department);
return "emp/add";
}
18.8.3 添加操作
- 在
EmployeeController
中编写addEmp()
方法
//添加员工
@PostMapping("/emp")
public String addEmp(Employee employee){
//添加的操作
employeeDao.save(employee);
return "redirect:/emps";
}
- 添加信息页面
文章图片
- 添加成功
文章图片
18.9 修改员工信息
18.9.1 修改按钮
- 在
list.html
中添加编辑按钮
编辑
18.9.2 跳转修改页面
update.html
编写,只需修改main
标签中的代码,其他和list.html
代码相同
- 跳转到
update.html
页面,EmployeeController
中编写toUpdateEmp()
方法
//跳转到修改页面
@GetMapping("/emp/{id}")
public String toUpdateEmp(@PathVariable("id") Integer id, Model model){
//查出修改前数据
Employee employee = employeeDao.getEmployeeById(id);
model.addAttribute("emp",employee);
//查出所有部门的信息
Collection department = departmentDao.getDepartments();
model.addAttribute("departments",department);
return "emp/update";
}
18.9.3 修改操作
- 在
EmployeeController
中编写updateEmp()
方法
//修改方法
@RequestMapping("/updateEmp")
public String updateEmp(Employee employee){
//把修改后的信息再次保存
employeeDao.save(employee);
return "redirect:/emps";
}
- 修改成功
文章图片
18.10 删除员工信息
18.10.1 删除按钮
- 在
list.html
中添加删除按钮
删除
18.10.2 删除操作
- 在
EmployeeController
中编写deleteEmp()
方法
//删除方法
@GetMapping("/delemp/{id}")
public String deleteEmp(@PathVariable("id")int id){
employeeDao.delete(id);
return "redirect:/emps";
}
- 删除成功,删除了1004号
文章图片
18.11 404页面
- 将
404.html
页面放入到templates
目录中的error
目录中
- 目录结构
文章图片
18.12 注销
- 在
commons.html
中添加注销按钮
注销
- 在
LoginController.java
中编写注销页面代码
//注销
@RequestMapping("/user/logout")
public String logout(HttpSession session){
session.invalidate();
return "redirect:/index";
}
- 注销实现
文章图片
18.13 如何开发一个网站
18.13.1 准备
- 前端涉及:页面具体样式
- 前端框架组件:Bootstrap、Layui、semantic-ui
- 设计数据库
- 前端能独立运行,独立化工程
- 数据接口如何对接:json,对象
- 前后端联调测试
- 有一套自己熟悉的后台模板:工作必须!推荐后台框架:x-admin
- 前端页面:至少自己能够通过前端框架,组合出来一个网站页面
- 让这个网站可以独立运行
推荐阅读
- Java学习笔记Day05
- SCI|小学生发SCI论文,中学生发新英格兰,这不是后浪,这是海啸啊
- java|PostMan测试接口-----上传文件、导出excel
- Java|JavaScript基础
- JavaSE|异常学习笔记
- PROG10082 面向对象
- Java|工作11年被公司辞退,中年危机怎么自救()
- JAVA人生|35岁程序员被裁后找了6份兼职,晒出收入
- java人生|985 毕业的那个大龄码农被裁了