【问题标题】:spring data Page/Pageable can't deserialization,how to use?spring data Page/Pageable不能反序列化,怎么用?
【发布时间】:2016-05-01 06:20:54
【问题描述】:

如果在控制器中使用 Page/Pageable 和 rest,我得到错误,因为它们没有用于反序列化的空结构

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of org.springframework.data.domain.Page, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
 at [Source: java.io.PushbackInputStream@67635da8; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148) ~[jackson-databind-2.6.4.jar:2.6.4]
at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:892) ~[jackson-databind-2.6.4.jar:2.6.4]
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:139) ~[jackson-databind-2.6.4.jar:2.6.4]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736) ~[jackson-databind-2.6.4.jar:2.6.4]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2810) ~[jackson-databind-2.6.4.jar:2.6.4]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:221) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
... 30 common frames omitted

【问题讨论】:

    标签: spring spring-data spring-data-jpa


    【解决方案1】:

    Pageable 实现 Page 并不是 Jackson 所期望的纯 POJO。但是,您可以构建自己的 Pageable 实现。您将能够将该实现传递给 Spring Data,因为它将尊重 Pageable 合同。

    我遇到了你的问题,我自己实现了 Pageable,以便我的 Java Rest Client 可以与我的 Spring Data Jpa Server 交换。

    【讨论】:

    • jpa实现了这些,PageImpl和PageRequest,但是没有空结构,所以不能反序列化,JpaRepository默认返回PageImpl怎么改成自定义实现
    • 您编写自己的 Pageable 接口实现。 Spring Data 与接口一起使用,因此只要您的自定义类实现 Pageable,您就可以毫无问题地将带有空结构的自定义 RestPageRequest 传递给 JPA 存储库。
    【解决方案2】:

    如果你通过 HTTP Body 传递参数,你需要使用一个具体的实现。推荐大牛的解决方案。

    另一个智能解决方案是使用HandlerMethodArgumentResolver

    第 1 步 - 创建与此类似的参数处理程序

    public class PageableHandler implements HandlerMethodArgumentResolver
    {
        @Override
        public boolean supportsParameter(MethodParameter methodParameter)
        {
            return methodParameter.getParameterType().equals(Pageable.class);
        }
    
        @Override
        public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception
        {
            String limit = nativeWebRequest.getParameter("limit");
            int size = toInt(limit, 100);
    
            String offset = nativeWebRequest.getParameter("offset");
            int page = (toInt(offset, size) / size);
            Sort sort = null;
            String sortStr = nativeWebRequest.getParameter("sort");
            String orderStr = nativeWebRequest.getParameter("order");
            if(sortStr != null && orderStr != null)
            {
                Direction direction = "asc".equalsIgnoreCase(orderStr) ? Direction.ASC : Direction.DESC;
                sort = new Sort(direction, sortStr);
            }        
            return new PageRequest(page, size, sort);
        }
    
        private int toInt(String value, int defaultValue)
        {
            int resultValue = defaultValue;
            if(value != null)
            {
                try
                {
                    resultValue = Integer.parseInt(value);
                }catch(NumberFormatException e)
                {
                }
            }
            return resultValue;
        }
    
    }
    

    第 2 步 - 在 Spring 配置中注册您的处理程序

    @Configuration
    public class WebMvcConfig extends WebMvcConfigurerAdapter {
    
    
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            argumentResolvers.add(new PageableHandler());
            super.addArgumentResolvers(argumentResolvers);
        }
    }
    

    第 3 步 - 在您的控制器上尽情使用

    @RequestMapping(value = "/api/personne", method = RequestMethod.GET)
    public List<Personne> getAllPersonnes(Pageable pageable) {
        return adminService.getAllPersonnes(pageable);
    }
    

    第 4 步 - REST GET 示例

    http://localhost:8080/api/personne?offset=2&limit=25
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-06
      • 2019-02-08
      • 1970-01-01
      • 2019-03-08
      • 1970-01-01
      • 2016-09-11
      • 1970-01-01
      • 2020-06-01
      相关资源
      最近更新 更多