rest spring

1.概述

本文将重点介绍ETag – Spring支持,RESTful API的集成测试以及带有curl的使用场景。 这是关于使用Spring 3.1和Spring Security 3.1和基于Java的配置来建立安全的RESTful Web服务的系列文章的第9篇。

REST with Spring系列:

  • 第1部分 – 使用Spring 3.1和基于Java的配置引导Web应用程序
  • P艺术2 - 构建RESTful Web服务使用Spring 3.1和Java配置
  • P艺术3 - 保护RESTful Web服务使用Spring Security 3.1
  • 第4部分 – RESTful Web服务可发现性
  • 第5部分 – 使用Spring进行REST服务发现
  • 第6部分 – 使用Spring Security 3.1的RESTful服务的基本身份验证和摘要身份验证
  • 第7部分 – Spring的REST分页
  • 第8部分 – 使用Spring Security对RESTful服务进行身份验证

2. REST和ETag

从有关ETag支持的Spring官方文档中:

ETag (实体标签)是HTTP / 1.1兼容的Web服务器返回的HTTP响应标头,用于确定给定URL的内容更改。

ETag用于两件事–缓存和条件请求。 ETag值可以作为从Response主体的字节中计算出的哈希值 。 因为可能使用加密哈希函数,所以即使是正文的最小修改也将极大地改变输出,从而改变ETag的值。 这仅适用于强大的ETag-该协议也提供了较弱的Etag 。

使用If- *标头会将标准GET请求转换为条件GET 。 与ETag一起使用的两个If- *标头是“ If-None-Match ”和“ If-Match ” –各自具有自己的语义,如本文稍后所述。

3.使用

涉及ETag的简单的Client-Server通信可以分为以下步骤:

首先 ,客户端进行REST API调用–响应包括要存储以供进一步使用的ETag标头:

curl -H 'Accept: application/json' -i http://localhost:8080/rest-sec/api/resources/1
HTTP/1.1 200 OK
ETag: 'f88dd058fe004909615a64f01be66a7'
Content-Type: application/json;charset=UTF-8
Content-Length: 52

–客户端对RESTful API发出的下一个请求包括带有上一步中的ETag值的If-None-Match请求标头; 如果服务器上的资源未更改,则响应将不包含任何正文,并且状态代码为304 –未修改

curl -H 'Accept: application/json' -H 'If-None-Match: 'f88dd058fe004909615a64f01be66a7''-i http://localhost:8080/rest-sec/api/resources/1
HTTP/1.1 304 Not Modified
ETag: 'f88dd058fe004909615a64f01be66a7'

现在 ,在再次检索资源之前,我们将通过执行更新来对其进行更改:

curl --user admin@fake.com:adminpass -H 'Content-Type: application/json' -i-X PUT --data '{ 'id':1, 'name':'newRoleName2', 'description':'theNewDescription' }'
http://localhost:8080/rest-sec/api/resources/1
HTTP/1.1 200 OK
ETag: 'd41d8cd98f00b204e9800998ecf8427e'
<strong>Content-Length: 0</strong>

最后 ,我们发出了最后一个请求以再次获取特权; 请记住,自上次检索以来已对其进行了更新,因此以前的ETag值将不再起作用-响应将包含新数据和新ETag,这些ETag可以再次存储以备后用:

curl -H 'Accept: application/json' -H 'If-None-Match: 'f88dd058fe004909615a64f01be66a7'' -i
http://localhost:8080/rest-sec/api/resources/1
HTTP/1.1 200 OK
ETag: '03cb37ca667706c68c0aad4cb04c3a211'
Content-Type: application/json;charset=UTF-8
Content-Length: 56

一切就在这里– ETags狂野地节省了带宽。

4. Spring对ETag的支持

对Spring的支持–在Spring中使用ETag非常容易设置,并且对应用程序完全透明 。 通过在web.xml中添加一个简单的Filter来启用该支持:

