SpringBoot 返回值 i18n 自动处理

定义基础通用类
[图片]

首先定义一波错误码:ResultCode

@Getter
@AllArgsConstructor
public enum ResultCode {
    SUCCESS(200, "请求成功", "request.success"),
    Fail(400, "请求失败", "request.failed"),

    PASSWORD_NOT_MATCH(100000, "密码不匹配", "password.not.match"),

    ......

    ;

    private final Integer code; // 错误码code
    private final String desc; // 错误码描述
    private final String i18nKey; // 国际化字符串

    ResultCode(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
        this.i18nKey = "";
    }
    
    }

定义返回对象:Result

@Getter
@Setter
public class Result<T> {
    private Integer code;
    private String message;
    private T data;

    public Result(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public Result() {

    }

    /**
     * 成功返回
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> Result<T> success(T data) {
        return new Result<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getDesc(), data);
    }

    /**
     * 失败返回
     *
     * @param message
     * @return
     */
    public static Result<Object> failed(String message) {
        return new Result<>(ResultCode.Fail.getCode(), message, null);
    }

    /**
     * @param code
     * @param message
     * @return
     */
    public static Result<Object> failed(Integer code, String message) {
        return new Result<>(code, message, null);
    }

    /**
     * @param code
     * @return
     */
    public static Result<Object> failed(ResultCode code) {
        return new Result<>(code.getCode(), code.getDesc(), null);
    }
}

定义一个异常通用类:ApiException

@Getter
@Setter
public class ApiException extends RuntimeException {
    private static final long serialVersionUID = -8412830185919566727L;

    private Integer resultCode = ResultCode.UNKNOWN_CODE.getCode();
    private String I18nKey = "";

    public ApiException(String message) {
        super(message);
    }

    public ApiException(Integer resultCode, String message) {
        this(message);
        this.resultCode = resultCode;
    }

    public ApiException(Integer resultCode) {
        this(ResultCode.Fail.getDesc());
        this.resultCode = resultCode;
    }

    public ApiException(Throwable cause) {
        super(cause);
    }

    //支持传入code对象触发i18n数据
    public ApiException(ResultCode code) {
        this(code.getDesc());
        this.resultCode = code.getCode();
        this.I18nKey = code.getI18nKey();
    }
}

定义异常拦截器:ApiExceptionHandler

/**
 * 全局异常处理类
 * 指定拦截异常的类型,被捕获的异常会调用handler方法,方法名自己随便定
 *
 **/
@RestControllerAdvice
public class ApiExceptionHandler {
    /**
     * ApiException异常处理
     *
     * @param e 异常
     * @return 返回给前端的结果
     */
    @ExceptionHandler(value = ApiException.class)
    public Result<Object> apiExceptionHandler(ApiException e) {
        String message = "";
        String i18nKey = e.getI18nKey();
        
        String i18nMessage = i18nUtils.getMessage(i18nKey);
        if(i18nMessage.isEmpty()){
            message = i18nKey;
        }else{
            message = i18nMessage;
        }
        
        if(!message.isEmpty()){
            return Result.failed(e.getResultCode(), message);
        }
        
        return Result.failed(e.getResultCode(), e.getMessage());
    }
}

定义 i18n 配置类:I18nConfig

@Slf4j
@Configuration
public class I18nConfig implements WebMvcConfigurer {
    public static final String COOKIE_NAME = "locale";

    @Resource
    WebProperties webProperties;

    @Bean(name = "messageSource")
    public ResourceBundleMessageSource getMessageSource() throws Exception {
        ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
        resourceBundleMessageSource.setDefaultEncoding("UTF-8");
        resourceBundleMessageSource.setBasenames("i18n/messages");
        resourceBundleMessageSource.setCacheSeconds(3);
        return resourceBundleMessageSource;
    }

    /**
     * @return SessionLocaleResolver
     */
    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(getDefaultLocale());
        return localeResolver;
    }

    /**
     * Cookie方式
     */
    @Bean
    public LocaleResolver localeResolver2() {
        CookieLocaleResolver clr = new CookieLocaleResolver();
        clr.setCookieName(COOKIE_NAME);
        //设置默认区域
        clr.setDefaultLocale(getDefaultLocale());
        //设置cookie有效期.
        clr.setCookieMaxAge(3600);
        return clr;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        //对请求页面路径中的参数lang进行拦截
        lci.setParamName("lang");
        return lci;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }

    private Locale getDefaultLocale() {
        Locale locale = webProperties.getLocale();
        if (locale == null) {
            locale = Locale.SIMPLIFIED_CHINESE;
        }
        return locale;
    }

}

定义 i18n 消息内容处理器:I18nUtils

