背景

国际化是指在设计软件,将软件与特定语言及地区脱钩的过程。当软件被移植到不同的语言及地区时,软件本身不用做内部工程上的改变或修正。

本文提到的异常响应信息国际化是指:前端向后台发起请求,后台在处理逻辑中发生异常,把异常信息返回给前端,返回的异常信息应该支持国际化,能够对应特定的语言、地区等环境。例如,中文语言环境下返回的异常信息应该是中文的,英文语言环境下返回的则是对应的英文。

javaweb项目中,不管是对底层的数据操作,还是业务层的处理过程,还是控制层的处理,都不可避免的会遇到各种可预知的(业务异常主动抛出)、不可预知的异常需要处理。一般dao层、service层的异常都会直接抛出,最后由controller统一进行处理,并对前端请求进行异常响应。针对此处的业务异常应该做到设计合理,统一格式,并且支持国际化。

springboot是一个开源的Java/Java EE的应用程序框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。利用springboot提供的API库,我们能方便地做到全局异常统一拦截,并且Spring提供了完善的国际化支持,在此基础上,我们能方便地做到全局异常信息的国际化。

原来存在的方案:

  1. 局部的异常信息国际化:程序在抛出异常时手动设置好国际化之后的异常message。

    此种方案代码耦合性强,代码繁琐,处理逻辑过程中抛出异常时还得额外考虑对异常进行国际化操作,使得代码逻辑无法很好的集中在业务逻辑的处理。示意图如图1.1。

  2. 半异常信息国际化:程序中未采用配置文件来记录国际化资源,而是直接在程序中写死了固定的异常值,每条异常值记录分别对应着不同的异常编号、某几种语言的异常信息。

    这是目前比较常见的方式,写起来方便,不需要在程序抛出异常时做国际化,只需在全局异常拦截中做统一的异常返回。但是,这种方式支持的异常信息比较单一,不能轻易添加多种语言的支持,只能改动现有程序的代码。示意图如图1.2。

  3. 使用编程语言自带的异常本地化接口。

    不少后台语言提供了异常信息本地化接口,比如java提供的java.lang.Throwable#getLocalizedMessage方法,但是这种方式只能获取到本地语言相关的对应的信息,并不能很好的支持多种语言,以及多种语言间的自由切换。

现在的方案

此方案结合异常码、字符串占位符和资源文件的特点及优势。异常码可理解为一个异常信息的ID,具有唯一性,必要性;异常信息资源文件中的值可包含占位符(格式为{n}),处理异常时可用实际值替换,达到异常信息的进一步具体化,但不是必须的。资源文件就是内容为“异常码=提心信息”的记录的文件。

方案具体描述如下:

  1. 首先,在springboot项目中定义系统的http请求统一返回的数据格式,此处我们的定义包含三个属性: code(业务异常状态码)、message(异常提示信息)、data(无异常时返回的数据体)。对异常信息国际化主要体现在message属性,也就是返回前端给用户展示的异常提示信息。code属性用于确定唯一的异常。其次定义需要抛出的业务异常,其中主要包括code(异常码)和params(用于替换异常信息字符串占位符{n}的实际值)属性。

  2. 在项目路径下定义异常信息的资源文件,文件内容包含多条记录,每条记录为键值对的形式,即key=value。对需要实现的语言种类分别提供一份对应的文件,这些文件名除默认信息外,均包含语言(地区信息),文件中包含中key是一致的,value为相应语言的字符串组成。如果添加语言的支持,只需要添加一份对应的资源文件即可。以下包含默认、英文环境和简体中文环境下对应的异常提示信息国际化资源文件,如图2.1

  3. 利用springboot的提供的接口定义统一拦截器,并且注入http请求上下文和资源获取器,在拦截器中对应用抛出的异常进行捕获,针对上述特定的异常做国际化处理。
    其国际化处理逻辑如下:根据http请求传入的语言信息指定特定的语言(地区)环境,如没有传入语言信息,则采用应用默认的语言配置;据此读取上述编写好的对应的异常信息资源文件,并依据捕获的异常中的code(异常码)查到到对应的字符串,将params实际值替换掉字符串中的占位符,完成后即为返回给前端的异常提示信息。

  4. 在controller、service和dao层中根据程序逻辑抛出相应异常,其中异常码应该在资源文件中已定义。示例代码如下图2.3

  5. 整体流程图如下图2.4

demo

以下是一个demo,其中提供了必要的代码注释,以便于理解。

  • 自定义异常结构,包含code和params

  • 异常资源文件定义

  • 全局异常拦截

  • 代码逻辑中抛出异常

  • 请求响应示例

请求1:http://127.0.0.1:8080/demo?lang=en&msg=a

返回:

请求2:http://127.0.0.1:8080/demo?lang=zh_CN&msg=a

返回:

请求3:http://127.0.0.1:8080/demo?lang=en&msg=c

返回:

请求4:http://127.0.0.1:8080/demo?lang=zh_CN&msg=c
返回:

总结

  1. 此方案能较好地处理异常信息的国际化,能自如地添加资源文件,不需要改动此方案的现有代码,这也使得程序耦合性降低;
  2. 统一的异常格式定义、全局异常拦截极大程度上减少了代码耦合性,大大简化了团队编码中对异常逻辑的处理,能减少重复性编码,有利于提高工作效率;
  3. 现有方案未能较好地支持异常信息中特定值的支持,此方案利用设置占位符的方式,较好地做到了支持,灵活方便;
  4. springboot支持的国际化实现中默认提供了缓存支持,性能良好。

