使用ResponseEntity处理API返回问题

 更新时间:2024年07月10日 16:24:40   作者:半城风花半城雨  
这篇文章主要介绍了使用ResponseEntity处理API返回问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

最近在做Google AMP mail的时候遇到了一个问题,在调用/unsub(退订)接口的时候需要向google client返回特定的ResponseHeader。

但是项目使用的是Springboot 2.x,通常使用@RestController修饰API层,无法做到动态的返回特殊的Header。那么如何对一些特殊的API做一些特别的返回值封装呢?

Spring framework中的ResponseEntity类很好的解决了此问题。

众所周知,我们的HTTP/HTTPS的响应由状态码、头部信息以及响应体内容三大块组成,响应体内容可以通过返回值进行一系列封装回传出结果,而状态码与头部信息需要特别设置。

ResponseEntity的使用

先上源码,看看ResponseEntity到底如何使用的。

1. ResponseEntity的第一种使用方式

public class ResponseEntity<T> extends HttpEntity<T> {
    public ResponseEntity(HttpStatus status) {
	    this((Object)null, (MultiValueMap)null, (HttpStatus)status);
	}
	
   public ResponseEntity(@Nullable T body, HttpStatus status) {
        this(body, (MultiValueMap)null, (HttpStatus)status);
    }
	
   public ResponseEntity(MultiValueMap<String, String> headers, HttpStatus status) {
        this((Object)null, headers, (HttpStatus)status);
    }
	
   public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) {
        super(body, headers);
        Assert.notNull(status, "HttpStatus must not be null");
        this.status = status;
    }

   private ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, Object status) {
        super(body, headers);
        Assert.notNull(status, "HttpStatus must not be null");
        this.status = status;
    }
}

可以看到这个类提供了五个构造方法,返回的状态码是必传的外,头部信息以及响应体内容都是可选择的。

当我们需要使用的时候,直接new一个ResponseEntity对象作为API返回值即可,这就是它的第一种使用方式。

需要注意的是,在有headers作为参数的构造方法中,需要传入一个类型为MultiValueMap<String, String>的参数。

MultiValueMap继承自Map这个抽象类,其中拥有一个叫做HttpHeaders的子类,我们可以当它为一个key和value都为String类型的HashMap使用。

HttpHeaders里面保存了一些常用的Header的key值,例如"Accept-Charset"。当然也可以自定义一些特殊的key。

HttpHeaders headers = new HttpHeaders();
headers.add("Access-Control-Expose-Headers", "AMP-Access-Control-Allow-Source-Origin");

return new ResponseEntity<>(resultBody, headers, HttpStatus.OK);

2. ResponseEntity的第二种使用方式

继续看源码,发现了好多返回值为ResponseEntity.BodyBuilder的方法有木有

    public static ResponseEntity.BodyBuilder status(HttpStatus status) {
        Assert.notNull(status, "HttpStatus must not be null");
        return new ResponseEntity.DefaultBuilder(status);
    }

    public static ResponseEntity.BodyBuilder status(int status) {
        return new ResponseEntity.DefaultBuilder(status);
    }
        public static ResponseEntity.BodyBuilder ok() {
        return status(HttpStatus.OK);
    }
    public static ResponseEntity.BodyBuilder created(URI location) {
        ResponseEntity.BodyBuilder builder = status(HttpStatus.CREATED);
        return (ResponseEntity.BodyBuilder)builder.location(location);
    }

    public static ResponseEntity.BodyBuilder accepted() {
        return status(HttpStatus.ACCEPTED);
    }

    public static ResponseEntity.HeadersBuilder<?> noContent() {
        return status(HttpStatus.NO_CONTENT);
    }

    public static ResponseEntity.BodyBuilder badRequest() {
        return status(HttpStatus.BAD_REQUEST);
    }

    public static ResponseEntity.HeadersBuilder<?> notFound() {
        return status(HttpStatus.NOT_FOUND);
    }

    public static ResponseEntity.BodyBuilder unprocessableEntity() {
        return status(HttpStatus.UNPROCESSABLE_ENTITY);
    }
    .........

事实证明,越是伟大的软件工程师是越“懒惰”的,为了节约时间增加效率,我们可以用Builder的方式去生成ResponseEntity对象并返回:

Map<String, String> resultBody = new HashMap<>();
resultBody.put("name":"Lucas");
resultBody.put("school":"harvard university");
 return ResponseEntity.status(HttpStatus.OK)
        .body(resultBody);

与其他方式对比

  • @RestController注解修饰controller层。

@RestController = @Controller + @ResponseBody

@ResponseBody是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。

注意:在使用此注解之后不会再走视图处理器(ModelAndView),而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

  • @ResponseStatus

这个注解主要用在自定义的Exception 上,或者直接用在controller层的API方法上也可,当发生异常/方法执行结束时,会返回相应的Http状态码和msg。

@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="不允许访问")

注:

  • ResponseEntity的优先级高于@ResponseBody。
  • 只有在返回值不为ResponseEntity的情况下才去检查有没有@ResponseBody注解;如果响应类型是ResponseEntity则会忽略@ResponseBody注解。

总结

ResponseEntity能够非常方便的修改返回值的状态码,但最优秀的用法仍然是能够为不同API设置不同的返回响应头。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 常用校验注解之@NotNull,@NotBlank,@NotEmpty的区别及说明

    常用校验注解之@NotNull,@NotBlank,@NotEmpty的区别及说明

    这篇文章主要介绍了常用校验注解之@NotNull,@NotBlank,@NotEmpty的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Springboot添加支付接口

    Springboot添加支付接口

    这篇文章主要介绍了springboot如何添加支付接口,帮助大家更好得理解和学习使用springboot框架,感兴趣的朋友可以了解下
    2021-04-04
  • JRebel2023.3 插件使用及安装步骤详解

    JRebel2023.3 插件使用及安装步骤详解

    JRebel是一款JVM插件,它使得Java代码修改后不用重启系统,立即生效,IDEA上原生是不支持热部署的,一般更新了 Java 文件后要手动重启 Tomcat 服务器,才能生效,浪费时间浪费生命,目前对于idea热部署最好的解决方案就是安装JRebel插件,本文分步骤介绍的非常详细,一起看看吧
    2023-08-08
  • Java日常练习题,每天进步一点点(6)

    Java日常练习题,每天进步一点点(6)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-07-07
  • mybatis中insert主键ID获取和多参数传递的示例代码

    mybatis中insert主键ID获取和多参数传递的示例代码

    这篇文章主要介绍了mybatis中insert主键ID获取和多参数传递的示例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java使用wait和notify实现线程之间的通信

    Java使用wait和notify实现线程之间的通信

    Java 线程通信是将多个独立的线程个体进行关联处理,使得线程与线程之间能进行相互通信,下面这篇文章主要给大家介绍了关于Java使用wait和notify实现线程之间通信的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • Java集合继承体系详解

    Java集合继承体系详解

    这篇文章主要为大家详细介绍了Java集合继承体系,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • mybatis如何使用Java8的日期LocalDate和LocalDateTime详解

    mybatis如何使用Java8的日期LocalDate和LocalDateTime详解

    这篇文章主要给大家介绍了关于mybatis如何使用Java8的日期LocalDate和LocalDateTime的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-09-09
  • Java实现邮件发送的过程及代码详解

    Java实现邮件发送的过程及代码详解

    这篇文章主要介绍了Java实现邮件发送的过程及代码详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • java随机数生产算法实例

    java随机数生产算法实例

    下面小编就为大家带来一篇java随机数生产算法实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10

最新评论