springboot自定义http反馈状态码
最近在开发一些http server类型程序,通过spring boot构建一些web程序,这些web程序之间通过http进行数据访问、共享,如下图:
假设现在client发起一次保存数据的请求到server,server可能会返回如下类似的数据:
{
"status":1,
"message":"xxxxxx"
}
然后client通过解析json获得status来判断当前的请求操作是否成功,开发过程中通过都是这么做的,但是这样在restful设计中不怎么好,其实这个status字段的表达完全可以通过http status来表示,类似404、500、502这种都有明确的定义并且相互理解、沟通起来也方便。
文章主要记录一下我是如何在spring boot中实现自定反馈状态码的,以及我找到的三种实现方式。
第一种,使用@ResponseStatus
这是一个注解,可以作用在方法和类上面,如下使用:
在方法上使用方式:
@RequestMapping(value = "/user", method = RequestMethod.GET)
@ResponseStatus(code=HttpStatus.INTERNAL_SERVER_ERROR,reason="server error")
public String getUser(){
return "im zhangsan";
}
启动web程序,通过postman访问http://127.0.0.1:8100/user,会出现下面结果:
{
"timestamp": 1497850427325,
"status": 500,
"error": "Internal Server Error",
"message": "server error",
"path": "/user"
}
这里我一开始觉得很奇怪,为什么我的getUser方法中没有错误,结果还是出现了500错误?原因就是@ResponseStatus注解的问题,我后面猜测它会强制的将映射转化成500的状态码。这种应用场景我想不太明白在什么地方会用到。
在类中使用方式:
@ResponseStatus(code=HttpStatus.INTERNAL_SERVER_ERROR,reason="111")
public class ServerException extends Exception { }
这种使用方式就是将自定义异常和状态码结合在一起,合理使用自定义异常机制可以最大化的提高程序的健壮性,下面看如何使用:
@RequestMapping(value = "/user", method = RequestMethod.GET)
public String getUser(@RequestParam String userName) throws ServerException{
if(StringUtils.isEmpty(userName)){
throw new ServerException();
}
return "im zhangsan";
}
这段代码的意思是当userName字段为null的时候会抛出ServerException异常,但是ServerException类被标记了@ResponseStatus注解,因此会直接报500错误,如果觉得500不适合还可以定义其它的错误代码。
这种方式看着已经很好了,可以按照逻辑自定义反馈码,程序够健壮。这种方式也有不好地方,如果反馈码太多需要定义太多的异常类,并且错误内容reason还是不能手动定义。
到这里,我基本上放弃了@ResponseStatus的使用了。
第二种,使用HttpServletResponse
HttpServletResponse是javax.servlet下的一个接口,如下使用:
@RequestMapping(value = "/user", method = RequestMethod.GET)
public void getUser(HttpServletResponse response) throws IOException{
response.setStatus(500);
response.getWriter().append("server error");
}
这种方式可以很好的实现同时满足自定义反馈码+消息内容,一般的实现方式也都是这样。但是这样也不是太好,
- 在括号内创建了一个response内置变量,这样显得不够美观,反而有些多余。
- 在方法中调用了源生的方法来设置反馈码和消息体,并且如果需要返回json格式数据还需要设置response.setContentType("application/json");和response.setCharacterEncoding("UTF-8");,这样做有些多余,重复的工作太多,虽然可以进行封装。
- 最严重的问题这个方法必须是void类型,否则就会和@ResponseBody出现冲突,其次就是不能利用@ResponseBody自动封装json的特性,在spring mvc框架中如果在方法上加上@ResponseBody是可以对返回值自动进行json封装的。
再找找其他的,如果没有找到,估计也只能接受这个不完美的东西了。
后来在翻阅spring boot文档的时候找到了ResponseEntity这么一个东西,这就是我要说的第三种方式。
第三种,使用ResponseEntity
不多说,直接上代码:
@RequestMapping(value = "/user", method = RequestMethod.GET)
public ResponseEntity<Map<String,Object>> getUser() throws IOException{
Map<String,Object> map = new HashMap<String,Object>();
map.put("name", "zhangsan");
return new ResponseEntity<Map<String,Object>>(map,HttpStatus.OK);
}
通过postman查看返回结果,如下:
{
"name": "zhangsan"
}
可以直接将map对象帮我转化成json对象,并且可以获得自定义状态码,很好,很强大。
这种方式很和我意,
- 不需要多于的HttpServletResponse,看着很干净。
- 可以充分利用@ResponseBody注解,直接将我的返回值帮我转化成json对象。
- 在设置返回值的时候同时还可以设置http反馈码,HttpStatus是springframework提供的一个枚举类,里面封装了所有的http反馈码,方便使用命名统一,不会有任何歧义。
相比于前面两种,这种方式很对我胃口。
仔细看了ResponseEntity的说明,发现spring mvc其它很多地方也都有使用,如下,下面内容摘自org.springframework.http.ResponseEntity文件注释,
In RestTemplate, this class is returned by getForEntity() and exchange():
ResponseEntity<String> entity = template.getForEntity("http://example.com", String.class);
String body = entity.getBody();
MediaType contentType = entity.getHeaders().getContentType();
HttpStatus statusCode = entity.getStatusCode();
Can also be used in Spring MVC, as the return value from a @Controller method:
@RequestMapping("/handle")
public ResponseEntity<String> handle() {
URI location = ...;
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setLocation(location);
responseHeaders.set("MyResponseHeader", "MyValue");
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED);
}
这就是上面说过的。
Or, by using a builder accessible via static methods:
@RequestMapping("/handle")
public ResponseEntity<String> handle() {
URI location = ...;
return ResponseEntity.created(location).header("MyResponseHeader", "MyValue").body("Hello World");
}
自定义http反馈码在设计优良的restful api中起到关键作用,http反馈码是业内统一、共识的,建议在尽量不要通过解析json来获得status判断操作结果。
springboot自定义http反馈状态码的更多相关文章
- Spring MVC自定义403,404,500状态码返回页面
代码 HTTP状态码干货:http://tool.oschina.net/commons?type=5 import org.springframework.boot.web.servlet.erro ...
- ASP.NET自定义错误页并返回正确的500、404状态码
在项目中,我们常常需要自定义错误页面,但往往返回的状态码都变成了200,对SEO很不友好.我尝试过在百度上寻找解决方案,但找到的资料中说的方法都试过了,发现都是无法返回正确的状态码的. 最后,只好自已 ...
- Python自定义状态码枚举类
在Java里很容易做到自定义有状态码和状态说明的枚举类例如: public enum MyStatus { NOT_FOUND(404, "Required resource is not ...
- 云监控自定义HTTP状态码说明
您在使用站点监控时,返回的6XX状态码均为云监控自定义HTTP状态码,具体含义如下表所示: 状态码 含义 备注 610 HTTP连接超时 监测点探测您的网站时出现连接超 ...
- Springboot 构建http服务,返回的http行是'HTTP/1.1 200' 无状态码描述 客户端解析错误
————————————————————————————————————————— *** 响应的数据格式 HTTP/1.1 200 OK Server: Apache-Coyote/1.1 A ...
- 紫色飞猪的研发之旅--06go自定义状态码
在实际开发中,需要前后端需要协商状态码,状态码用于后端返前端时使用.在一个团队中,定义的状态码讲道理应该是一致的,项目开始的起始阶段状态码应该是定义了个七七八八的,随着功能的叠加而不断增加.此系列将围 ...
- Nginx自定义404页面并返回404状态码
Nginx定义404页面并返回404状态码, WebServer是nginx,直接告诉我应该他们配置了nginx的404错误页面,虽然请求不存在的资源可以成功返回404页面,但返回状态码确是200. ...
- HTTP状态码总结
HTTP状态码(HTTP Status Code)是用以表示网页服务器HTTP响应状态的3位数字代码.有些 App 端接口与 HTML 接口用的是同一个,所以做移动端开发也有必要了解一下HTTP状态码 ...
- Http状态码之:301、302重定向
概念 301 Moved Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一.如果可能,拥有链接编辑功能的客户端应当自动把请求的地 ...
随机推荐
- PHP 迭代器和生成器
迭代和迭代器 迭代是指反复执行一个过程,每执行一次叫做迭代一次.比如普通的遍历便是迭代: $arr = [1, 2, 3, 4, 5];foreach($arr as $key => $valu ...
- 【Algorithm | 链表】单链表“环”、“环的起点”、“环的长度”问题
参考资料 • Floyd判圈算法 { 链接 } • 单链表“环”.“环的起点”.环的长度”问题 { 链接 } 链表环的问题 一.判断链表有换 使用两个指针slow和fast.两个指针开始时均在头节点处 ...
- C#的委托(delegate、Action、Func、predicate)
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 1.委托的声明 delegate我们常用到的一种声明 delegate至少0个参数,至多32个参 ...
- PostgreSQL主要优势
PostgreSQL主要优势: 1. PostgreSQL完全免费,而且是BSD协议,如果你把PostgreSQL改一改,然后再拿去卖钱,也没有人管你,这一点很重要,这表明了PostgreSQL数据 ...
- js手机端和pc端加载不同的样式
function loadCSS() { if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android| ...
- PHP 数组中取出随机取出指定数量子值集
#关键:array_rand() 函数返回数组中的随机键名,或者如果您规定函数返回不只一个键名,则返回包含随机键名的数组.#思路:先使用array_rand()随机取出所需数量键名,然后将这些键名指向 ...
- fbs创建windows下安装qtpy应用程序!
cd 到python3.6目录下Python -m venv venv 创建虚拟环境call venv\scripts\activate.bat 激活虚拟环境将pip升级到最新版19.2pip ins ...
- hdu 2036 求多边形面积 (凸、凹多边形)
<题目链接> Problem Description “ 改革春风吹满地,不会AC没关系;实在不行回老家,还有一亩三分地.谢谢!(乐队奏乐)” 话说部分学生心态极好,每天就知道游戏,这次考 ...
- hdu1698 Just a Hook 【区间修改】(模板题)
题目链接:https://vjudge.net/contest/182746#problem/E 题目大意: 一段线段由n条小线段组成,每次操作把一个区间的小线段变成金银铜之一(金的价值为3,银为2, ...
- window版chrome 57.0.2970.0 (64-bit)滚动条的BUG
有一个元素div,它有一个子元素ul,给div添加一个:hover样式{color: red},挡鼠标hover div时,字体变红. 当鼠标hover div时,ul字体变红,鼠标hover ul的 ...