SpringBoot自动加载路由前缀
阅读原文时间:2023年07月08日阅读:2

@RequestMapping() 将controller注册到容器中时需要加入路由地址,如果项目层数较深,地址会非常的长,并且有很多一样的路由前缀,每写一个controller都要重复一遍非常的麻烦,既然Spring这么强大,有没有什么机制可以自动生成路由前缀?

思路:如何可以在@RequestMapping中不加URL前缀------>我们可以让配置类自动加入前缀

既然用@RequestMapping()可以注册路由,那肯定有一个对应的配置类可以修改路由地址。

RequestMappingHandlerMapping应运而生。我们需要写一个配置类继承RequestMappingHandlerMapping并重写其中的getMappingForMethod方法。

public class AutoPrefixUrlMapping extends RequestMappingHandlerMapping {
    //missyou.api-package = com.chauncy.missyou.api  写在application.properties中
    @Value("${missyou.api-package}")
    private String apiPackagePath;

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        //我们所需的路由信息在handlerType中
        RequestMappingInfo mappingForMethod = super.getMappingForMethod(method, handlerType);
        if (mappingForMethod != null) {
            String prefix = this.getPrefix(handlerType);
            //这里prefix = "/v1"但远远不够还要加上路由的自己设的地址
            return RequestMappingInfo.paths(prefix).build().combine(mappingForMethod);
        }
        return null;
    }

    private String getPrefix(Class<?> handlerType) {
        String packName = handlerType.getPackage().getName();
        //为什么这么处理?因为我们只需要和入口文件同级的包名,packName为该路由的完整包名
        //packname = com.chauncy.missyou.api.v1 而我们只需要v1这个前缀,
        String newPackName = packName.replaceAll(this.apiPackagePath, "");
        return newPackName.replace(".", "/");
    }
}

注意事项:不能简单的把这个配置类直接用Component注解加载到容器中

需要使用接口形式加载到容器中

@Component
public class AutoPrefixUrlMappingConfiguration implements WebMvcRegistrations {
    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new AutoPrefixUrlMapping();
    }
}

为什么?因为是这个类设计的时候规定的

protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
            return this.webFluxRegistrations != null && this.webFluxRegistrations.getRequestMappingHandlerMapping() != null ? this.webFluxRegistrations.getRequestMappingHandlerMapping() : super.createRequestMappingHandlerMapping();
        }

如果getRequestMappingHandlerMapping()返回值为空,就新建一个不做后续处理。