Spring ResponseEntity
简单记录下 ResponseEntity 的使用方式
@RequestMapping(value="/demo1" )
public ResponseEntity demo1(){
// 使用方式一.
// ResponseEntity responseEntity = new ResponseEntity(new User("lvbb",24),HttpStatus.OK); // 使用方式二.
return ResponseEntity.ok(new User("lvbb",24));
}
效果: 在引入jackson的jar包,以及开启<mvc:annotation-driven/>之后,访问请求可以看到 界面上显示出 User 的json格式。
说明. ResponseEntity可以理解为 @ResponseBody + @ResponseStatus 的组合.
ResponseEntity类介绍:
ResponseEntity类继承自HttpEntity,有三个关键属性 httpStatus 、body、httpHeader,分别代表响应状态码、响应体、响应头信息;
原理简单记录:
Spring对于@RequestMapping方法返回值有个接口,专门用来处理返回值类型HandlerMethodReturnValueHandler,接口两个声明方法:supportsReturnType判断是否支持对当前返回值类型,如果是支持解析该种返回值,就调用接口第二个方法handleReturnValue,解析@RequestMapping返回值。
Spring4.3.0 <mvc:annotation-driven/>一共会为我们注册15个HandlerMethodReturnValueHandler的实现类. 其中 RequestResponseBodyMethodProcessor用来处理@ResponseBody,而HttpEntityMethodProcessor是用来处理 ReponseEntity类型的返回值. 这里也可以发现一点:HttpEntityMethodProcessor在arrayList中的位置要比RequestResponseBodyMethodProcessor靠前,所以 使用了 ResponseEntity 就没有@ResponseBody出场的机会了.

从HandlerMethodReturnValueHandler接口的第一个方法分析使用满足条件:
代码片段位于:org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor#supportsReturnType
只要@RequestMapping的方法返回值为 HttpEntity的实现类 且不是 RequestEntity类或其子类 就会使用HttpEntityMethodProcessor来处理 请求返回值,简单来说ResponseEntity类就行.