参考

(文中配图有空再改!!)

基于springboot实现http响应异常信息国际化的更多相关文章

  1. springboot 1.3.5升级1.5.9后 默认使用tomcat 8.5版本 get请求报400 异常信息为 The valid characters are defined in RFC 7230 and RFC 3986

    1.springboot 1.3.5升级1.5.9后 默认使用tomcat 8.5版本而之前用的是tomcat7    get请求报400 异常信息为 The valid characters are ...

  2. c#执行插入sql 时,报错:异常信息:超时时间已到。在操作完成之前超时时间已过或服务器未响应

    问题:c#执行插入sql 时,报错:异常信息:超时时间已到.在操作完成之前超时时间已过或服务器未响应 解决: SqlCommand cmd = new SqlCommand(); cmd.Comman ...

  3. springboot 统一管理异常信息

    新建ResponseEntityExceptionHandler的继承类:(依然,需要入口类扫描) /** * @author sky * @version 1.0 */ @ControllerAdv ...

  4. 基于SpringBoot搭建应用开发框架(二) —— 登录认证

    零.前言 本文基于<基于SpringBoot搭建应用开发框架(一)——基础架构>,通过该文,熟悉了SpringBoot的用法,完成了应用框架底层的搭建. 在开始本文之前,底层这块已经有了很 ...

  5. shiro,基于springboot,基于前后端分离,从登录认证到鉴权,从入门到放弃

    这个demo是基于springboot项目的. 名词介绍: ShiroShiro 主要分为 安全认证 和 接口授权 两个部分,其中的核心组件为 Subject. SecurityManager. Re ...

  6. 基于springboot的web项目最佳实践

    springboot 可以说是现在做javaweb开发最火的技术,我在基于springboot搭建项目的过程中,踩过不少坑,发现整合框架时并非仅仅引入starter 那么简单. 要做到简单,易用,扩展 ...

  7. 基于SpringBoot+AntDesign的快速开发平台,JeecgBoot 2.0.2 版本发布

    Jeecg-Boot 是一款基于SpringBoot+代码生成器的快速开发平台! 采用前后端分离架构:SpringBoot,Ant-Design-Vue,Mybatis,Shiro,JWT. 强大的代 ...

  8. 搭建基于springboot轻量级读写分离开发框架

    何为读写分离 读写分离是指对资源的修改和读取进行分离,能解决很多数据库瓶颈,以及代码混乱难以维护等相关的问题,使系统有更好的扩展性,维护性和可用性. 一般会分三个步骤来实现: 一. 主从数据库搭建 信 ...

  9. Shiro 核心功能案例讲解 基于SpringBoot 有源码

    Shiro 核心功能案例讲解 基于SpringBoot 有源码 从实战中学习Shiro的用法.本章使用SpringBoot快速搭建项目.整合SiteMesh框架布局页面.整合Shiro框架实现用身份认 ...

随机推荐

  1. SpringCloud (一)Eureka注册中心搭建

    前提 系统安装jdk1.8及以上,配置好maven的ide(这里用idea进行演示,maven版本3.5,配置阿里云源) 项目搭建 新建一个maven项目,创建最简单的那种就好,项目名这里为Eurek ...

  2. windows安装zookeeper和kafka,flume

    一.安装JDK 过程比较简单,这里不做说明. 最后打开cmd输入如下内容,表示安装成功 二.安装zooeleeper 下载安装包:http://zookeeper.apache.org/release ...

  3. a 标签传值

    转载:http://blog.csdn.net/muyeju/article/details/48594377 .<a>标签传值的形式--参数固定:<a href="地址? ...

  4. 【洛谷 P3199】 [HNOI2009]最小圈(分数规划,Spfa)

    题目链接 一开始不理解为什么不能直接用\(Tarjan\)跑出换直接求出最小值,然后想到了"简单环",恍然大悟. 二分答案,把所有边都减去\(mid\),判是否存在负环,存在就\( ...

  5. 【洛谷 P1772】 [ZJOI2006]物流运输(Spfa,dp)

    题目链接 \(g[i][j]\)表示不走在\(i\text{~}j\)时间段中会关闭的港口(哪怕只关\(1\)天)从\(1\)到\(m\)的最短路. \(f[i]\)表示前\(i\)天的最小花费.于是 ...

  6. Vue修改mint-ui默认样式(默认风格)

    加入my-mint.css 我这里用的postcss的变量定义,如果亲们用的是其他预处理器,要改成其他处理器的定义方式 覆盖mint-ui的primary颜色,改为自己UI的主题色 --main-co ...

  7. zedboard学习记录.2.PS+PL 流水灯与uart

    1.建立一个工程. 硬件设计 2.IP integrator -> create block desgin;Run Block Automation. 3.add IP -> AXI GP ...

  8. C#里面中将字符串转为变量名

    public partial class Form1 : Form { string str = "spp"; public string spp = "very goo ...

  9. 在字符串S1中删除字符串S2中所包含的字符【转】

    转自:http://www.cnblogs.com/tolimit/p/4202959.html /************************************************** ...

  10. Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x7f070058 android-studio 3.0 from canary 5 to canary 6

    我升级android-studio到了3.0 canary 6打包编译安装出现如下错误: 07-11 13:00:39.523 8913-8913/dcpl.com.myapplication E/A ...