为了账号安全,请及时绑定邮箱和手机立即绑定

在 Spring 的编译期间用另一个注释替换一个注释?

在 Spring 的编译期间用另一个注释替换一个注释?

慕田峪7331174 2023-04-19 16:45:49
我在我的控制器参数上使用 Swagger 注释。所以,我最终得到了像@ApiParam(name="default name", value="this is a default value"). 我认为这很冗长。我想把它改成类似的东西@Foo。我想知道是否有办法在编译期间@Foo替换为。@ApiParam另外,由于我使用的是 Spring,我想我也必须考虑 Spring 中的注释处理顺序。我的意思是我不应该在 Swagger 或 Spring 接受它之后替换@ApiParam为。@Foo有什么办法吗?简而言之,我使用了 5 次具有相同参数的相同注释。基本上,我想用一些自定义注释替换它们。我知道我必须展示我已经尝试过的东西,但我不知道从哪里开始。另外,这个问题与Swagger无关,它只是一个例子。我想在编译时将一个注解替换为另一个注解,这样 Spring 拾取的将不是我放在源代码上的那个,而是我替换的那个。
查看完整描述

1 回答

?
慕码人2483693

TA贡献1860条经验 获得超9个赞

如果我理解您的要求,则无需编译时注释处理即可实现。它并不漂亮,而且可能比它的价值更复杂,但这是一种方法。


这是我制作的自定义注释,用于我的速记@ApiParam。


@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.PARAMETER)

public @interface GameIdParam {

    String name() default "My Game ID";


    String value() default "The integer ID of a particular game";

}

@ApiParam您可以定义您希望覆盖的任何属性。然后您可以使用Springfox 的扩展框架为新注释实现自定义处理程序。


import com.google.common.base.Optional;

import io.swagger.annotations.ApiParam;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.core.annotation.AnnotationUtils;

import org.springframework.stereotype.Component;

import springfox.documentation.schema.Example;

import springfox.documentation.spi.DocumentationType;

import springfox.documentation.spi.schema.EnumTypeDeterminer;

import springfox.documentation.spi.service.contexts.ParameterContext;

import springfox.documentation.spring.web.DescriptionResolver;

import springfox.documentation.swagger.readers.parameter.ApiParamParameterBuilder;


import java.util.function.Predicate;


import static java.util.Optional.ofNullable;

import static springfox.documentation.swagger.common.SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER;

import static springfox.documentation.swagger.common.SwaggerPluginSupport.pluginDoesApply;

import static springfox.documentation.swagger.readers.parameter.Examples.examples;


@Component

public class ShorthandAnnotationPlugin extends ApiParamParameterBuilder {

    private final DescriptionResolver descriptions;

    private final EnumTypeDeterminer enumTypeDeterminer;


    @Autowired

    public ShorthandAnnotationPlugin(

            DescriptionResolver descriptions,

            EnumTypeDeterminer enumTypeDeterminer) {

        super(descriptions, enumTypeDeterminer);

        this.descriptions = descriptions;

        this.enumTypeDeterminer = enumTypeDeterminer;

    }


    @Override

    public void apply(ParameterContext context) {

        Optional<GameIdParam> gameIdParam = context.resolvedMethodParameter().findAnnotation(GameIdParam.class);


        if (gameIdParam.isPresent()) {

            GameIdParam annotation = gameIdParam.get();


            // Instantiate an ApiParam so we can take default values for attributes we didn't override.

            ApiParam parentAnnotation = AnnotationUtils.synthesizeAnnotation(ApiParam.class);


            context.parameterBuilder().name(ofNullable(annotation.name())

                    .filter(((Predicate<String>) String::isEmpty).negate()).orElse(null))

                    .description(ofNullable(descriptions.resolve(annotation.value()))

                            .filter(((Predicate<String>) String::isEmpty).negate()).orElse(null))

                    .parameterAccess(ofNullable(parentAnnotation.access())

                            .filter(((Predicate<String>) String::isEmpty).negate())

                            .orElse(null))

                    .defaultValue(ofNullable(parentAnnotation.defaultValue())

                            .filter(((Predicate<String>) String::isEmpty).negate())

                            .orElse(null))

                    .allowMultiple(parentAnnotation.allowMultiple())

                    .allowEmptyValue(parentAnnotation.allowEmptyValue())

                    .required(parentAnnotation.required())

                    .scalarExample(new Example(parentAnnotation.example()))

                    .complexExamples(examples(parentAnnotation.examples()))

                    .hidden(parentAnnotation.hidden())

                    .collectionFormat(parentAnnotation.collectionFormat())

                    .order(SWAGGER_PLUGIN_ORDER);

        }

    }


    @Override

    public boolean supports(DocumentationType documentationType) {

        return pluginDoesApply(documentationType);

    }

}

我以Springfox 的 ApiParamParameterBuilder为例。


现在,我可以用我的@GameIdParam


@PostMapping("/{gameId}/info")

public String play(@GameIdParam @PathVariable int gameId) // ...

这种模式可以推广到与一系列自定义速记注释一起工作。它并不漂亮,它引入了另一种间接级别,了解 Springfox Swagger 的人不会熟悉。


查看完整回答
反对 回复 2023-04-19
  • 1 回答
  • 0 关注
  • 102 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信