Spring rest对etag支持
原文地址: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