我自创的 Response泛型 返回类,全自动 推断,非常方便使用。
package com.diandaxia.common.utils; import java.util.Date; /**
* by liyuxin 2019.12.16 更新
* 统一返回格式
*/
public class ApiResponse<T> { /**
* 此次HTTP请求任务的最终结果状态,即HTTP协议层面成功了,然后对应的业务层面的操作也成功了,完全成功。
* 举例:若HTTP请求层面没有任何异常抛出,业务层面也完全成功了,则flag=true;
* 业务层面的完全成功的意思为:用户名和密码完全正确,后续所有的操作完全正确没有问题。
* 若用户名或密码错误那么就是业务层面的错误,若业务层面的错误则flag=false,
* 重要:这是一个所有环节均全部成功的标记,方便前端使用。前端可以判断此标记,来判断请求的所有环节是否完全成功。
*/
private Boolean flag; /**
* 错误代码--标识。
* 这个code的作用,仅仅是来标识出错的时候的错误代码。没有任何含义,并非网上说的HTTP协议状态码。
* 服务端已经做了全局异常处理,服务端返回的协议状态码永远是200;不要再加status字段,毫无意义。
* 这个仅仅是一个标识,没有任何意思。
* 0:标识成功
* 1:标识一般的业务错误
* 2:标识一般的异常错误
* 3.标识token过期,当然为了方便前端使用,boolean类型的tkexp也标识token是否过期
* 4.带hurl帮助信息的错误
* 5.外部的API调用返回错误标识,External Error,举例:调用淘宝的API返回了错误
* 一般0,1,2,3,4,5就完全足够了;宗旨不是给用户友好的提示错误,宗旨是不给用户任何提示错误,直接默认全部帮他处理好。所以错误不细分。而是疯狂减少错误的几率。
* 若依然有一些,其它的错误需真的需要特殊标识,方便前端使用的需要向我报备,我会加在一个枚举bean里;
*/
private Integer code; /**
* 错误详细信息标识;
* 成功时为null;失败才需要理由。
*/
private String msg; /**
* 若成功往往有data数据
* 示例:
* UserBase userBase = new UserBase();
* userBase.setUserName("李昱鑫");
* userBase.setUserPwd("123");
* userBase.setUserAge(100);
* return ResponseUtil.okWithData(userBase); 对应结果1:
* return ResponseUtil.okWithData(objectMapper.writeValueAsString(userBase)); 对应结果2:
*
* 结果1:{"flag":true,"code":0,"msg":"ok","data":{"userName":"李昱鑫","userPwd":"123","userAge":100},"tkexp":false,"hurl":null,"time":"2019-12-31 08:19:25"}
* 结果2:{"flag":true,"code":0,"msg":"ok","data":"{\"userName\":\"李昱鑫\",\"userPwd\":\"123\",\"userAge\":100}","tkexp":false,"hurl":null,"time":"2019-12-31 08:21:40"}
* 这个为Object不再为String,若为String的话,当数据量非常多的时候,会产生很多转义字符\,浪费网络流量,所以这里修改为object类型,其余的工作交给前端。
* 使用方法要求如下:
* 1.当是用到第三方的接口时的返回时,比如淘宝的API接口,返回值必须与文档上一致。那么需要传入字符串,淘宝的举例:return ResponseUtil.okWithData(rsp.getBody());
* 虽然这样会产生很多的转义字符,但是没有办法,必须与文档的返回一致,这时data要传入String类型。
* 2.当是我们自己调用我们自己的接口时,就没有必须传入String了,直接传入Object就可以了。举例:查询数据库中的记录,直接返回mybatis的mapper查询的结果list对象就可以,举例:
* Mapper.java里 -- List<JdpTbTrade> selectListByTids(String tids); Controller里 -- return ResponseUtil.okWithData(jdpTbTradeMapper.selectListByTids(tids));
* 这样就减少了转义字符,前端调试看着也方便。
*/
private T data; /**
* token过期的标记,这个比较常用,因为各个子项目都依赖token,当token过期的时候需要自动重新登录,获取新的token
* 故把这个token过期单独出来标志,此标志仅仅表示token是否过期;秘钥错误等问题,并不标识
* tkexp为token_expire缩写。true 标识过期了 false标识正常,没有过期.
*/
private Boolean tkexp; /**
* 当遇到错误的时候,有一些特殊错误必须要给出一套解决方案 来指导用户按流程操作,可以利用这个help_url,客户端要
* 提示用户打开这个链接进行查看相关教程,这个必须是一个url链接.
*/
private String hurl; /**
* 外部的业务错误标识,External Error 缩写:exterr 举例:调用淘宝的API,分2种错误:
* 1.若是我们自己的业务异常,则报错,举例token的验证,以及从Redis里取accessToken 都有可能异常,
* 这种错误是我们自己的业务错误,
*
* 2.若我们自己的业务无错误,调用淘宝的接口,由于其他原因淘宝会给返回错误,这类错误是外部错误,需要特殊标识一下
* 方便客户端知道是外部的业务错误还是内部的业务错误。
* -----------------------------------------------------
* 以下是客户端需要做的:
* 1.根据flag就知道是遇到错误了,还是完全正确了。
*
* 2.若是遇到错误了,再通过额外标识这个字段,来判断是平台的接口返回的错误,还是我们自己的内部业务错误。
*
* a.若是平台返回的错误【msg 里会是一个平台返回的完整 json字符串】,那么需要客户端解析msg里的字符串,然后做提示或其它默认处理操作。
*
* b.若是我们自己的业务错误【msg 里会是一个普通的字符串 非json】,比如token过期,那么就不需要解析msg里的字符串,直接提示这个字符串就行。
* ----------------------------------------------------
* 第一种情况,我们自己的业务错误,内部错误。
*
* {
* "flag": false,
* "code": 3,
* "msg": "token expire please login again",
* "data": null,
* "tkexp": true,
* "hurl": null,
* "exterr": false,
* "time": "2020-01-12 16:41:24"
* }
*
*
* 第二中情况,淘宝的API 返回错误。
*
* {
* "flag": false,
* "code": 1,
* "msg": "{\"error_response\":{\"code\":27,\"msg\":\"Invalid session\",\"sub_code\":\"invalid-sessionkey\",\"sub_msg\":\"非法或过期的SessionKey参数,请使用有效的SessionKey参数\",\"request_id\":\"556il21uswlw\"}}",
* "data": null,
* "tkexp": false,
* "hurl": null,
* "exterr": true,
* "time": "2020-01-12 16:43:28"
* }
*/
private Boolean exterr; /**
* 响应处理时间,方便以后根据报文的时间来判断错误,spring boot 项目不要忘记配置jackson
* spring.jackson.time-zone=GMT+8
* spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
*/
private Date time; /**
*用于内部构造
*/
private ApiResponse(Boolean flag, Integer code, String msg, T data, Boolean tkexp, String hurl, Boolean exterr){
this.flag = flag;
this.code = code;
this.msg = msg;
this.data = data;
this.tkexp = tkexp;
this.hurl = hurl;
this.exterr = exterr;
this.time = new Date();
} /**
* Http请求全程无异常--->业务代码层面也成功,即完全响应成功,不带返回数据(这个也常用,msg加了一个success)
*/
public static <T> ApiResponse<T> ok(){
return new ApiResponse<T>(true, 0,"ok",null, false, null, false);
} /**
* Http请求全程无异常--->业务代码层面也成功,即完全响应成功,带返回数据(这个常用)
*/
public static <T> ApiResponse<T> okWithData(T data){
return new ApiResponse<T>(true, 0,"ok", data, false, null, false);
} /**
* Http请求全程无异常--->业务代码层面不成功(比如用户需要输入密码或缺少参数),即不能完全响应成功。算失败。
* 这个最常用,错误代码默认为1,一般性业务错误。
*/
public static <T> ApiResponse<T> error(String msg){
return new ApiResponse<T>(false, 1, msg,null, false, null, false);
} /**
* Http请求有异常抛出--->走不到业务代码层面,即不能完全响应成功。
* 这个方法不常用,主要放在 SpringBoot项目的 全局异常类里使用。
* 把异常的信息传递进来.错误代码为2:标识一般的异常错误
*/
public static <T> ApiResponse<T> errorException(String msg){
return new ApiResponse<T>(false, 2, msg,null, false, null, false);
} /**
* token过期,单独出来供全局异常处理那里使用,要求每一个子项目,必须有一个全局异常处理类,且这个全局异常处理类里必须包含
* 处理token过期的方法,错误代码为3.标识token过期,当然为了方便前端使用,boolean类型的tkexp也标识token是否过期
*/
public static <T> ApiResponse<T> errorTokenExpire(){
return new ApiResponse<T>(false, 3, "Authorization token is expired",null, true, null, false);
} /**
* 有一些特殊错误必须要给出一套解决方案 来指导用户按流程操作,可以利用这个help_url
* 提示用户打开这个链接进行查看相关教程,这个是必须返回一个教程对应的URL
* 错误代码默认为1,一般性业务错误。
*/
public static <T> ApiResponse<T> errorWithHelp(String msg, String hurl){
return new ApiResponse<T>(false, 4, msg,null, false, hurl, false);
} /**
* 调用各个电商平台的Api返回的错误,并非我们自身的业务错误,需要标识一下外部错误.
*/
public static <T> ApiResponse<T> errorExternalApi(String msg){
return new ApiResponse<T>(false, 5, msg,null, false, null, true);
} /**
* 【这个比较少用,只有特殊情况下,才会使用,而且要尽量少用,只有当需要前端根据code来做出【自动】反应时才会用到】
* Http请求全程无异常--->业务代码层面不成功,但需要特殊标识一下code,方便前端判断code自动做出处理。这个方法最不常用,特殊标识的
* 我的目标不是友好的提示错误,还是自动消掉错误,这个类里要尽可能少错误的定义.
* 特殊情况下,某一些错误,需要特殊标识,方便前端判断 然后自动做出处理
* 现实中实际场景发现,每一个接口返回的code的意义可能都不同,无法统一code;
* 举例:abc.diandaxia.com/aaa 接口若返回 code=100 可能代表的意思是 哎哎哎;
* abc.diandaxia.com/bbb 接口也返回 code=100 他代码的意思是 哈哈哈;
* 可见不同的接口会返回相同的code,代表不同的意思,具体意思由接口人自己规定了。
* 但是有几个code是共有code,不可私自定义,比如0-5;这几个code不可私自定义使用。
* @param code 不可以为0,1,2,3,4,5
*/
public static <T> ApiResponse<T> errorOtherMark(Integer code, String msg){
if(code.equals(0) || code.equals(1) || code.equals(2) || code.equals(3) || code.equals(4) || code.equals(5)){
return new ApiResponse<T>(false, code, "code limit error",null, false, null, false);
}
return new ApiResponse<T>(false, code, msg,null, false, null, false);
} /**
* 【这个尽量少用,只有在一些特殊的情况下才使用】
* 场景1:一个接口需要返回临时token,但即使返回临时token 整理登录流程也算失败,
* 所以最终会是:{flag:false,code:123,msg:需要短信二次认证,data:tempToken},
* 这样有中文提示,同时也带回了一个辅助数据,方便客户端做一些自动操作。
* 思维上,既然有okWithData 就也应该有 errorWithData,但是errorWithData
* 仅仅只能一些特殊的情况下,才允许使用,所以命名为:errorOtherMarkWithData
* 其它的说明与errorOtherMark一致。
* @param code 不可以为0,1,2,3,4,5
*/
public static <T> ApiResponse<T> errorOtherMarkWithData(Integer code, String msg, T data){
if(code.equals(0) || code.equals(1) || code.equals(2) || code.equals(3) || code.equals(4) || code.equals(5)){
return new ApiResponse<T>(false, code, "code limit error",null, false, null, false);
}
return new ApiResponse<T>(false, code, msg, data, false, null, false);
} //============================== 以下是setter和getter 方便实例使用 ================================== public Boolean getFlag() {
return flag;
} public void setFlag(Boolean flag) {
this.flag = flag;
} public Integer getCode() {
return code;
} public void setCode(Integer code) {
this.code = code;
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
} public T getData() {
return data;
} public void setData(T data) {
this.data = data;
} public Boolean getTkexp() {
return tkexp;
} public void setTkexp(Boolean tkexp) {
this.tkexp = tkexp;
} public String getHurl() {
return hurl;
} public void setHurl(String hurl) {
this.hurl = hurl;
} public Boolean getExterr() {
return exterr;
} public void setExterr(Boolean exterr) {
this.exterr = exterr;
} public Date getTime() {
return time;
} public void setTime(Date time) {
this.time = time;
}
}
开始测试自动推断能力:
{"flag":true,"code":0,"msg":"ok","data":null,"tkexp":false,"hurl":null,"exterr":false,"time":"2020-06-20 20:10:07"}
{
"flag": true,
"code": 0,
"msg": "ok",
"data": {
"userId": null,
"userName": "小李飞刀",
"userPwd": null,
"userStatus": null,
"userType": null,
"userVersion": null,
"registerTime": null,
"lastLoginTime": null,
"fuwuId": null
},
"tkexp": false,
"hurl": null,
"exterr": false,
"time": "2020-06-20 20:11:16"
}
{
"flag": true,
"code": 0,
"msg": "ok",
"data": [
{
"userId": null,
"userName": "小李飞刀",
"userPwd": null,
"userStatus": null,
"userType": null,
"userVersion": null,
"registerTime": null,
"lastLoginTime": null,
"fuwuId": null
}
],
"tkexp": false,
"hurl": null,
"exterr": false,
"time": "2020-06-20 20:12:58"
}
{
"flag": true,
"code": 0,
"msg": "ok",
"data": [
{
"userId": null,
"userName": "小李飞刀",
"userPwd": null,
"userStatus": null,
"userType": null,
"userVersion": null,
"registerTime": null,
"lastLoginTime": null,
"fuwuId": null
}
],
"tkexp": false,
"hurl": null,
"exterr": false,
"time": "2020-06-20 20:15:03"
}
统统都没有任何问题,全程不报任何泛型警告,完美无瑕。 非常的方便使用;可见 Java 泛型 牛逼啊。
我自创的 Response泛型 返回类,全自动 推断,非常方便使用。的更多相关文章
- Boost源码剖析之:泛型指针类any
C++是强类型语言,所有强类型语言对型别的要求都是苛刻的,型别一有不合编译器就会抱怨说不能将某某型别转换为某某型别,当然如果在型别之间提供了转换操作符或是标准所允许的一定程度的隐式转换(如经过非exp ...
- 仿boost::any的泛型指针类any的实现
在boost库中,any是一种特殊容器,只能容纳一个元素,但这个元素可以是任意的类型----int.double.string.标准容器或者任何自定义类型.程序可以用any保存任意的数据,也可以在任何 ...
- RestTemplate将响应数据转换为具有泛型的类对象
前言: 重要,RestTemplate在SpringBoot项目里即便通过HttpMessageConverters添加了Fastjson且优先级比jackson要高也不会在RestTemplate里 ...
- Day 8:方法上自定义泛型、类上、接口上、泛型的上下限
泛型 泛型是jdk1.5使用的新特性 泛型的好处: 1. 将运行时的异常提前至了编译时 2. 避免了无谓的强制类型转换 泛型在集合中的常见应用: ArrayList<Strin ...
- c#中判断类是否继承于泛型基类
在c#中,有时候我们会编写类似这样的代码: public class a<T> { //具体类的实现 } public class b : a<string>{} 如果b继承a ...
- 【Java Web】项目通用返回模块ServerResponse:枚举code状态码、泛型返回值、序列化注解限制数据
一.枚举类编写ResponseCode package com.boulderaitech.common; /** * 编写枚举类的步骤 * (1)编写所需的变量 * (2)编写枚举类构造方法 * ( ...
- 返回类型和return语句
return语句终止当前正在执行的函数并将控制权返回到调用该函数的地方.return语句有两种形式: return; return expression; 无返回值函数 没有返回值的return语句只 ...
- 函数----基础,参数传递,返回类型和return语句
一.函数基础1.形参和实参 实参是形参的初始值.第一个实参初始化第一个形参,第二个实参初始化第二个形参,以此类推.尽管实参与形参存在对应关系,但是并没有规定实参的求值顺序.编译器能以任意可行的顺序对实 ...
- 【c++ primer, 5e】返回类型和return语句
[无返回值函数] 1.在c++的void函数中,可以显式地使用return;语句来提前结束函数的调用. [有返回值函数] 1.值是如何被返回的:返回一个值的方式和初始化一个变量或者形参的方式完全一样. ...
- SpringBoot 通用返回类设计
在项目中通常需要为前端设计通过的返回类,返回的格式为: { "status": "success", "data": {...} } 定义通 ...
随机推荐
- 使用element-plus的el-scrollbar时滚动条没有显示出来但是页面可以滚动的解决办法
如果使用 Element UI 的 el-scrollbar 组件时,滚动条没有显示出来但页面可以滚动,可以尝试调用其 update 方法来更新滚动条. 在适当的时机(例如在数据加载完成后或组件更新后 ...
- 昆虫科学院 AtCoder Race Ranking 2023 Autumn
概况 为提高选手们的训练 / 比赛热情,我们(昆虫科学院)通过商讨,在 \(2023-5-25\) 仿照 AtCoder Race Ranking (WTF) 机制,设立了"昆虫科学院 At ...
- Spring boot 自定义ThreadPoolTaskExecutor 线程池并进行异步操作
本文为博主原创,转载请注明出处: 1. 使用 ThreadPoolTaskExecutor 封装自定义配置的线程池Bean ThreadPoolTaskExecutor 是Spring 中封装的一个 ...
- 基于java+springboot的旅游信息网站、旅游景区门票管理系统
该系统是基于java+springboot开发的旅游景区门票管理系统.是给师弟开发的大四实习作品.学习过程中,遇到问题可以咨询github作者. 演示地址 前台地址: http://travel.gi ...
- Angular系列教程之观察者模式和RxJS
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- python3查看文件是否存在,以及读、写与执行的属性
技术背景 在使用python对系统文件进行操作的项目中,经常需要用到对本地文件的存在和读写进行判断的操作.最常用的比如os.exists函数,可以很方便的判断给定的文件名是否存在于系统中.但是这里我们 ...
- SpringBoot03:首页国际化
页面国际化 有的时候,我们的网站会去涉及中英文甚至多语言的切换,这时候我们就需要学习国际化! 1.配置文件编写 首先在resources资源文件下新建一个i18n目录,存放国际化配置文件 新建一个lo ...
- Python注释是什么东东
注释 标注解释,目的是帮助读者理解的文本 也就是说,注释首先是文本,其二是说明,其三是思路,其四是例子注释有两种形式 1. # ... 单行注释 用于对某句语句或语句块进行解释 放在语句块的头行或一个 ...
- 百度网盘(百度云)SVIP超级会员共享账号每日更新(2024.01.05)
一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...
- [转帖]awk的printf格式化输出
https://www.cnblogs.com/chanix/p/12738097.html awk的printf格式化输出20121108 Chenxincat sort_result.txt223 ...