Spingboot落地国际化需求,Springboot按照请求的地区返回信息

@[TOC]

一、国际化

1、概述

国际化(internationalization)是设计和制造领域适应不同区域要求的产品的一种方式。它要求从产品中抽离所有地域语言,国家/地区和文化相关的元素。换言之,应用程序的功能和代码设计考虑在不同地区运行的需要,其代码简化了不同本地版本的生产。开发这样的程序的过程,就称为国际化。

2、Spring国际化

Spring国际化详解,Spring国家化实例及源码详解

二、springboot简单使用国际化

1、定义MessageSource

java 复制代码
/**
 * 国际化相关
 * @return
 */
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("messages/message");
    messageSource.setDefaultEncoding("UTF-8");
    return messageSource;
}

2、定义message配置文件

bash 复制代码
# message_en.properties
test=meiguo
test2=meiguo{0}

# message_zh.properties
test=中国

3、测试

java 复制代码
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    String message = applicationContext.getMessage("test", null, new Locale("zh"));
    System.out.println(message); // 中国

    String message2 = applicationContext.getMessage("test", null, new Locale("en"));
    System.out.println(message2); // meiguo

	String message3 = applicationContext.getMessage("test2", new String[]{"content"}, new Locale("en"));
    System.out.println(message3); // meiguocontent
}

我们发现,按照不同地区,根据配置文件获取到了不同的配置。

三、根据请求的地区获取信息

1、定义message配置文件

bash 复制代码
# message_en_US.properties
Success={0}success
Test=myTest

# message_zh_CN.properties
Success={0}成message功
Test=我的test内容

2、定义配置类

java 复制代码
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration
public class I18nConfig {

    /**
     * 国际化相关
     */
    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages/message");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }
}

3、基础模板工具

java 复制代码
import org.springframework.context.NoSuchMessageException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public interface I18nTemplateBase {


    String defaultMessage();

    String name();


    /**
     * 解析国际化模板
     */
    default String resolve(HttpServletRequest request, Object... args) {
        // 先解析参数
        List<Object> argResolveList = new ArrayList<>();
        if (args != null) {
            for (Object arg : args) {
                if (arg instanceof I18nTemplateBase) {
                    I18nTemplateBase i18nTemplateBase = (I18nTemplateBase) arg;
                    try {
                        argResolveList.add(resolveTemplate(request, i18nTemplateBase.name()));
                    } catch (NoSuchMessageException e) {
                        argResolveList.add(i18nTemplateBase.defaultMessage());
                    }
                }
            }
        }


        // 再解析最终的
        String resolveResult;
        try {
            resolveResult = resolveTemplate(request, name(), argResolveList.toArray());
        } catch (NoSuchMessageException e) {
            // 拿不到模板用默认模板
            resolveResult = MessageFormat.format(defaultMessage(), args);
        }
        return resolveResult;

    }


    /**
     * 根据key解析国际化模板
     */
    default String resolveTemplate(HttpServletRequest request, String code, Object... args) {
        Locale locale = RequestContextUtils.getLocale(request);
        WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        if (context != null) {
            return context.getMessage(String.valueOf(code), args, locale);
        } else {
            throw new NoSuchMessageException("WebApplicationContext not available");
        }
    }
}

4、消息模板定义枚举

java 复制代码
/**
 * 标准国际化消息模板
 */
public enum I18nTemplate implements I18nTemplateBase {

    Success("{0}成功"),
    Error("{0}失败"),

    Data("{0}"),

    // TODO - 定义更多消息模板
    Test("测试结果"),
    ;

    private final String defaultMessage;

    I18nTemplate(String defaultMessage) {
        this.defaultMessage = defaultMessage;
    }

    public String defaultMessage() {
        return defaultMessage;
    }

}

5、测试一下

java 复制代码
@GetMapping("/test1")
public String test1(HttpServletRequest request) {
    // 模板定制 + 参数定制
    String resolve1 = I18nTemplate.Success.resolve(request, I18nTemplate.Test);
    System.out.println(resolve1);

    // 模板定制 + 参数手输
    String resolve2 = I18nTemplate.Error.resolve(request, "手写的参数");
    System.out.println(resolve2);

    // 模板参数都手输
    String resolve3 = I18nTemplate.Data.resolve(request, "手写的参数");
    System.out.println(resolve3);
    return "success";
}
bash 复制代码
请求头:Accept-Language=en-US

结果:
myTestsuccess
手写的参数失败
手写的参数
bash 复制代码
请求头:Accept-Language=zh-CN

结果:
我的test内容成message功
手写的参数失败
手写的参数

可以实现模板消息、默认消息等。

6、总结

我们可以通过Spring的国际化,将每一个国家的语言模板都定义在配置文件中,这样就可以动态的解决数据返回的语言问题了。

真正生产环境还会将消息再进一步封装,配合httpcode码、返回的数据、请求成功状态、消息等等统一进行封装返回。此处就不进行详细分享了。

相关推荐
顾漂亮8 分钟前
Spring AOP 实战案例+避坑指南
java·后端·spring
间彧19 分钟前
Redis Stream相比阻塞列表和发布订阅有哪些优势?适合什么场景?
后端
间彧24 分钟前
Redis阻塞弹出和发布订阅模式有什么区别?各自适合什么场景?
后端
苏三说技术32 分钟前
统计接口耗时的6种常见方法
后端
SimonKing37 分钟前
Mybatis-Plus的竞争对手来了,试试 MyBatis-Flex
java·后端·程序员
我命由我123451 小时前
PDFBox - PDFBox 加载 PDF 异常清单(数据为 null、数据为空、数据异常、文件为 null、文件不存在、文件异常)
java·服务器·后端·java-ee·pdf·intellij-idea·intellij idea
渣哥1 小时前
当容器里有多个 Bean,@Qualifier 如何精准定位?
javascript·后端·面试
7哥♡ۣۖᝰꫛꫀꪝۣℋ1 小时前
Spring Boot
java·spring boot·后端
浩泽学编程1 小时前
【源码深度 第1篇】LinkedList:双向链表的设计与实现
java·数据结构·后端·链表·jdk
哲此一生9841 小时前
创建一个SpringBoot项目(连接数据库)
java·spring boot·后端