Spring Boot 修改请求url

背景介绍

在做后端API接口的时候,被前端同事吐槽以前的接口URL没有遵循Restful API 规范,所以开会讨论,最终拍板确定,新做的要接口定义要照着标准规范来。

找了找关于Restful API的文章,还是这位大佬说的容易理解: www.ruanyifeng.com/blog/2014/0…

里面讲到了API的版本号。

这里跟组员协商确定后,URL要也同样要突出版本号。所以在某个版本阶段开发的API接口,要指明URL的版本号。

在实际代码中,发现如下问题:

如果把"v1"这类词直接写到controller的映射中,那就变成类似如下:

@GetMapping("/v1/user/info")
复制代码

这样每个实际url都要写一遍重复的"v1",不够灵活。

有没有方法,可以直接在指定的url上,前面全部拼接上v1呢?

因此这里就抛出一个问题:Spring Boot 如何修改请求url?

问题描述

Spring Boot 如何修改请求url?

关键词: Spring Boot add url prefix

解决方案

自定义注解@ApiVersion, 设置注解修饰的方法,在请求映射 request mapping 上添加前缀值。

具体值直接传入注解,即可。

实现代码

自定义注解 @ApiVersion

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiVersion {
    int[] value();
}
复制代码

配置注解 @ApiVersion 生效

自定义bean ApiVersionRequestMappingHandlerMapping, 重写 RequestMappingHandlerMapping


public class ApiVersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    private final String prefix;

    public ApiVersionRequestMappingHandlerMapping(String prefix) {
        this.prefix = prefix;
    }

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo info = super.getMappingForMethod(method, handlerType);
        if(info == null) return null;

        ApiVersion methodAnnotation = AnnotationUtils.findAnnotation(method, ApiVersion.class);
        if(methodAnnotation != null) {
            RequestCondition<?> methodCondition = getCustomMethodCondition(method);
            // Concatenate our ApiVersion with the usual request mapping
            info = createApiVersionInfo(methodAnnotation, methodCondition).combine(info);
        } else {
            ApiVersion typeAnnotation = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
            if(typeAnnotation != null) {
                RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
                // Concatenate our ApiVersion with the usual request mapping
                info = createApiVersionInfo(typeAnnotation, typeCondition).combine(info);
            }
        }
        return info;
    }

    private RequestMappingInfo createApiVersionInfo(ApiVersion annotation, RequestCondition<?> customCondition) {
        int[] values = annotation.value();
        String[] patterns = new String[values.length];
        for(int i=0; i<values.length; i++) {
            // Build the URL prefix
            patterns[i] = prefix+values[i];
        }

        return new RequestMappingInfo(
                new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(), useSuffixPatternMatch(), useTrailingSlashMatch(), getFileExtensions()),
                new RequestMethodsRequestCondition(),
                new ParamsRequestCondition(),
                new HeadersRequestCondition(),
                new ConsumesRequestCondition(),
                new ProducesRequestCondition(),
                customCondition);
    }

}

复制代码

添加配置WebMvcConfig,启动时注入bean ApiVersionRequestMappingHandlerMapping

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        return new ApiVersionRequestMappingHandlerMapping("v");
    }

    @Bean
    protected RequestMappingHandlerMapping customRequestMappingHandlerMapping() {
        return new ApiVersionRequestMappingHandlerMapping("v");
    }
}
复制代码

Controller 方法使用注解

如下所示:

原来的请求url是 : /user/info

加上注解 @ApiVersion 后,请求url就变成 /v1/user/info;

同理,改成@ApiVersion 后,请求url就变成 /v2/user/info.

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;
 
    @GetMapping("/info")
    @ApiVersion
    public R getUserInfo(UserQueryDTO userQueryDTO){
        try {
            return userService.getUserInfo(userQueryDTO)
                    .msg("success");
        } catch (Exception e) {
            log.error("get user info fail:{}", e);
            return R.fail().msg("get user info fail");
        }
    }

}

 

全部评论

相关推荐

给我发了笔试链接,想着等晚上回去做,结果还没做流程就终止了
伟大的小黄鸭在学习:我猜就是笔试几乎没用,就是用来给用人部门拖时间复筛简历的,可能用人部门筛到你简历觉得不合适就提前挂了
投递小鹏汽车等公司10个岗位
点赞 评论 收藏
分享
码农索隆:想看offer细节
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务