Spring Boot学习系列(七)------国际化实现

Spring Boot学习系列(七)------国际化实现

前言

基本上了解了SpringBoot的项目使用之后,也需要自己动手来多练习,因此这篇文章,来写一个很简单的Demo,使用SpringBoot来实现国际化.

正文

1. 创建项目,实现首页的默认访问

首先我们使用IDEA来创建一个SpringBoot项目,仅仅添加了Web模块,项目结构如下:
在这里插入图片描述

接下来我们引入要用的页面:

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
	<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 href="asserts/css/bootstrap.min.css"  rel="stylesheet">
		<!-- Custom styles for this template -->
		<link href="asserts/css/signin.css"  rel="stylesheet">
	</head>
	<body class="text-center">
		<form class="form-signin" action="dashboard.html" th:action="@{/user/login}" method="post">
			<img class="mb-4"  src="asserts/img/bootstrap-solid.svg" alt="" width="72" height="72">
			<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
			<!--判断-->
			<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
			<label class="sr-only" >Username</label>
			<input type="text"  name="username" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
			<label class="sr-only" >Password</label>
			<input type="password" name="password" class="form-control" placeholder="Password" th:placeholder="#{login.password}" required="">
			<div class="checkbox mb-3">
				<label>
          			<input type="checkbox" value="remember-me"/> Remember Me
        		</label>
			</div>
			<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
			<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
			<a class="btn btn-sm" >中文</a>
			<a class="btn btn-sm" >English</a>
		</form>
	</body>

</html>

可以看到,在页面中引入了一些css样式,还有bootstrap的样式,这里我们使用webjars的方式来引入jar文件.,打开https://www.webjars.org/,我们引入Bootstrap的pom坐标"

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.1.3</version>
</dependency>

可以看到依赖中已经存在了:
在这里插入图片描述

接着引入Thymeleaf

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring‐boot‐starter‐thymeleaf</artifactId>
        </dependency>

因为SpringBoot已经帮我们控制版本,所以我们不需要指定版本,版本的切换查看我的其他博文即可.

引入了对应的文件以后,我们先来写个controller:

@Controller
public class IndexController {

    @RequestMapping({"/", "/index.html"})
    public  String login() {
        return "login";
    }

}

OK,现在我们访问http://localhost:8080/,可以成功访问页面了:

在这里插入图片描述

如果没有修改login.html中的图片路径,图片是看不到的,要修改一下:

<img class="mb-4"  src="asserts/img/bootstrap-solid.svg" th:src="@{asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
    
    还要修改页面中的js文件的引用路径

现在,我们使用的controller增加方法的方式来跳转到登录页面的,我们知道,SpringBoot为我们自动配置了很多的东西,其实,我们可以直接自定义一个配置类,直接在配置类中增加页面的跳转映射:

这里需要注意,我们前面的博文中讲到,要实现自己的配置,需要继承类WebMvcConfigurerAdapter,但是在SpringBoot2.0中,这个方法已经过时了,但是我们可以直接实现接口WebMvcConfigurer,得益于java1.8的新特性,现在接口的方法可以选择实现,不用全部实现,因此我们可以实现以下方法来增加:

@Configuration//这个自定义的配置要继承
public class MyConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
    }
}

这里需要注意,如果我们使用了注解@Configuration,就不必使用@Bean注解来注册这个配置类,这样,当我们访问http://localhost:8080/login的时候,页面也会跳转到登录页面,使用这样的方式可以不用写controller层的方法.

2.实现页面国际化

目前我们的页面是这样的:

在这里插入图片描述

可以看到,页面上有五个地方需要国际化转化,目前没有完成的情况下,点击页面中的中文English是没有效果的.

下面我们来实现国际化页面:

  1. 编写国际化配置文件,抽取页面需要格式化的信息

在这里插入图片描述

