美食网站建设策划书,上传文件网站根目录,谷歌云wordpress,服务商名称是什么意思这是有关使用Spring 3.1和Spring Security 3.1和基于Java的配置来建立安全的RESTful Web Service的系列文章的第七篇。 本文将重点介绍RESTful Web服务中的分页实现 。 REST with Spring系列#xff1a; 第1部分– 使用Spring 3.1和基于Java的配置引导Web应用程序 第2部分–… 这是有关使用Spring 3.1和Spring Security 3.1和基于Java的配置来建立安全的RESTful Web Service的系列文章的第七篇。 本文将重点介绍RESTful Web服务中的分页实现 。 REST with Spring系列 第1部分– 使用Spring 3.1和基于Java的配置引导Web应用程序 第2部分– 使用Spring 3.1和基于Java的配置构建RESTful Web服务 第3部分– 使用Spring Security 3.1保护RESTful Web服务 第4部分– RESTful Web服务可发现性 第5部分– 使用Spring进行REST服务发现 第6部分– 使用Spring Security 3.1的RESTful服务的基本身份验证和摘要身份验证 页面作为资源vs页面作为表示 在RESTful架构的上下文中设计分页时的第一个问题是将页面视为实际资源还是仅表示资源 。 将页面本身视为资源会带来许多问题例如不再能够在调用之间唯一地标识资源。 这加上以下事实在RESTful上下文之外不能将页面视为适当的实体但是在需要时构造的所有者会使选择变得简单 页面是表示的一部分 。 在REST上下文中的分页设计中的下一个问题是在何处包括分页信息 在URI路径中 / foo / page / 1 URI查询 / foopage 1 请记住 页面不是资源 因此不再可以将页面信息编码为URI。 URI查询中的页面信息 在URI查询中对URI查询中的页面信息进行编码是解决此问题的标准方法。 但是这种方法确实有一个缺点 –它切入了用于实际查询的查询空间 / foopage 1size 10 控制器 现在对于实现– 用于分页的Spring MVC控制器非常简单 RequestMapping( value admin/foo,params { page, size },method GET )
ResponseBody
public List Foo findPaginated( RequestParam( page ) int page, RequestParam( size ) int size, UriComponentsBuilder uriBuilder, HttpServletResponse response ){Page Foo resultPage service.findPaginated( page, size );if( page resultPage.getTotalPages() ){throw new ResourceNotFoundException();}eventPublisher.publishEvent( new PaginatedResultsRetrievedEvent Foo ( Foo.class, uriBuilder, response, page, resultPage.getTotalPages(), size ) );return resultPage.getContent();
} 这两个查询参数在请求映射中定义并通过RequestParam注入到控制器方法中 HTTP响应和Spring UriComponentsBuilder注入到Controller方法中以包含在事件中因为实现可发现性将需要两者。 REST分页的可发现性 在分页的范围内满足REST的HATEOAS约束意味着使API的客户端能够基于导航中的当前页面发现下一页和上一页。 为此将使用Link HTTP标头以及官方的 “ next ”“ prev ”“ first ”和“ last ”链接关系类型。 在REST中可发现性是一个横切关注点 不仅适用于特定操作还适用于操作类型。 例如每次创建资源时客户端应可发现该资源的URI。 由于此要求与ANY资源的创建有关因此应分开处理并与主Controller流分离。 使用Spring这种分离是通过事件来实现的 如上一篇文章中已充分讨论的那样该文章侧重于RESTful服务的可发现性。 对于分页在控制器中触发了事件– PaginatedResultsRetrievedEvent –并且在此事件的侦听器中实现了可发现性 void addLinkHeaderOnPagedResourceRetrieval( UriComponentsBuilder uriBuilder, HttpServletResponse response, Class clazz, int page, int totalPages, int size ){String resourceName clazz.getSimpleName().toString().toLowerCase();uriBuilder.path( /admin/ resourceName );StringBuilder linkHeader new StringBuilder();if( hasNextPage( page, totalPages ) ){String uriNextPage constructNextPageUri( uriBuilder, page, size );linkHeader.append( createLinkHeader( uriForNextPage, REL_NEXT ) );}if( hasPreviousPage( page ) ){String uriPrevPage constructPrevPageUri( uriBuilder, page, size );appendCommaIfNecessary( linkHeader );linkHeader.append( createLinkHeader( uriForPrevPage, REL_PREV ) );}if( hasFirstPage( page ) ){String uriFirstPage constructFirstPageUri( uriBuilder, size );appendCommaIfNecessary( linkHeader );linkHeader.append( createLinkHeader( uriForFirstPage, REL_FIRST ) );}if( hasLastPage( page, totalPages ) ){String uriLastPage constructLastPageUri( uriBuilder, totalPages, size );appendCommaIfNecessary( linkHeader );linkHeader.append( createLinkHeader( uriForLastPage, REL_LAST ) );}response.addHeader( HttpConstants.LINK_HEADER, linkHeader.toString() );
} 简而言之侦听器逻辑检查导航是否允许下一页上一页第一页和最后一页如果允许则将相关的URI添加到链接HTTP标头中。 它还确保链接关系类型是正确的-“下一个”“上一个”“第一个”和“最后一个”。 这是侦听器的唯一职责 此处是完整代码 。 测试驾驶分页 分页和可发现性的主要逻辑都应由小型集中的集成测试广泛涵盖 与上一篇文章一样 使用保证库来使用REST服务并验证结果。 这些是分页集成测试的一些示例 要获得完整的测试套件请查看github项目本文结尾的链接 Test
public void whenResourcesAreRetrievedPaged_then200IsReceived(){Response response givenAuth().get( paths.getFooURL() ?page1size10 );assertThat( response.getStatusCode(), is( 200 ) );
}
Test
public void whenPageOfResourcesAreRetrievedOutOfBounds_then404IsReceived(){Response response givenAuth().get( paths.getFooURL() ?page randomNumeric( 5 ) size10 );assertThat( response.getStatusCode(), is( 404 ) );
}
Test
public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources(){restTemplate.createResource();Response response givenAuth().get( paths.getFooURL() ?page1size10 );assertFalse( response.body().as( List.class ).isEmpty() );
} 测试驾驶分页可发现性 测试分页的可发现性相对简单尽管有很多基础要讲。 测试的重点是导航中当前页面的位置以及应该从每个位置发现的不同URI Test
public void whenFirstPageOfResourcesAreRetrieved_thenSecondPageIsNext(){Response response givenAuth().get( paths.getFooURL()?page0size10 );String uriToNextPage extractURIByRel( response.getHeader( LINK ), REL_NEXT );assertEquals( paths.getFooURL()?page1size10, uriToNextPage );
}
Test
public void whenFirstPageOfResourcesAreRetrieved_thenNoPreviousPage(){Response response givenAuth().get( paths.getFooURL()?page0size10 );String uriToPrevPage extractURIByRel( response.getHeader( LINK ), REL_PREV );assertNull( uriToPrevPage );
}
Test
public void whenSecondPageOfResourcesAreRetrieved_thenFirstPageIsPrevious(){Response response givenAuth().get( paths.getFooURL()?page1size10 );String uriToPrevPage extractURIByRel( response.getHeader( LINK ), REL_PREV );assertEquals( paths.getFooURL()?page0size10, uriToPrevPage );
}
Test
public void whenLastPageOfResourcesIsRetrieved_thenNoNextPageIsDiscoverable(){Response first givenAuth().get( paths.getFooURL()?page0size10 );String uriToLastPage extractURIByRel( first.getHeader( LINK ), REL_LAST );Response response givenAuth().get( uriToLastPage );String uriToNextPage extractURIByRel( response.getHeader( LINK ), REL_NEXT );assertNull( uriToNextPage );
} 这些只是使用RESTful服务的集成测试的几个示例。 获取所有资源 关于分页和可发现性的同一主题必须选择是否允许客户端一次检索系统中的所有资源 或者客户端必须要求对它们进行分页。 如果选择了客户端无法通过单个请求检索所有资源并且分页不是可选的而是必需的则可以使用几个选项来响应对“获取所有”请求 。 一种选择是返回404 未找到 并使用Link标头使第一页可被发现 链接 http// localhost8080 / rest / api / admin / foopage 0size 10; rel “ first ”http// localhost8080 / rest / api / admin / foopage 103size 10; rel “ 最后一个 “ 另一个选择是将重定向– 303 请参阅其他 返回到分页的第一页。 第三种选择是为GET请求返回405 不允许使用方法 。 带有范围HTTP标头的REST Paginag 分页的一种相对不同的方法是使用HTTP Range标头 – RangeContent-RangeIf-RangeAccept-Ranges –和HTTP状态码 – 206 部分内容 413 请求实体太大 416 请求的范围无法满足 。 关于这种方法的一种观点是HTTP Range扩展不是用于分页的它们应该由服务器而不是由应用程序管理。 尽管在技术上不像本文中讨论的实现那样普遍但是基于HTTP Range标头扩展实现分页还是可行的。 结论 本文介绍了使用Spring在RESTful服务中分页的实现并讨论了如何实现和测试可发现性。 有关分页的完整实现请查看github项目。 如果您读完本文 则应 在Twitter上关注我 。 参考 Baeldung博客中我们JCG合作伙伴 Eugen Paraschiv的SpringREST分页 翻译自: https://www.javacodegeeks.com/2012/01/rest-pagination-in-spring.html