欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring boot自定义http反馈状态码详解

程序员文章站 2023-12-17 15:10:16
前言 最近在开发一些http server类型程序,通过spring boot构建一些web程序,这些web程序之间通过http进行数据访问、共享,如下图, 假设现...

前言

最近在开发一些http server类型程序,通过spring boot构建一些web程序,这些web程序之间通过http进行数据访问、共享,如下图,

Spring boot自定义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");
}

这种方式可以很好的实现同时满足自定义反馈码+消息内容,一般的实现方式也都是这样。但是这样也不是太好,

  1. 在括号内创建了一个response内置变量,这样显得不够美观,反而有些多余。
  2. 在方法中调用了源生的方法来设置反馈码和消息体,并且如果需要返回json格式数据还需要设置response.setcontenttype("application/json");response.setcharacterencoding("utf-8"); ,这样做有些多余,重复的工作太多,虽然可以进行封装。
  3. 最严重的问题这个方法必须是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对象,并且可以获得自定义状态码,很好,很强大。

这种方式很和我意,

  1. 不需要多于的httpservletresponse,看着很干净。
  2. 可以充分利用@responsebody注解,直接将我的返回值帮我转化成json对象。
  3. 在设置返回值的时候同时还可以设置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判断操作结果。

总结

以上就是这篇文章的全部内容了,希望本文的内容对给各位ios开发者们能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。

上一篇:

下一篇: