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

 更新时间:2017年06月21日 11:20:36   作者:小强哥  
这篇文章主要给大家介绍了Spring boot自定义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");
}

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

  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开发者们能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • 基于java构造方法Vector遍历元素源码分析

    基于java构造方法Vector遍历元素源码分析

    本篇文章是关于ava构造方法Vector源码分析系列文章,本文主要介绍了Vector遍历元素的源码分析,有需要的朋友可以借鉴参考下,希望可以有所帮助
    2021-09-09
  • Java设计模式之命令模式CommandPattern详解

    Java设计模式之命令模式CommandPattern详解

    这篇文章主要介绍了Java设计模式之命令模式CommandPattern详解,命令模式是把一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作,需要的朋友可以参考下
    2023-10-10
  • maven依赖包冲突SLF4J: Class path contains multiple SLF4J bindings处理方法

    maven依赖包冲突SLF4J: Class path contains multiple SLF4J bi

    这篇文章主要给大家介绍了关于maven依赖包冲突SLF4J: Class path contains multiple SLF4J bindings的处理方法,这个问题通常是因为项目中存在多个SLF4J的实现绑定(bindings)导致的冲突,需要的朋友可以参考下
    2024-02-02
  • java开发gui教程之jframe监听窗体大小变化事件和jframe创建窗体

    java开发gui教程之jframe监听窗体大小变化事件和jframe创建窗体

    这篇文章主要介绍了java开发gui教程中jframe监听窗体大小变化事件和jframe创建窗体的示例,需要的朋友可以参考下
    2014-03-03
  • Spring security登录过程逻辑详解

    Spring security登录过程逻辑详解

    这篇文章主要介绍了SSpringsecurity登录过程逻辑详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Spring学习笔记之RestTemplate使用小结

    Spring学习笔记之RestTemplate使用小结

    这篇文章主要给大家介绍了关于Spring学习笔记之RestTemplate使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • springboot开启mybatis二级缓存的步骤详解

    springboot开启mybatis二级缓存的步骤详解

    这篇文章给大家介绍了springboot开启mybatis二级缓存的详细步骤,文中通过代码示例给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-02-02
  • Spring Boot 如何整合连接池

    Spring Boot 如何整合连接池

    这篇文章主要介绍了Spring Boot 如何整合连接池,帮助大家更好的理解和学习spring boot框架,感兴趣的朋友可以了解下
    2020-11-11
  • 浅析javax.servlet.Servlet,ServletContext接口

    浅析javax.servlet.Servlet,ServletContext接口

    本篇文章是对javax.servlet.Servlet,ServletContext接口进行了纤细的分析介绍,需要的朋友参考下
    2013-07-07
  • Spring boot搭建邮件服务的完整步骤

    Spring boot搭建邮件服务的完整步骤

    这篇文章主要给大家介绍了关于Spring boot搭建邮件服务的完整步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09

最新评论