<filter><filter-name>etagFilter</filter-name><filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>
<filter-mapping><filter-name>etagFilter</filter-name><url-pattern>/api/*</url-pattern>
</filter-mapping>

筛选器映射到与RESTful API本身相同的URI模式。 从Spring 3.0开始,过滤器本身就是ETag功能的标准实现。

该实现是一个浅层实现-根据响应计算ETag,这将节省带宽,不能 节省 服务器性能 。 因此,将受益于ETag支持的请求仍将作为标准请求处理,消耗通常会消耗的任何资源(数据库连接等),并且只有在将其响应返回给客户端之前,ETag支持才会启动在。

届时,ETag将从响应主体中计算出来,并在资源本身上设置; 同样,如果在请求中设置了If-None-Match标头,则也会对其进行处理。

ETag机制的更深层实现可能会带来更大的好处-例如为缓存中的某些请求提供服务,而根本不必执行计算-但这种实现绝非像浅层方法那样简单,也不可插入在这里描述。

5.测试ETag

让我们开始简单–我们需要验证检索单个Resource的简单请求的响应是否实际上将返回“ ETag”标头:

@Test
public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() {// GivenResource existingResource = getApi().create(new Resource());String uriOfResource = baseUri + '/' + existingResource.getId();// WhenResponse findOneResponse = RestAssured.given().header('Accept', 'application/json').get(uriOfResource);// ThenassertNotNull(findOneResponse.getHeader(HttpHeaders.ETAG));
}

接下来我们验证ETag行为的幸福路径 –如果从服务器检索资源的请求使用正确的ETag值,则不再返回资源。

@Test
public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() {// GivenT existingResource = getApi().create(createNewEntity());String uriOfResource = baseUri + '/' + existingResource.getId();Response findOneResponse = RestAssured.given().header('Accept', 'application/json').get(uriOfResource);String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG);// WhenResponse secondFindOneResponse= RestAssured.given().header('Accept', 'application/json').headers('If-None-Match', etagValue).get(uriOfResource);// ThenassertTrue(secondFindOneResponse.getStatusCode() == 304);
}

一步步:

  • 首先创建资源 ,然后再检索–存储ETag值以备将来使用
  • 发送新的检索请求,这次使用“ If-None-Match ”标题指定先前存储的ETag
  • 在第二个请求上,服务器仅返回304 Not Modified ,因为在两个检索操作之间资源本身确实没有被修改。

最后 ,我们验证在第一个和第二个检索请求之间更改资源的情况:

@Test
public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() {// GivenT existingResource = getApi().create(createNewEntity());String uriOfResource = baseUri + '/' + existingResource.getId();Response findOneResponse = RestAssured.given().header('Accept', 'application/json').get(uriOfResource);String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG);existingResource.setName(randomAlphabetic(6))getApi().update(existingResource.setName(randomString));// WhenResponse secondFindOneResponse= RestAssured.given().header('Accept', 'application/json').headers('If-None-Match', etagValue).get(uriOfResource);// ThenassertTrue(secondFindOneResponse.getStatusCode() == 200);
}

一步步:

  • 首先创建资源 ,然后再检索–存储ETag值以备将来使用
  • 然后更新相同的资源
  • 发送新的检索请求,这次使用“ If-None-Match ”标题指定先前存储的ETag
  • 在第二个请求上,服务器将返回200 OK以及完整的Resource,因为ETag值不再正确,因为与此同时资源已更新

接下来 ,我们测试“ If-Match ”的行为– ShallowEtagHeaderFilter没有为If-Match HTTP标头提供开箱即用的支持(在此JIRA问题上进行了跟踪),因此以下测试应失败:

@Test
public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsReceived() {// GivenT existingResource = getApi().create(createNewEntity());// WhenString uriOfResource = baseUri + '/' + existingResource.getId();Response findOneResponse = RestAssured.given().header('Accept', 'application/json').headers('If-Match', randomAlphabetic(8)).get(uriOfResource);// ThenassertTrue(findOneResponse.getStatusCode() == 412);
}

一步步:

  • 首先创建资源
  • 然后使用“ If-Match ”标头检索资源,指定错误的ETag值-这是有条件的GET请求
  • 服务器应返回412 Precondition Failed

6. ETag很大

我们仅将ETag用于读取操作 – 存在一个RFC,试图阐明实现方式应如何在写入操作中处理ETag –这不是标准的,但很有趣。

当然,ETag机制还有其他可能的用途,例如使用Spring 3.1的乐观锁机制以及处理相关的“丢失更新问题” 。

使用ETag时,还要注意一些已知的潜在陷阱和警告 。

7.结论

本文仅介绍了Spring和ETags所能提供的功能。 要全面实现启用了ETag的RESTful服务,以及用于验证ETag行为的集成测试,请查看github项目 。

参考:来自badung博客的JCG合作伙伴 Eugen Paraschiv的Spring的ETags 。

翻译自: https://www.javacodegeeks.com/2013/01/etags-for-rest-with-spring.html

rest spring

rest spring_带有Spring的REST的ETag相关推荐

  1. 带有Spring的REST的ETag

    1.概述 本文将重点介绍ETags-Spring支持,RESTful API的集成测试以及带有curl的使用场景. 这是关于使用Spring 3.1和Spring Security 3.1和基于Jav ...

  2. oauth2_带有Spring Security的OAuth 2.0快速指南

    oauth2 "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验 ...

  3. 带有Spring Cloud Config和JHipster的Java微服务

    朋友不允许朋友写用户身份验证. 厌倦了管理自己的用户? 立即尝试Okta的API和Java SDK. 在几分钟之内即可对任何应用程序中的用户进行身份验证,管理和保护. 如今,使用Java和Spring ...

  4. spring javafx_带有Spring的JavaFX 2

    spring javafx 我将从一个大胆的声明开始:我一直很喜欢Java Swing或applet. 在那里,我说了. 如果我进行一些自我分析,那么这种钦佩可能是在我接触Java时开始的. Swin ...

  5. 带有Spring的JavaFX 2

    我将从一个大胆的声明开始:我一直很喜欢Java Swing或applet. 在那里,我说了. 如果我进行一些自我分析,那么这种钦佩可能是在我入门Java时开始的. Swing(实际上)是我使用Java ...

  6. jsr303 spring_使用Spring和JSR 303进行方法参数验证

    jsr303 spring Spring提供了一种使用JSR 303 bean验证来验证方法参数的简便方法. 在这篇文章中,我们将看到如何使用此功能. 建立 首先,我们需要通过创建MethodVali ...

  7. apache.camel_带有Spring Boot 2支持的Apache Camel 2.22发布

    apache.camel 今天,我们发布了最新的Apache Camel 2.22.0版本 ,这是第一个正式完全支持Spring Boot 2的版本.这是一项重大的工作,因为针对像Apache Cam ...

  8. 带有Spring Boot和Spring Cloud的Java微服务

    朋友不允许朋友写用户身份验证. 厌倦了管理自己的用户? 立即尝试Okta的API和Java SDK. 在几分钟之内即可对任何应用程序中的用户进行身份验证,管理和保护. Java是开发微服务架构时使用的 ...

  9. 带有Spring Security的OAuth 2.0快速指南

    "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证. 在构建W ...

最新文章

  1. 【论文精读】Temporally Refined Graph U-Nets for Human Shape and Pose Estimation From Monocular Videos
  2. SSKeychain
  3. Some Notes About Design Pattern
  4. 【2018ACM山东省赛 - G】Games(Nim博弈 + dp)
  5. pg数据库开启远程连接_疫情之下,开启在家办公模式,远程连接工具篇之向日葵...
  6. 信息学奥赛一本通 1216:红与黑 / OpenJudge NOI 2.5 1818
  7. c基础学汇编语言,王爽《汇编语言》学习笔记、习题(第一章 基础知识)
  8. 为推广5G 4G网络降速?三大运营商回应:不存在的!
  9. java sql 创建触发器_SQL Server创建触发器
  10. 手机app登录显示服务器异常,手机app 连接云服务器异常
  11. 桂林电子科技大学第三届ACM程序设计竞赛 C
  12. 系列教程|Apache Doris ODBC 外表使用指南(一)
  13. 帮你自动化办公的python - 自动提取pdf指定页(项目概述)
  14. 【NOIP2016提高A组五校联考1】排队
  15. js / java 文档对比
  16. cnpm 新版本替换,及randomUUID is not a function问题解决
  17. RFC2616中文版
  18. react-router 与react-reduct 配合使用时,页面不刷新问题
  19. 报错:SyntaxError: Unexpected token u in JSON at position 0 at JSON.parse (<anonymous>)
  20. CMD管理员运行切换目录

热门文章

  1. 推荐系统常用的推荐算法
  2. 干货!sqlserver数据库所有知识点总结整理,含代码(挺全的)
  3. 《金色梦乡》金句摘抄(十)
  4. hutool中身份证工具-IdcardUtil
  5. idea报错:Error:java: JDK isn‘t specified for module ‘xxx‘
  6. 基于Spring boot,使用idea方便地切换启动环境
  7. springboot创建项目2 开发环境的搭建
  8. java编译提示错误信息_JAVA编译错误提示缺少“{”
  9. map分组后取前10个_海关数据 | 图解前10个月外贸
  10. skimage直方图如何保存_LightGBM的参数详解以及如何调优