@Slf4j
@Component
public class I18nUtils {
    @Resource
    private MessageSource messageSource;

    /**
     * @param key:对应文本配置的key.
     * @return 对应地区的语言消息字符串
     */
    public String getMessage(String key) {
        return this.getMessage(key, new Object[]{});
    }

    public String getMessage(String key, String defaultMessage) {
        return this.getMessage(key, null, defaultMessage);
    }

    public String getMessage(String key, String defaultMessage, Locale locale) {
        return this.getMessage(key, null, defaultMessage, locale);
    }

    public String getMessage(String key, Locale locale) {
        return this.getMessage(key, null, "", locale);
    }

    public String getMessage(String key, Object[] args) {
        return this.getMessage(key, args, "");
    }

    public String getMessage(String key, Object[] args, Locale locale) {
        return this.getMessage(key, args, "", locale);
    }

    public String getMessage(String key, Object[] args, String defaultMessage) {
        Locale locale = LocaleContextHolder.getLocale();
        String message = this.getMessage(key, args, defaultMessage, locale);
        return message;
    }

    public String getMessage(String key, Object[] args, String defaultMessage, Locale locale) {
        return messageSource.getMessage(key, args, defaultMessage, locale);
    }

}

项目集成

编写i18n翻译文件

resources/i18n/messages.properties
password.not.match=密码不匹配

resources/i18n/messages_zh_CN.properties
password.not.match=密码不匹配

resources/i18n/messages_en_US.properties
password.not.match=The password does not match

接口处理层抛出异常

if (dateList.isEmpty()) {
    throw new ApiException(ResultCode.PASSWORD_NOT_MATCH);
}

数据返回
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/656804.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

独家揭秘!Amazon、lazada、Shopee测评自养号,新手也能秒变高手!

近年来&#xff0c;随着国内卖家涌入跨境电商平台&#xff0c;市场竞争愈加激烈。为了迅速占领市场&#xff0c;测评变得至关重要。然而&#xff0c;真人测评供不应求&#xff0c;服务商账号质量不一&#xff0c;且存在高权重账号稀缺和黑卡下单风险。因此&#xff0c;许多大卖…

为什么选择CleanMyMac软件呢?推荐理由

你是否曾经遇到过这样的问题&#xff1a;电脑运行缓慢&#xff0c;存储空间不足&#xff0c;不知道如何清理垃圾文件&#xff1f;别担心&#xff0c;我们为你找到了解决方案——CleanMyMac软件。这款强大的工具可以帮助你轻松解决这些问题&#xff0c;让你的电脑焕然一新&#…

VirtualBox+Ubuntu22.10+Docker+ROS2

Docker 拉取ros2镜像 docker pull osrf/ros:foxy-desktop 运行 docker run -it --nameros2 -p 50022:22 osrf/ros:foxy-desktop 进入容器安装组件 apt-get update apt-get install vim apt-get install git apt-get install net-tools # 安装ssh apt-get install openssh…

【FPGA】正原子XC7A35T

25_实战篇&#xff1a;时钟IP核MMCM&#xff08;第一讲&#xff1a;时钟资源讲解&#xff09;_哔哩哔哩_bilibili 25时钟IP核MMCM 7系列的时钟资源 bufferG bufferR 下图可视为一个FPGA&#xff08;官方手册&#xff09; 4 MRCC,SRCC 全局时钟&#xff1a;MRCC P 差分时…

Java入门-“第九大数据类型“-字符串

字符串String **字符串(String)**是指多个字符连接起来组合成的字符序列&#xff0c;例如”中国”&#xff0c;“hello world”都为字符串。注意对比字符&#xff0c;字符只能存储一个字符使用单引号’中’&#xff0c;’国’。 字符串底层源码 字符串定义 创建String对象 St…

2024年5月软考成绩什么时候出?附查询方式

2024年5月软考成绩查询时间及查询方式&#xff1a; 查询时间&#xff1a;预计在2024年7月上旬进行。 查询方式&#xff1a; 方式一&#xff1a;登陆中国计算机技术职业资格网&#xff08;www.ruankao.org.cn&#xff09;&#xff0c;点击报名系统&#xff0c;输入注册账号和…

nodejs中使用ffmpeg零基础教程(electron+vue3)

同学们可以私信我加入学习群&#xff01; 正文开始 前言一、多方案对比二、ffmpeg各插件简介三、使用ffmpeg-static插件四、使用fluent-ffmpeg插件五、如果使用ai&#xff0c;可能会踩的坑5.1第一个坑5.2第二个坑5.3第三个坑 总结 前言 最近想要把自己写的一些知识点&#xff…

【NumPy】全面解析NumPy的astype函数:高效数据类型转换指南

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

