文章目录
九、一个简单的员工管理系统
- 这个系统不是完整的,它只是为了看一下,使用SpringBoot开发,我们要进行哪些操作!
9.1准备工作
-
导入lombok 依赖
-
Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。用在实体类中,用注解生成构造方法,get/set,等方法
-
@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
-
导入lombok需要安装插件:可以参考这个文章:https://www.freesion.com/article/5093806462/
-
<!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <version>1.18.2</version> </dependency>
-
之后编写实体类Department ,Employee,以及对应的dao ,DepartmentDao,EmployeeDao
9.2首页实现
-
首页配置:注意点:所有页面的静态资源导入都需要使用Thymeleaf接管,步骤为导入命名空间,之后将静态资源的链接变为 th:href="@{/css/bootstrap.min.css}" ,这个地方的链接开头一定要是/ ,如果我们在application.properties 配置文件中,重新定义了项目的访问路径,springboot会帮我们在链接前加上新的访问路径
-
index.html 看第2,10,12行,
<!DOCTYPE html> <html lang="en" xml:th="http://www.thymeleaf.org" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>Signin Template for Bootstrap</title> <!-- Bootstrap core CSS --> <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"> <!-- Custom styles for this template --> <link th:href="@{/css/signin.css}" rel="stylesheet"> </head> <body class="text-center">...</body> </html>
-
application.properties
#关闭模板引擎缓存 spring.thymeleaf.cache=false # 新的访问路径 server.servlet.context-path=/wlw
-
重新定义了项目的访问路径,之后重新访问,并查看源代码
9.3页面国际化
- 有的时候,我们的网站会去涉及中英文甚至多语言的切换,这时候我们就需要学习国际化了!
9.3.1准备工作
- 先在IDEA中统一设置properties的编码问题!
9.3.2配置文件编写
-
编写国际化配置文件,抽取页面需要显示的国际化页面消息。我们可以去登录页面查看一下,哪些内容我们需要编写国际化的配置!
-
1、我们在resources资源文件下新建一个i18n目录,存放国际化配置文件
-
2、建立一个login.properties文件,还有一个login_zh_CN.properties;发现IDEA自动识别了我们要做国际化操作;文件夹变了!
-
3、我们可以在这上面去新建一个文件; 弹出如下页面:我们再添加一个英文的;
-
4、接下来,我们就来编写配置,我们可以看到idea下面有另外一个视图;
-
这个视图我们点击 + 号就可以直接添加属性了;我们新建一个login.tip,可以看到边上有三个文件框可以输入;
-
我们添加一下首页的内容!
-
然后依次添加其他页面内容即可!
-
然后去查看我们的配置文件;
# login.properties login.password=密码 login.remember=记住我 login.tip=请登录 login.username=用户名 loign.btn=登录
#login_zh_CN.properties login.password=密码 login.remember=记住我 login.tip=请登录 login.username=用户名 loign.btn=登录
#login_en_US.properties login.password=Password login.remember=Remember me login.tip=Please sign in login.username=Username loign.btn=Sign in
- OK,配置文件步骤搞定!
-
-
9.3.3配置文件生效探究
-
我们去看一下SpringBoot对国际化的自动配置!这里又涉及到一个类:MessageSourceAutoConfiguration
-
里面有一个方法,这里发现SpringBoot已经自动配置好了管理我们国际化资源文件(就是在i8n文件夹下的文件)的组件 ResourceBundleMessageSource; (这个东西是识别国际化配置信息文件里的信息,而下面的那个LocaleResolver 是判断我们是否自己写了国家化配置信息文件)
// 获取 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目录下,所以我们要去配置这个messages的路径;
spring.messages.basename=i18n.login
9.3.4配置页面国际化值
-
去页面获取国际化的值,查看Thymeleaf的文档,找到message取值操作为:#{…}。我们去页面测试下:
-
我们可以去启动项目,访问一下,发现已经自动识别为中文的了!
-
但是我们想要更好!可以根据按钮自动切换中文英文!
9.3.5配置国际化解析
-
在Spring中有一个国际化的Locale (区域信息对象);里面有一个叫做LocaleResolver (获取区域信息对象)的解析器!
-
我们去我们webmvc(WebMvcAutoConfiguration.java)自动配置文件,寻找一下!看到SpringBoot默认配置:
@Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "spring.mvc", name = "locale") public LocaleResolver localeResolver() { // 容器中没有就自己配,有的话就用用户配置的(在application.properties配置文件中 spring.messages.basename=i18n.login 这一句就是绑定用户自己配置的国家化信息) if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.mvcProperties.getLocale()); } // 接收头国际化分解 AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); localeResolver.setDefaultLocale(this.mvcProperties.getLocale()); return localeResolver; }
-
AcceptHeaderLocaleResolver 这个类中有一个方法 (这是源码给的一个国际化(地区)解析器,我们也可以自己写一个)
public class AcceptHeaderLocaleResolver implements LocaleResolver{ ... public Locale resolveLocale(HttpServletRequest request) { Locale defaultLocale = this.getDefaultLocale(); // 默认的就是根据请求头带来的区域信息获取Locale进行国际化 if (defaultLocale != null && request.getHeader("Accept-Language") == null) { return defaultLocale; } else { Locale requestLocale = request.getLocale(); List<Locale> supportedLocales = this.getSupportedLocales(); if (!supportedLocales.isEmpty() && !supportedLocales.contains(requestLocale)) { Locale supportedLocale = this.findSupportedLocale(request, supportedLocales); if (supportedLocale != null) { return supportedLocale; } else { return defaultLocale != null ? defaultLocale : requestLocale; } } else { return requestLocale; } } } ... }
-
那假如我们现在想点击链接让我们的国际化资源生效,就需要让我们自己的Locale生效!我们去自己写一个自己的LocaleResolver,可以在链接上携带区域信息!修改一下前端页面的跳转连接:
<!-- 这里传入参数不需要使用 ?使用 (key=value)--> <a class="btn btn-sm" th:href="@{/index.html(language='zh_CN')}">中文</a> <a class="btn btn-sm" th:href="@{/index.html(language='en_US')}">English</a>
-
我们去写一个处理的组件类!
package com.wlw.config; import org.springframework.util.StringUtils; import org.springframework.web.servlet.LocaleResolver; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Locale; //自定义 国际化解析器 public class MyLocalResolver implements LocaleResolver { //解析请求 @Override public Locale resolveLocale(HttpServletRequest request) { //获取请求参数 String language = request.getParameter("language"); Locale locale = Locale.getDefault();//如果没有就使用默认的 //如果请求的链接中携带了国际化的参数,就获取,拆分 if(!StringUtils.isEmpty(language)){ String[] split = language.split("_"); //zh_CN //国家,地区 locale = new Locale(split[0],split[1]); } return locale; } @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { } }
-
为了让我们的区域化信息能够生效,我们需要再配置一下这个组件!在我们自己的MvcConfig下添加bean;
//自定义的国家化组件就生效了 @Bean //注入组件 public LocaleResolver localeResolver(){ return new MyLocalResolver(); }
-
我们重启项目,来访问一下,发现点击按钮可以实现成功切换!搞定收工!
9.3.6总结
- 页面国家化步骤:
- 我们需要配置i18n文件,并在application.properties配置文件中绑定,之后在对应的html中用thymeleaf获取(获取国家化信息使用#{} ,链接url是@{} ,变量${})
- 如果我们需要在项目中进行按钮自动切换,我们需要自己定义一个组件MyLocalResolver继承LocaleResolver
- 记得将自己写的组件配置到spring容器中,@Bean
9.4登录功能与登录拦截器
- LoginController
package com.wlw.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
@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) && "123456".equals(password)){//登录成功(理解过程)
session.setAttribute("loginUser",username); //保存登录信息,用于拦截器
return "redirect:/main.html"; //重定向
}else { //失败
model.addAttribute("msg","用户名或密码错误"); //返回到index的提示信息
return "index";
}
}
}
- LoginHnadlerInterceptor
package com.wlw.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginHnadlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
//登录成功之后应有 用户的session
if(session.getAttribute("loginUser") == null){ //登录失败
request.setAttribute("msg","没有权限,请先登录!");
request.getRequestDispatcher("/index.html").forward(request,response);//转发到index.html 显示提示信息
return false;
}else { //登录成功
return true;
}
}
}
- MyMvcConfig
package com.wlw.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
//如果你想diy一些定制化的功能,只要写这个组件,然后把它交给SpringBoot,SpringBoot就会帮我们自动装配
@Configuration //这个注解表明这是扩展的SpringMVC
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
registry.addViewController("/main.html").setViewName("dashboard");
}
//自定义的国际化组件就生效了
@Bean //注入组件
public LocaleResolver localeResolver(){
return new MyLocalResolver();
}
//拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHnadlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/index.html","/","/user/login","/css/**","/js/**","img/**");
}
}
9.5展现员工列表
-
这一部分主要是对前端页面的学习,学习thymeleaf的应用,主要还是要通过Thymeleaf文档来学习,在这官网如果进不去,可以参考https://blog.csdn.net/liuminglei1987/article/details/106692004 ,这是个一篇Thymeleaf参考手册的博客,感谢博主总结!
-
要知道thymeleaf ,获取普通变量值 . . . ; 选 择 表 达 式 ∗ . . . : 和 {...} ; 选择表达式 *{...}:和 ...;选择表达式∗...:和{}在功能上是一样;获取国际化内容 #{…}
;定义URL @{…} ; 片段引用表达式 ~{…} -
抽取 重复的前端代码: 在第一层标签中加上 th:fragment=“templatename” ,之后在需要这段代码的位置使用属性 th:insert 或 th:replace 属性,表达式是 “~{templatename::fragmentname}”,如图
-
如果要传递参数,可以直接使用() 传参,此处做了一个选中高亮显示
-
列表循环展示
<table class="table table-striped table-sm"> <thead> <tr> <th>id</th> <th>lastName</th> <th>email</th> <th>gender</th> <th>birth</th> <th>department</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()==0?'女':'男'}"></td> <td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td> <td th:text="${emp.department.getDepartmentName()}"></td> <td> <button class="btn btn-sm btn-primary">编辑</button> <button class="btn btn-sm btn-danger">删除</button> </td> </tr> </tbody> </table>
9.6添加,修改与删除员工
-
主要是一个逻辑操作,和之前的操作差不多,新东西还是thymeleaf在各个标签的用法
-
看代码吧
-
项目为:springboot_03_web
9.7错误处理
- 很简单,只要在templates文件夹下建立一个error文件夹,并且里面的html文件是以404或500这样的错误代码命名的,当出现错误时,会自动的寻找对应的错误显示页面