`

Spring rest对etag支持

    博客分类:
  • web
 
阅读更多

原文地址:http://www.javaarch.net/jiagoushi/698.htm

 

Spring rest对etag支持

etag(entity tag)是http响应头中用来判断对应响应结果是否修改。可以使用hash算法来计算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

那么下次客户端访问的时候If-None-Match或者If-Match头来让服务端判断是否修改


	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"
	Content-Length: 0
	
如果我们再访问
	
	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
	
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>
	
测试etags

第一次判断etag不为空

	@Test
	public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() {
		// Given
		Resource existingResource = getApi().create(new Resource());
		String uriOfResource = baseUri + "/" + existingResource.getId();
	 
		// When
		Response findOneResponse = RestAssured.given().
		  header("Accept", "application/json").get(uriOfResource);
	 
		// Then
		assertNotNull(findOneResponse.getHeader(HttpHeaders.ETAG));
	}
	
第二次,我们从上一次取出etag之后把etag发送给服务端验证

	@Test
	public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() {
		// Given
		T 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);
	 
		// When
		Response secondFindOneResponse= RestAssured.given().
		  header("Accept", "application/json").headers("If-None-Match", etagValue)
		  .get(uriOfResource);
	 
		// Then
		assertTrue(secondFindOneResponse.getStatusCode() == 304);
	}

测试服务端响应结果变化了,则

	@Test
	public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() {
		// Given
		T 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));
	 
		// When
		Response secondFindOneResponse= RestAssured.given().
		  header("Accept", "application/json").headers("If-None-Match", etagValue)
		  .get(uriOfResource);
	 
		// Then
		assertTrue(secondFindOneResponse.getStatusCode() == 200);
	}
	
如果请求带上不正确的etag值并且加上if-match判断,则会返回412Precondition Failed

	@Test
	public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsReceived() {
		// Given
		T existingResource = getApi().create(createNewEntity());
	 
		// When
		String uriOfResource = baseUri + "/" + existingResource.getId();
		Response findOneResponse = RestAssured.given().header("Accept", "application/json").
		  headers("If-Match", randomAlphabetic(8)).get(uriOfResource);
	 
		// Then
		assertTrue(findOneResponse.getStatusCode() == 412);
	}
	
github示例地址:https://github.com/eugenp/REST



分享到:
评论

相关推荐

    Building+a+REST+API+with+Spring

    根据给定的文件标题、描述、标签以及部分内容,本文将详细介绍如何使用Spring框架构建REST API。文章涵盖了从项目初始化到REST API开发、安全配置、消息转换、错误处理等多个方面。 ### 1. Bootstrap a Web ...

    etag-lastmod-example:使用带有 Spring Data REST 的 ETags 进行乐观并发控制和条件 GET

    总结来说,通过Spring Data REST,Java开发者可以轻松地在应用程序中集成ETag和Last-Modified机制,实现高效的乐观并发控制和条件GET请求,提高系统性能,保证数据一致性。这种做法不仅适用于单体应用,也是微服务...

    spring-mvc-rest

    Spring MVC提供了`MockMvc`类,允许在没有实际服务器的情况下对REST服务进行单元测试。同时,可以使用`curl`命令行工具或Postman等图形化工具进行接口测试。 9. **安全性**: Spring Security模块可以帮助保护...

    spring-webservice:REST web项目

    Spring提供了多种库和模块来支持RESTful服务的开发,如Spring MVC和Spring Web Services。在这个项目中,我们将探讨如何利用Spring MVC创建RESTful API。 1. **Spring MVC与REST**:Spring MVC是Spring框架的一部分...

    spring-best-practices:Spring异步最佳实践(未维护)

    功能完善,经过测试的功能完备的Spring 3.2参考应用程序,具有JPA持久性,REST Level-3资源,异步处理,作业,安全性,单元,模拟,集成,功能,其余客户端存根,性能测试以及许多最佳实践,聚集了在MVC / Spring / ...

    Building a RESTful Web Service with Spring

    - **ETags**:通过ETag头来标识资源的版本,从而实现条件GET请求。 #### 七、安全性 安全是RESTful Web服务的重要组成部分,我们将讨论如何实现身份验证: - **HTTP Basic认证**:一种简单的认证机制,客户端将...

    java-rest-schema:Java REST 模式测试用例

    9. **分页和过滤**: REST服务常需支持分页和过滤功能,这可以通过添加查询参数如`page`、`size`和`sort`实现。 10. **API版本管理**: 良好的REST服务应支持API版本控制,可以使用URL路径(如`/v1/users`)或HTTP头...

    rest-showcase

    REST API 支持 JSON 和 XML 以及 GZIP 编码和 ETag 缓存。 项目与 Heroku 和 MongoLab 集成。 你可以访问它。 使用示例 以 JSON 格式获取所有书籍 curl -H 'Accept: application/json' -X GET -D - ...

    restservices

    8. 缓存控制:REST服务可以利用HTTP缓存机制提高性能,如设置Cache-Control和ETag头。 9. 版本管理:为避免破坏已有接口,REST服务通常需要版本控制。可以通过URL路径、查询参数或Accept头部来指定API版本。 10. ...

    beerstock_api:用于啤酒库存管理的REST API

    Java的Spring Boot框架常被用于构建REST API,因为它提供了丰富的功能,包括依赖注入、安全控制、自动配置等,大大简化了开发过程。 **Spring Boot与REST API** Spring Boot是Spring框架的一个扩展,旨在简化...

    RESTAPI

    - Spring框架也提供了Spring MVC和Spring WebFlux模块,支持创建REST API。使用`@RestController`、`@RequestMapping`等注解定义控制器和路由。 5. JSON Web Token(JWT)与安全性: - REST API通常采用JWT进行...

    REST5000API

    在Java中实现RESTful API,通常会使用如Spring Boot这样的框架,因为它提供了强大的支持来快速开发这些API。 在"REST5000API-main"这个文件夹中,我们可以推测它包含的是REST5000API项目的主代码和资源。下面将详细...

    reactJ:使用Java和Spring Webflux的响应式服务

    Spring Security提供了对Webflux的全面支持,包括JWT令牌验证、OAuth2等安全机制,可以在后端设置权限控制,前端则可以通过拦截器或库如axios-auth-refresh处理身份验证。 6. **部署与测试**: 应用部署时,可以将...

    Web on Servlet Stack

    - **Multipart Requests**:对于包含文件上传的请求,Spring提供了两种主要的支持方式:`CommonsFileUpload`和Servlet 3.0的原生支持。 **Filters** 除了核心的`DispatcherServlet`之外,还可以配置过滤器来处理...

    springMVC搭建Restful服务

    4. **缓存**:通过HTTP的Cache-Control和ETag头支持资源的缓存。 通过遵循这些原则,你可以构建出高效且易于扩展的RESTful服务。Spring MVC 4提供了强大的支持,使得开发RESTful服务变得简单易行。在实际项目中,还...

    cxf webservice restful实现

    在IT行业中,CXF是一个广泛使用的开源框架,用于构建和开发...在实际项目中,根据具体需求,我们还可以进一步优化和定制,例如引入更多高级特性,如CORS支持、HATEOAS、超媒体链接等,以实现更符合REST原则的服务设计。

    RestInDepthMeetup:深度休息聚会的来源

    具有 REST/HATEAOS Web 界面的订单应用程序 具有 REST 和 Atom 界面的产品应用程序 打开操作: - 幻灯片 HATEAOS 和 Atom - 示例 Appl 订单(带有 Spring 的 HATEAOS) -示例 Appl 产品(带有 Jersey 和 ROME 或 ...

    HateNotepad:公共访问 API,用于控制充斥互联网的巨魔和可恶的人。 开发用于说明如何使用 Spring Boot 构建 RESTful API

    5. **缓存**:支持HTTP缓存机制,如Cache-Control和ETag头。 在 HateNotepad API 中,可能包含以下核心组件和功能: 1. **用户管理**:注册、登录、验证用户身份,可能使用JWT(JSON Web Tokens)进行认证。 2. **...

    RestApi

    在实际开发中,开发者可能会使用各种框架和工具来简化REST API的实现,例如Node.js的Express,Python的Flask或Django,Java的Spring Boot等。这些框架提供了一套便捷的方式来定义路由、处理请求和响应,以及实现认证...

    Java面试题-Web相关.pdf

    在Java Web开发中,常见的框架如Spring MVC和Spring Boot提供了很好的支持来构建RESTful服务,简化了上述概念的实现。理解并熟练运用这些RESTful设计原则,对于提升Java Web应用程序的效率、可维护性和互操作性至关...

Global site tag (gtag.js) - Google Analytics