VUE-watch和watchEffect的区别

区别简短扼要地说&#xff1a; watch-官方定义&#xff1a;侦听一个或多个响应式数据源&#xff0c;并在数据源变化时调用所给的回调函数。是需要指定监听的数据&#xff0c;并且只有在响应式数据变化的时候去执行 watchEffect-官方定义&#xff1a;立即运行一个函数&#xff0…

mybatis关联查询使用resultMap查询到了多条,结果返回一条。

今天在写代码时候&#xff0c;遇到了一个很让我费解的问题&#xff0c;在使用关联查询的时候&#xff0c;在明明数据库里面&#xff0c;已经查到了两条数据&#xff0c;结果resultMap这个集合里面&#xff0c;就只返回一条数据。 数据库的SQL&#xff1a; mybatis的xml里面的r…

公告:关于博主的重要通知

大家好&#xff0c;我是博主夏目。 本期不分享知识&#xff0c;博主想说明一下博主的一些重要提示。 分享的内容&#xff0c;从不收费&#xff0c;也未向任何人进行收费。 意在分享知识&#xff0c;传播文化&#xff0c;结交更多志同道合的朋友。 截至目前&#xff0c;从未…

多系统集成的项目周期为何普遍较长?

在现代企业的运营中&#xff0c;各种信息系统的集成已成为提升效率和竞争力的关键。然而&#xff0c;当工厂的ERP系统需要与MES、SRM、WMS、CRM等其他系统集成时&#xff0c;项目周期往往长达一年以上&#xff0c;这不仅耗费时间、人力和财力&#xff0c;还可能影响企业的正常运…

【GD32F303红枫派使用手册】第一节 RCU-时钟配置及输出实验

1.1 实验内容 通过本实验主要学习以下内容&#xff1a; RCU时钟原理及配置&#xff1b; RCU时钟输出验证。 1.2 实验原理 1.2.1 RCU时钟树原理 GD32F303系列MCU的时钟树如下图所示&#xff0c;由该图可知&#xff0c;GD32F303系列MCU的时钟树可大致分为三个部分&#xff…

外卖系统源码解读:校园外卖APP开发全攻略

外卖系统源码解读&#xff1a;校园外卖APP开发全攻略 今天&#xff0c;小编将深入解读外卖系统的源码&#xff0c;详细介绍如何开发一款功能齐全的校园外卖APP&#xff0c;帮助开发者快速上手&#xff0c;打造出高质量的外卖应用。 一、需求分析 应具备以下基本功能&#xff…

C++之对象的使用

1、static成员 2、static成员优点 2、static成员函数 静态成员函数不能访问非静态成员原因&#xff1a;因为没有this指针。也不可以访问非静态成员函数。 可以通过对象来访问静态成员&#xff0c;但是不推荐这么使用&#xff0c;会让人误解成这个x_是属于对象的&#xff0c;但…

使用prometheus监测MySQL主从同步状态方案

说明&#xff1a;本文介绍如何使用prometheus、alertmanager监测MySQL主从&#xff0c;当从节点中断同步时&#xff0c;发送邮箱报警&#xff0c;并使用grafana将数据视图化。 结构图如下&#xff1a; 安装 &#xff08;1&#xff09;安装应用 首先&#xff0c;来安装promet…

svg画简单的立方体

开发背景 要开发一个拖拽的大屏项目&#xff0c;其中涉及到一个装饰组件&#xff0c;是一个立方体cube&#xff0c;要求颜色可以修改&#xff0c;大小可以拖拽改变。 效果如下 分析 经过我一番奇思妙想&#xff0c;决定用svg实现&#xff0c;因为对svg比较熟悉。那就先来在草…

LabVIEW中实现Trio控制器的以太网通讯

在LabVIEW中实现与Trio控制器的以太网通讯&#xff0c;可以通过使用TCP/IP协议来完成。这种方法包括配置Trio控制器的网络设置、使用LabVIEW中的TCP/IP函数库进行数据传输和接收&#xff0c;以及处理通讯中的错误和数据解析。本文将详细说明实现步骤&#xff0c;包括配置、编程…

职责链设计模式

职责链设计模式&#xff08;Chain of Responsibility Design Pattern&#xff09;是一种行为设计模式&#xff0c;使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合。这些对象被链接成一条链&#xff0c;沿着这条链传递请求&#xff0c;直到有一…

【Vue】自动导入组件

1. 下载插件 npm install unplugin-vue-components 2. 修改vite.config.js import { fileURLToPath, URL } from node:urlimport { defineConfig } from vite import vue from vitejs/plugin-vue import Components from unplugin-vue-components/vite // 按需加载自定义组件/…