环境准备

静态资源

  • HTML页面放入templates文件夹下
  • CSS、JS、图片等放在static文件夹下

数据准备

  • 这里未使用数据库,需要伪造数据。首先创建实体类
1
2
3
4
5
6
7
8
// 部门表
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department {
private Integer id;
private String departmentName;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 员工表
@Data
@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, Date birth) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.department = department;
// 默认创建日期
this.birth = new Date();
}
}
  • 在Dao层模拟数据库数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 部门Dao
@Repository
public class DepartmentDao {
// 模拟数据库中的数据
private static Map<Integer, Department> departmentmap = null;
static {
departmentmap = new HashMap<>(); //创建一个部门表
departmentmap.put(101,new Department(101,"教学部"));
departmentmap.put(102,new Department(102,"市场部"));
departmentmap.put(103,new Department(103,"教研部"));
departmentmap.put(104,new Department(104,"运营部"));
departmentmap.put(105,new Department(105,"后勤部"));
}

// 获取所有部门学校
public Collection<Department> getDepartments(){
return departmentmap.values();
}
// 通过id得到部门
public Department getDepartmentByID(Integer id){
return departmentmap.get(id);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 员工Deao
@Repository
public class EmployeeDao {
// 模拟数据库中的数据
private static Map<Integer, Employee> employeeMap = null;
// 员工有所属的部门
@Autowired
private DepartmentDao departmentDao;
static {
employeeMap = new HashMap<>(); //创建一个员工表
employeeMap.put(101,new Employee(101,"张三","A247312312@qq.com",1,new Department(101,"教学部"),new Date()));
employeeMap.put(102,new Employee(102,"李四","B247312312@qq.com",0,new Department(102,"市场部"),new Date()));
employeeMap.put(103,new Employee(103,"王五","C247312312@qq.com",1,new Department(103,"教研部"),new Date()));
employeeMap.put(104,new Employee(104,"赵六","D247312312@qq.com",0,new Department(104,"运营部"),new Date()));
employeeMap.put(105,new Employee(105,"老白","E247312312@qq.com",1,new Department(105,"后勤部"),new Date()));
}
// 增加一个员工,主键自增
private static Integer initID = 1006;

public void save(Employee employee){
if(employee.getId() == null){
employee.setId(initID++);
}
employee.setDepartment(departmentDao.getDepartmentByID(employee.getDepartment().getId()));
employeeMap.put(employee.getId(),employee);
}
// 获得查询全部员工信息
public Collection<Employee> getAll(){
return employeeMap.values();
}
//通过ID查询员工
public Employee getEmployeeByID(Integer id){
return employeeMap.get(id);
}
// 删除员工通过id
public void delete(Integer id){
employeeMap.remove(id);
}
}

首页实现

视图跳转

  • 视图跳转有两种实现方式,第一种是写一个Controller进行跳转
1
2
3
4
5
6
7
8
@Controller
public class IndexController {
// /和/index.html都映射到首页,但不建议用这种方法实现
@RequestMapping({"/","/index.html"})
public String index(){
return "index";
}
}
  • 第二种方法是写一个/config包下的扩展SpringMVC
1
2
3
4
5
6
7
8
9
//扩展springmvc
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}

静态资源

  • 打开页面发现静态资源加载不出来,这是因为Thymeleaf没配好
  • 首先要配置约束头
1
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  • URL静态资源的引入,首先@{/}就代表资源根目录,其用于定义URL,比如/static/
1
2
<!--/static/css/..-->
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
  • 如果页面还是没有效果,可能是模板引擎缓存的影响,可以在配置文件中去掉缓存
1
spring.thymeleaf.cache=false
  • 图片的引入也是一样,属性前加th:即可
1
<img th:src="@{/img/bootstrap-solid.svg}">

在线链接不需要加th:

  • @{/}是万能匹配的,比如更改项目虚拟路径
1
server.servlet.context-path=/lzy

国际化

准备工作

  • 先在IDEA中统一设置properties的编码问题!确保为UTF-8
  • 编写国际化配置文件,抽取页面需要显示的国际化页面消息。我们可以去登录页面查看一下,哪些内容我们需要编写国际化的配置!

配置文件编写

  • resources资源文件下新建一个i18n目录,存放国际化配置文件
  • 建立一个login.properties文件,还有一个login_zh_CN.properties;发现IDEA自动识别了我们要做国际化操作;文件夹变了!

  • 可以在这资源包上面去新建一个文件;

  • 弹出如下页面:再添加一个英文的;

  • 这样就快多了

  • 接下来,我们就来编写配置,我们可以看到idea编辑区左下面有另外一个视图;

  • 这个视图我们点击 + 号就可以直接添加属性了;我们新建一个login.tip,可以看到边上有三个文件框可以输入

  • 然后依次添加其他页面内容即可!

  • 然后去查看我们的配置文件;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# login.properties(默认)
login.btn=请登录
login.passwod=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

# login_en_US.properties(英文)
login.btn=Sign in
login.passwod=Password
login.remember=Remember me
login.tip=Please sign in
login.username=Username

# login_zh_CN.properties(中文)
login.btn=请登录
login.passwod=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

配置文件生效探究

  • 我们去看一下SpringBoot对国际化的自动配置!这里又涉及到一个类:MessageSourceAutoConfiguration
  • 里面有一个方法,这里发现SpringBoot已经自动配置好了管理我们国际化资源文件的组件 ResourceBundleMessageSource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 获取 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的路径;
1
spring.messages.basename=i18n.login

配置页面国际化值

  • 去页面获取国际化的值,查看Thymeleaf的文档,找到message取值操作为:#{...}。我们去页面测试下:

  • 去启动项目,访问一下,发现已经自动识别为中文的了!

  • 但是我们需要可以根据按钮自动切换中文英文!

配置国际化解析

  • 在Spring中有一个国际化的Locale (区域信息对象);里面有一个叫做LocaleResolver (获取区域信息对象)的解析器!
  • 我们去我们webmvc自动配置文件,寻找一下!看到SpringBoot默认配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver() {
// 容器中没有就自己配,有的话就用用户配置的
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 这个类中有一个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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,可以在链接上携带区域信息!
  • 修改一下前端页面的跳转连接:
1
2
3
<!-- 这里传入参数不需要使用 ?使用 (key=value)-->
<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包下新建一个MyLocaleResolver类·
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//可以在链接上携带区域信息
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request) {
// 获取请求中的语言参数
String language = request.getParameter("l");
Locale locale = Locale.getDefault(); // 如果没有获取到就使用系统默认的
//如果请求链接不为空
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) {

}
}
  • 为了让我们的区域化信息能够生效,我们需要再配置一下这个组件!在我们自己的MvcConofig下添加bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//扩展springmvc
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
@Override
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
  • 重启项目,来访问一下,发现点击按钮可以实现成功切换!