从HandlerMethodReturnValueHandler接口的第二个方法分析使用如何将ResponseEntity返回给浏览器?
代码片段位于:org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor#handleReturnValue
对比@ResponseEntity解析器RequestResponseBodyMethodProcessor,很多地方相似,这两个解析器都继承自AbstractMessageConverterMethodProcessor。
记录下与@ResponseBody不同的地方:1. 可以设置HttpHeaders响应头消息,并通过Response写回;通过这种方式 ResponseEntity可以实现下载文件
2. 可以设置HttpStatus,设置响应状态码.
代码具体地方都和ResponseEntity一样,可以看下我这篇解析:
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { mavContainer.setRequestHandled(true);
if (returnValue == null) {
return;
} ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); Assert.isInstanceOf(HttpEntity.class, returnValue);
HttpEntity<?> responseEntity = (HttpEntity<?>) returnValue; HttpHeaders outputHeaders = outputMessage.getHeaders();
HttpHeaders entityHeaders = responseEntity.getHeaders();
if (outputHeaders.containsKey(HttpHeaders.VARY) && entityHeaders.containsKey(HttpHeaders.VARY)) {
List<String> values = getVaryRequestHeadersToAdd(outputHeaders, entityHeaders);
if (!values.isEmpty()) {
outputHeaders.setVary(values);
}
}
if (!entityHeaders.isEmpty()) {
for (Map.Entry<String, List<String>> entry : entityHeaders.entrySet()) {
if (!outputHeaders.containsKey(entry.getKey())) {
outputHeaders.put(entry.getKey(), entry.getValue());
}
}
} if (responseEntity instanceof ResponseEntity) {
outputMessage.getServletResponse().setStatus(((ResponseEntity<?>) responseEntity).getStatusCodeValue());
HttpMethod method = inputMessage.getMethod();
boolean isGetOrHead = (HttpMethod.GET == method || HttpMethod.HEAD == method);
if (isGetOrHead && isResourceNotModified(inputMessage, outputMessage)) {
outputMessage.setStatusCode(HttpStatus.NOT_MODIFIED);
// Ensure headers are flushed, no body should be written.
outputMessage.flush();
// Skip call to converters, as they may update the body.
return;
}
} // Try even with null body. ResponseBodyAdvice could get involved.
writeWithMessageConverters(responseEntity.getBody(), returnType, inputMessage, outputMessage); // Ensure headers are flushed even if no body was written.
outputMessage.flush();
}
简单记录下:ResponseEntity小文件下载的方式
@RequestMapping(value="/demo2")
public ResponseEntity demo2() throws IOException {
ClassPathResource resource = new ClassPathResource("download/note.txt");
InputStream in = resource.getInputStream();
byte[] bytes = new byte[in.available()];
in.read(bytes);
HttpHeaders headers=new HttpHeaders();
headers.add("Content-Disposition","attachment;filename="+resource.getFilename());
HttpStatus statusCode=HttpStatus.OK;
return new ResponseEntity(bytes,headers,statusCode);
}
效果等同于:利用@ResponseEntity返回byte数组
//通过 ResponseBody返回文件 二进制文件
@RequestMapping(value="/demo11")
@ResponseBody
public byte[] demo11(HttpServletResponse response) throws IOException {
ClassPathResource resource = new ClassPathResource("download/note.txt");
InputStream in = resource.getInputStream();
byte[] bytes = new byte[in.available()];
in.read(bytes);
response.addHeader("Content-Disposition","attachment;filename="+resource.getFilename());
return bytes;
}
最原始的方式:
@RequestMapping(value="/demo3")
public void demo3(HttpServletResponse response) throws IOException {
ClassPathResource resource = new ClassPathResource("download/note.txt");
InputStream in = resource.getInputStream();
response.addHeader("Content-Disposition","attachment;filename="+resource.getFilename());
FileCopyUtils.copy(in,response.getOutputStream());
}
Spring ResponseEntity的更多相关文章
- [转发]SPRING MVC3.2案例讲解--SPRING MVC3的@ResponseBody和ResponseEntity
在传统的开发过程中,我们的控制CONTROLL层通常需要转向一个JSP视图:但随着WEB2.0相关技术的崛起,我们很多时候只需要返回数据即可,而不是一个JSP页面. SPRING MVC3的@Resp ...
- spring中的ResponseEntity理解
参考: https://blog.csdn.net/weixin_37869477/article/details/82762976 https://blog.csdn.net/sswqzx/arti ...
- 【Spring】源码浅析 - ResponseEntity.ok 转载
https://www.jianshu.com/p/1238bfb29ee1 ResponseEntity.ok具体源码
- Spring MVC中的ResponseEntity和ResponseBody的区别
1.ResponseEntity的优先级高于@ResponseBody. 在不是ResponseEntity的情况下才去检查有没有@ResponseBody注解. 如果响应类型是ResponseEnt ...
- 用Spring中的ResponseEntity文件批量压缩下载
我看了很多网上的demo,先生成ZIP压缩文件,然后再下载. 我这里是生成ZIP文件流 进行下载.(核心代码没多少,就是一些业务代码) @RequestMapping(value = "/& ...
- 基于spring注解AOP的异常处理
一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...
- Spring 4 使用Freemarker模板发送邮件&添加附件
前言 Spring对Java的邮件发送提供了很好的支持,提供了超级简单的API,大大简化了Java邮件发送功能的开发. Spring对Email的支持是基于JavaMail API开发的,所以,我们在 ...
- Spring 4 创建REST API
什么是REST 全称:表述性状态转移 (Representational State Transfer), 将资源的状态以最适合客户端或服务端的形式从服务器端转移到客户端(或者反过来). 面向资源,而 ...
- [Java] Spring MVC 知识点
云图: @Service 用于标注业务层组件. 在 Spring-servlet 配置xml中,component-scan 标签默认情况下自动扫描指定路径下的包(含所有子包),将带有@Compone ...
随机推荐
- 中大 9095. Islands
9095. Islands 限制条件 时间限制: 2 秒, 内存限制: 256 兆 题目描述 Whenever it rains, Farmer John's field always ends up ...
- Python自动化开发 - Django【进阶篇】
Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...
- [javascript-code-snippet]javascript代码段
<ul> <li>Picture 1</li> <li>Picture 2</li> <li>Picture 3</li& ...
- 关于TF卡的工作原理
首先关于TF卡的定义 其次是TF卡的卡槽 有4个数据传输端,D0,D1,D2,D3.有一个CMD脚,是用来读取卡内信息的,在刚插入TF时,主机会读取卡的内存大小,格式之类的. Sd脚是插入检测脚,当卡 ...
- [Leedcode 169]Majority Element
1 题目描述 Given an array of size n, find the majority element. The majority element is the element that ...
- IE兼容性小结(IE7及以上版本)
缘由 在急速的互联网时代,原本ie系列的低版本浏览器就该淘汰了.可偏偏还是有很多xp系统ie7.8浏览器,这有让网站甚是苦逼.练就了一套新技术,原本以为能大展身手,可却在ie阵容中认怂了,不得不规规矩 ...
- winform最小化后重复进load事件原因
最近编写一个工具发现的问题,窗体不论是最小化还是进入托盘,重新打开的时候都会进入控件load事件. 产生这个现象的条件是: 1.使用了用户控件,在控件中使用了load事件 2.在主窗体中,隐藏或显示任 ...
- zookeeper的安装与配置(单机和集群)
单机模式: 1.首先去官网下载zookeeper的包 zookeeper-3.4.10.tar.gz 2.用FTP上传到服务器或者Linux虚拟机的/usr/local目录下 3.解压文件tar -z ...
- Swift5 语言指南(二十八) 高级运算符
除了Basic Operators中描述的运算符之外,Swift还提供了几个执行更复杂值操作的高级运算符.这些包括C和Objective-C中您熟悉的所有按位和位移运算符. 与C中的算术运算符不同,S ...
- 组件基础(参数校验和动态组件、v-once)—Vue学习笔记
最最最后一点关于组件传值的问题. 提醒:本篇内容请使用Vue.js开发版!(附带完成的警告和提示) 1.组件的参数校验 父组件向子组件传值,子组件可以决定传值的一些限制. 比如,子组件指向接收Stri ...