@PathVariable的自定义参数解析器

问题描述 投票:1回答:1

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

我需要传递一个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个回答
1
投票

我有一个类似的问题,我想添加一个自定义参数解析器,将路径变量字符串值转换为大写。我通过创建一个GenericConverter来解决它,该 @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Uppercase { String value() default ""; } 为使用某个注释注释的路径变量转换了string =>字符串。

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

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

这是在像这样的休息控制器映射上使用的

Uppercase

然后触发Generic Converter在任何String参数上运行,并且convert方法检查参数是否用Uppercase注释标记,以确定它是否应该是大写的。这也意味着Swagger API仍然将路径变量报告为来自路径并正确提取路径变量值,然后运行转换器(如果它使用 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; } } 注释)。

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.