问题描述
你能告诉我如何以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);
}
}
}