【问题标题】:Custom argument resolver for @PathVariable@PathVariable 的自定义参数解析器
【发布时间】:2018-05-21 11:04:23
【问题描述】:

场景:我的控制器接受 Long 值作为路径变量的 id。

我需要传递一个String,它是对 id 的外部引用。所以我需要将字符串引用解析为它的Long 值。

尝试:当注释 @PathVariable 存在时,我的自定义参数解析器不会被调用,因为 PathVariableMethodArgumentResolver 高于解析器列表中的自定义解析器,它只支持带有 @PathVariable 注释的所有参数

如果我删除 @PathVariable 并添加我自己的注释,它会正常工作。但随后 Swagger 将 id 作为 Request body 参数获取并产生此错误:

TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.

我的自定义解析器:

@Override
public boolean supportsParameter( MethodParameter methodParameter )
{
    return methodParameter.hasParameterAnnotation( ExternalRefParam.class );
}

@Override public Object resolveArgument( MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory ) throws Exception
{
    Map nameValueMap = (Map) nativeWebRequest.getAttribute( HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, 0 );
    switch( methodParameter.getParameterName() )
    {
        case CART_ID:
            return resolveCartId( nameValueMap );
        case PRODUCT_KEY:
            return resolveProductKey( nameValueMap );
    }
    return -1L;
}

控制器签名:

public ResponseEntity<Cart> readCart( 
                @ApiParam(value = "Cart ID", required = true) @ExternalRefParam Long cartId,  HttpServletRequest request )

【问题讨论】:

    标签: java spring spring-mvc swagger swagger-2.0


    【解决方案1】:

    我有一个类似的问题,我想添加一个自定义参数解析器,它将路径变量字符串值转换为大写。我通过创建一个GenericConverter 解决了这个问题,该GenericConverter 将一个字符串 => 字符串转换为带有某个注释的路径变量。

    路径变量注释类型只是一个标记注释,如下所示:

        @Target(ElementType.PARAMETER)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public @interface Uppercase {
            String value() default "";
        }
    

    用于像这样的休息控制器映射

        @PostMapping(value = "/clients/{clientId}/postalAddress")
        @ResponseStatus(HttpStatus.CREATED)
        public IdResponse create(
            @PathVariable("clientId") @Uppercase final String clientId,
            @RequestBody @NotNull @Valid final AddressRequest request) {...}
    

    然后触发 Generic Converter 以在任何 String 参数上运行,并且 convert 方法检查该参数是否被标记为 Uppercase 注释以了解它是否应该大写。这也意味着 Swagger API 仍将路径变量报告为来自路径并正确提取路径变量值,然后在使用 Uppercase 注释时运行转换器。

        public class CarPolicyIdAttributeConverter implements GenericConverter {
    
            @Override
            public Set<ConvertiblePair> getConvertibleTypes() {
                final ConvertiblePair[] pairs = new ConvertiblePair[] {
                    new ConvertiblePair(String.class, String.class)
                };
                return ImmutableSet.copyOf(pairs);
            }
    
            @Override
            public Object convert(final Object source, final TypeDescriptor sourceType, final TypeDescriptor targetType) {
                if (targetType.getAnnotation(Uppercase.class) != null) {
                    return ((String)source).toUppercase();
                }
                return source;
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-02
      • 2017-09-26
      • 2018-08-06
      • 2013-08-03
      • 2015-11-06
      • 2014-03-27
      相关资源
      最近更新 更多