如图,在resource目录下创建一个目录用来保存国际化属性文件,创建对应的页面属性文件,文件中的五个属性分别对应login页面中需要国际化的信息.

  1. 使用SpringBoot的国际化管理组件

    在以前使用SpringMVC的时候,我们要自己写一个国际化信息管理组件,现在使用了SpringBoot以后,我们直接使用即可,查看SpringBoot的代码可以看到有一个组件:MessageSourceAutoConfiguration,这是SpringBoot帮我们配置好的,我们可以看一下这个类"

    public class MessageSourceAutoConfiguration {
        private static final Resource[] NO_RESOURCES = new Resource[0];
    
        public MessageSourceAutoConfiguration() {
        }
    
        @Bean
        @ConfigurationProperties(
            prefix = "spring.messages"
        )
        @Bean
        public MessageSource messageSource() {
            MessageSourceProperties properties = this.messageSourceProperties();
            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;
        }
    

    **可以看到,SpringBoot自动装配的国际化组件使用的属性名是message,如果我们的属性文件命名为message,就可以直接在页面使用.**在这里我们使用了自己的,所以需要在配置文件中定义一个属性:

    spring.messages.basename=international.login
    

    属性值指向国际化文件,这样我们就可以取值了.

  2. 在页面获取国际化的值

    在Thymeleaf中,可以使用#{}来获取国际化的值,所以我们修改一下html文件:

    <!DOCTYPE html>
    <html lang="en"  xmlns:th="http://www.thymeleaf.org">
    	<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 href="asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.1.3/css/bootstrap.css}" rel="stylesheet">
    		<!-- Custom styles for this template -->
    		<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
    	</head>
    	<body class="text-center">
    		<form class="form-signin" action="dashboard.html"  method="post">
    			<img class="mb-4"  src="asserts/img/bootstrap-solid.svg" th:src="@{asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
    			<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
    			<!--判断-->
    			<p style="color: red" ></p>
    			<label class="sr-only" th:text="#{login.username}">Username</label>
    			<input type="text"  name="username" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
    			<label class="sr-only" th:text="#{login.password}">Password</label>
    			<input type="password" name="password" class="form-control" placeholder="Password" th:placeholder="#{login.password}" required="">
    			<div class="checkbox mb-3">
    				<label>
              			<input type="checkbox" value="remember-me"/> Remember Me [[#{login.remember}]]
            		</label>
    			</div>
    			<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
    			<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
    			<a class="btn btn-sm" >中文</a>
    			<a class="btn btn-sm" >English</a>
    		</form>
    	</body>
    
    </html>
    

    启动项目,可以看到,页面已经变成了中文,需要注意的是,SpringBoot的国际化是按照浏览器的默认语言来设置的,如果我们修改了浏览器的语言为英语,刷新一下以后,页面会自动切换成英语的.

4.根据点击按钮来实现语言切换

现在页面有两个按钮,我们要实现点击不同的按钮,切换不同的语言,就要明白SpringBoot实现国际化的原理:

当一个请求到达服务端以后,SpringBoot会有一个区域信息解析器LocaleResolver来解析请求头中的区域信息,根据不同的请求内容,响应不同的国际化内容,我们可以查看WebMvcAutoConfiguration类:

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(
            prefix = "spring.mvc",
            name = {"locale"}
        )
        public LocaleResolver localeResolver() {
            if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
                return new FixedLocaleResolver(this.mvcProperties.getLocale());
            } else {
                AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
                localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
                return localeResolver;
            }
        }

可以看到,默认情况下,SpringBoot使用自己的区域信息解析器来解析国家化信息的,我们要实现这个需求,只需要自己创建一个解析器,并添加到容器中即可:

package com.xiaojian.springboot.international.component;

import org.springframework.context.annotation.Configuration;
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 MyLocaResolver implements LocaleResolver {

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        System.out.println("区域信息解析器~~~~~~~~~~");
        String local = request.getParameter("local");
        Locale locale = Locale.getDefault();
        if (!StringUtils.isEmpty(local)) {
            String[] split = local.split("_");
            locale = new Locale(split[0], split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}

然后在配置类中注册bean:

    @Bean
    public LocaleResolver localeResolver() {
        return new MyLocaResolver();
    }

然后更改页面中两个按钮的连接地址:

			<a class="btn btn-sm" th:href="@{/login(local='zh_CN')}">中文</a>
			<a class="btn btn-sm" th:href="@{/login(local='en_US')}">English</a>

启动项目以后,点击按钮就可以实现不同的语言切换.

总结

至此,国际化的功能初步实现了,回头看来,SpringBoot在初始化以后,为我们配置了很多的组件来方便我们的开发,我们要自己定制化,就要写好自己的组件并注册使用.

猜你喜欢

转载自blog.csdn.net/xiaoyao2246/article/details/82968392