@PathVariable 的自定义参数解析器

Ish*_*ghe 3 java spring spring-mvc swagger swagger-2.0

场景:我的控制器接受Longid 的值,该值是路径变量。

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

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

@PathVariable如果我删除并添加自己的注释,效果很好。但随后 Swagger 获取 id 作为请求正文参数并产生以下错误:

TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
Run Code Online (Sandbox Code Playgroud)

我的自定义解析器:

@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;
}
Run Code Online (Sandbox Code Playgroud)

控制者签名:

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

Sha*_*att 5

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

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

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

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

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

然后触发通用转换器在任何字符串参数上运行,并且转换方法检查该参数是否用注释标记,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;
        }
    }
Run Code Online (Sandbox Code Playgroud)