弹簧数据使用蛇形参数排序

问题描述

你能告诉我如何以snake_case格式将排序参数传递给rest控制器吗?

我的实体类

@Entity
public class MyEntity extends BaseEntity{

  @Id
  private Long id;

  @Column
  private Long parentId;
}

控制器方法

@GetMapping("list")
    List<MyEntity> getEntityList(
           @PageableDefault(sort = {"id"},direction = Sort.Direction.DESC) Pageable pageable);
}

在请求中我想使用 ?sort=parent_id

我已经创建了 Jackson2ObjectMapperBuilder 并且它构建了正确的 snake_case json

但是 spring 给我发送了 Caused by: org.springframework.data.mapping.PropertyReferenceException: No property parent found for type MyEntity! Did you mean 'parentId'? 我认为这是关于解析的问题,因为 spring 在 '_' 符号之后剪切了所有内容

我试过了:

  • @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
  • @Column(name = "parent_id") @JsonProperty("parent_id")
  • @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

解决方法

我解决了这个问题。为了正确使用snake_case 参数值,我们需要创建自定义的OncePerRequestFilter。此过滤器在传递给控制器​​之前准备参数。

用户 nullptr 使用相同的方式 here。顺便说一句,使用过滤器您可以准备任何其他参数/​​值,但此解决方案可能会产生错误。所有请求都将通过过滤器。

@Configuration
public class SnakeCaseFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain)
            throws ServletException,IOException {

        final Map<String,String[]> formattedParams = new ConcurrentHashMap<>();

        //Convert values for each parameter
        for (String param : request.getParameterMap().keySet()) {
            String[] values = request.getParameterValues(param);

            String formattedParam = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,param);

        formattedParams.put(formattedParam,values);
        }

        filterChain.doFilter(new CustomResponseWrapper(request,formattedParams),response);

    }


    /**
     * Wrapper return new formatted parameters
     */
     class CustomResponseWrapper extends HttpServletRequestWrapper {

        /**
         * Constructs a request object wrapping the given request.
         *
         * @param request the {@link HttpServletRequest} to be wrapped.
         * @throws IllegalArgumentException if the request is null
         */

        private Map<String,String[]> params;

        public CustomResponseWrapper(HttpServletRequest request,Map<String,String[]> params) {
            super(request);
            this.params = params;
        }

        @Override
        public Map<String,String[]> getParameterMap() {
            return params;
        }

        @Override
        public String[] getParameterValues(String name) {
            return params.get(name);
        }

    }
}