例子说明
在例子中,我们将学习如何分页显示用户的评论。
加入spring data
引入jar包
加入spring data在pom中引入
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.11.10.RELEASE</version> </dependency>
在Root上下文的配置
@Configuration @EnableAsync( mode = AdviceMode.PROXY, proxyTargetClass = false, order = Ordered.HIGHEST_PRECEDENCE ) @EnableTransactionManagement( mode = AdviceMode.PROXY, proxyTargetClass = false, order = Ordered.LOWEST_PRECEDENCE ) @EnableJpaRepositories( basePackages = "cn.wei.flowingflying.customer_support.site.repositories", entityManagerFactoryRef = "entityManagerFactoryBean", transactionManagerRef = "jpaTransactionManager" ) @EnableScheduling @ComponentScan( basePackages = "cn.wei.flowingflying.customer_support.site", excludeFilters = @ComponentScan.Filter({Controller.class,ControllerAdvice.class,Endpoint.class})) public class RootContextConfiguration implements AsyncConfigurer, SchedulingConfigurer{ ...... }
在DispatchServlet上下文的配置
简单地可以加上@EnableSpringDataWebSupport,在例子中,我们采用通过代码定制化设置的方式。
@Configuration @EnableWebMvc @ComponentScan( basePackages = "cn.wei.flowingflying.customer_support.site", useDefaultFilters = false, includeFilters = @ComponentScan.Filter(WebController.class)) public class WebServletContextConfiguration extends WebMvcConfigurerAdapter{ private static final Logger log = LogManager.getLogger(); @Inject private ApplicationContext applicationContext; ...... //【1】SortHandlerMethodArgumentResolver,转换请求中的Sort参数 //【2】PageableHandlerMethodArgumentResolver,转换请求中的Pageable参数 @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { //【1.1】设置缺省的排序方式:根据id的升序 Sort defaultSort = new Sort(new Sort.Order(Sort.Direction.ASC, "id")); //【2.1】设置缺省的分页情况,第一个参数是zero-based page index,如果显示第一页就填0,每页10个条目,采用缺省的排序方式(根据id的升序) Pageable defaultPageable = new PageRequest(0, 10, defaultSort); //【1.2】设置Sort的转换器:自动转换请求参数或者@SortDefault标记 SortHandlerMethodArgumentResolver sortResolver = new SortHandlerMethodArgumentResolver(); sortResolver.setSortParameter("paging.sort"); //请求中的排序参数为paging.sort,请对照后面的jsp代码 sortResolver.setFallbackSort(defaultSort); //【2.2】设置Page的转换器:从web请求中获取也信息,并注入到控制器方法中的Pageable对象中 PageableHandlerMethodArgumentResolver pageableResolver = new PageableHandlerMethodArgumentResolver(sortResolver); pageableResolver.setMaxPageSize(100); pageableResolver.setOneIndexedParameters(true); //页的序号从1开始,缺省是false pageableResolver.setPrefix("paging."); pageableResolver.setFallbackPageable(defaultPageable); //【1.3】添加解析器 resolvers.add(sortResolver); //【2.3】添加解析器 resolvers.add(pageableResolver); } //org.springframework.data.repository.support.DomainClassConverter:将请求参数和路径进行转换 @Override public void addFormatters(FormatterRegistry registry) { if(!(registry instanceof FormattingConversionService)){ log.warn("Unable to register Spring Data JPA converter."); return; } // DomainClassConverter adds itself to the registry。 // org.springframework.core.convert.converter.Converter to convert arbitrary input into domain classes managed by Spring Data CrudRepositorys. The implementation uses a ConversionService in turn to convert the source type into the domain class' id type which is then converted into a domain class object by using a CrudRepository. 也就是根据id自动获得一个entity DomainClassConverter<FormattingConversionService> converter = new DomainClassConverter<>((FormattingConversionService)registry); converter.setApplicationContext(this.applicationContext); } ...... }
如果有多个dispatchServlet,如果需要使用到分页和排序,我们也进行相应的的设置,相关的缺省参数不一样,代码例子如下:
@Configuration @EnableWebMvc @ComponentScan( basePackages = "cn.wei.flowingflying.customer_support.site", useDefaultFilters = false, includeFilters = @ComponentScan.Filter({RestEndpoint.class, RestEndpointAdvice.class}) ) public class RestServletContextConfiguration extends WebMvcConfigurerAdapter{ private static final Logger log = LogManager.getLogger(); @Inject ApplicationContext applicationContext; ...... @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { Sort defaultSort = new Sort(new Sort.Order(Sort.Direction.ASC, "id")); Pageable defaultPageable = new PageRequest(0, 20, defaultSort); SortHandlerMethodArgumentResolver sortResolver = new SortHandlerMethodArgumentResolver(); sortResolver.setSortParameter("$paging.sort"); sortResolver.setFallbackSort(defaultSort); PageableHandlerMethodArgumentResolver pageableResolver = new PageableHandlerMethodArgumentResolver(sortResolver); pageableResolver.setMaxPageSize(200); pageableResolver.setOneIndexedParameters(true); pageableResolver.setPrefix("$paging."); pageableResolver.setFallbackPageable(defaultPageable); resolvers.add(sortResolver); resolvers.add(pageableResolver); } @Override public void addFormatters(FormatterRegistry registry){ if(!(registry instanceof FormattingConversionService)){ log.warn("Unable to register Spring Data JPA converter."); return; } DomainClassConverter<FormattingConversionService> converter = new DomainClassConverter<>((FormattingConversionService)registry); converter.setApplicationContext(this.applicationContext); } }
对于RESTful接口分页的信息除了URL外,例如http://localhost:8080/persons?page=1&size=5&sort,还可以使用HTTP Range headers: Range, Content-Range, If-Range, Accept-Ranges,而相关的返回代码:
- 206 (Partial Content)
- 413 (Request Entity Too Large)
- 416 (Requested Range Not Satisfiable).