Spring Boot从零入门6_Swagger2生成生产环

发布时间:2020-08-03 23:57:54 作者:艾弗森哇
来源:网络 阅读:424

1 前言

在如今前后端分离开发的模式下,前端调用后端提供的API去实现数据的展示或者相关的数据操作,保证及时更新和完整的REST API文档将会大大地提高两边的工作效率,减少不必要的沟通成本。本文采用的Swagger2就是一个当前流行的通过少量的注解就可以生成漂亮的API文档工具,且在生成的在线文档中提供类似POSTMAN直接调试能力,不仅仅是静态的文档。接下来将会利用这个工具与Spring Boot项目结合,最终生成我们上一篇文章中所涉及到的REST API文档。

这一篇文章基本将Swagger2在生产环境中可能会用到的配置都有涉及,慢慢看吧,看了这一篇因该是够了。

2 Swagger2简介

Swagger是与用于实现 OpenAPI 文档广泛使用的工具,Swagger工具集包括开源工具,免费工具和商业工具的组合,可在API生命周期的不同阶段使用。

3 开始使用

3.1 构建Restful WEB服务

参考《Spring Boot从零入门5_五脏俱全的RESTful Web Service构建》。构建好后有如下REST API:

# 获取所有用户信息GET http://localhost:8080/api/v1/users# 新增一个用户,参数通过body传递POST http://localhost:8080/api/v1/users# 更新一个用户信息PUT http://localhost:8080/api/v1/users/{id}# 删除指定用户DELETE http://localhost:8080/api/v1/users/{id}

3.2 集成Swagger2

构建好RESTful WEB服务后,接下来我们集成Swagger,然后对上节中的REST API自动生成接口文档。

3.2.1 pom.xml添加依赖

集成Swagger2,需要在pom.xml中添加依赖源:

<dependencies>
	<dependency>
	    <groupid>io.springfox</groupid>
	    <artifactid>springfox-swagger2</artifactid>
	    <!-- 截至2019年11月7日为止,最新版本为2.9.2 -->
	    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
	    <version>2.9.2</version>
	</dependency></dependencies>
3.2.2 Swagger 配置及初始化

springfox有一个专用对象Docket,可以灵活的配置Swagger的各种属性,首先我们简单的创建一个Swagger配置类Swagger2Config.java

@Configuration@EnableSwagger2
public class Swagger2Config {
    @Bean("UsersApis")
    public Docket usersApis() {        return new Docket(DocumentationType.SWAGGER_2)                .select()                .apis(RequestHandlerSelectors.any())                .paths(PathSelectors.any())                .build();
    }
}

这里的@Configuration注解用于定义配置类,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext类进行扫描,并用于构建Bean定义,初始化对象。@ComponentScan会自动获取所有的Spring Components,包括@Configuration类。另外这里的“用户管理模块”API生成配置很简单,对所有路径上API都去生成文档。

3.2.3 启动服务并验证

当完成Swagger2的配置类时,启动WEB服务,通过http://localhost:8080/v2/api-docs就可以访问生成文档内容,但是浏览器返回的是JSON内容,基本上很难给需要用到相关API的开发人员进行参考。这个时候就需要用到Swagger2 UI了。

3.3 集成Swagger2 UI

pom.xml添加依赖,然后重启WEB服务就可以了,再次访问http://localhost:8080/swagger-ui.html,这时候看到的就是WEB文档了。

<dependency>
    <groupid>io.springfox</groupid>
    <artifactid>springfox-swagger-ui</artifactid>
    <version>2.9.2</version></dependency>

Spring Boot从零入门6_Swagger2生成生产环

从swagger-ui页面看到的内容有一部无关的内容,或者是如何明显表现跟项目相关的内容呢?下面章节详细讲解Swagger的各种配置,能够应用到实际生产环境中去。

4 Swagger2 深度配置

4.1 深度配置目标

首先,如果要将我们最后生成的API文档给生产环境的开发人员查阅,那么友好的展示信息和归类是很有必要的,我们接下来实现如下目标:

为了更好地展示API分组功能,这里另外加了一组REST API (代码层面上只需要将User相关的代码全部复制一份,将User关键字全部改为Product就可以了,包括大小写):

# 获取所有产品信息GET http://localhost:8080/api/v1/products# 新增一个产品,参数通过body传递POST http://localhost:8080/api/v1/products# 更新一个产品信息PUT http://localhost:8080/api/v1/products/{id}# 删除指定产品DELETE http://localhost:8080/api/v1/products/{id}

4.2 文档信息配置

@Configuration@EnableSwagger2public class Swagger2Config {    @Bean("UsersApis")    public Docket usersApis() {        return new Docket(DocumentationType.SWAGGER_2)        		// select()返回的是ApiSelectorBuilder对象,而非Docket对象
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())                 
                // build()返回的是Docket对象
                .build()                // 测试API时的主机URL
                .host("https://xiaobaiai.net")    
                // API前缀
                .pathProvider(new RelativePathProvider(null) {                    @Override
                    public String getApplicationBasePath() {                        return "/prefix";
                    }
                })
                .apiInfo(apiInfo());
    }    
    public ApiInfo apiInfo() {    	// API负责人的联系信息
    	final Contact contact = new Contact(    			"Ethan", "https://xiaobaiai.net", "ycm_hy@163.com");        return new ApiInfoBuilder()        	// API文档标题
            .title("X系统平台接口文档")            // API文档描述
            .description("用户/产品相关API, 更多请关注公众号: 小白AI 或微信小程序:小白AI博客")            // 服务条款URL
            .termsOfServiceUrl("https://github.com/yicm")            // API文档版本
            .version("1.0")            // API负责人的联系信息
            .contact(contact)            // API的许可证Url
            .licenseUrl("http://license.coscl.org.cn/MulanPSL")
            .license("MulanPSL")
            .build();
    }
}

通过添加文档信息编译对象ApiInfoBuilder可以配置API文档的各种信息,包括标题、描述、服务条款、版本、责任人、许可证等。最后在Docket中添加信息配置对象即可生效。

4.3 API分组配置、API精细配置

4.3.1 API分组展示

上面的文档信息配置中默认是没有对API分组的,即所有的API都展示在了一个页面,没有隔离,如果需要分组,那我们需要对不同API组分配Bean,目前示例可以分为用户API组和产品API组,然后通过apis() 和 paths()进行API过滤。

为了不显示某个包下面API或某个URL路径下API, Docket提供了 apis() 和 paths() 两 个方法来帮助我们在不同级别上过滤接口(上面示例我们默认对这两个设置是不做任何过滤,扫描所有API):

apis和paths中的Predicates除了anyantnone,还支持regex正则表达式。

如:

PathSelectors.regex("/api/v2/users.*")

下面就是分组示例代码,实现分组,很简单,就是在Docket中配置组名就好了:

@Configuration@EnableSwagger2public class Swagger2Config {    @Bean
    public Docket usersApis() {        return new Docket(DocumentationType.SWAGGER_2)
        		.groupName("用户管理接口")        		// select()返回的是ApiSelectorBuilder对象,而非Docket对象
                .select()
                
                .apis(RequestHandlerSelectors.basePackage("com.xiaobaiai.user"))
                .paths(Predicates.or(                        // 两个**,可以匹配底下所有URL
                        // 一个*,只能匹配一级URL分段
                        PathSelectors.ant("/api/v1/users/**"),
                        PathSelectors.ant("/api/v1/users/*")))              
                // build()返回的是Docket对象
                .build()                // 测试API时的主机URL
                .host("https://xiaobaiai.net")    
                // API前缀,最终所有API的基础地址就是host+prefix: https://xiaobaiai.net/prefix
                .pathProvider(new RelativePathProvider(null) {                    @Override
                    public String getApplicationBasePath() {                        return "/prefix";
                    }
                })
                .apiInfo(apiInfo());
    }    
    @Bean
    public Docket productsApis() {        return new Docket(DocumentationType.SWAGGER_2)
        		.groupName("产品管理接口")        		// select()返回的是ApiSelectorBuilder对象,而非Docket对象
                .select()
                
                .apis(RequestHandlerSelectors.basePackage("com.xiaobaiai.product"))
                .paths(Predicates.or(                        // 两个**,可以匹配底下所有URL
                        // 一个*,只能匹配一级URL分段
                        PathSelectors.ant("/api/v1/products/**"),
                        PathSelectors.ant("/api/v1/products/*")))              
                // build()返回的是Docket对象
                .build()                // 测试API时的主机URL
                .host("https://xiaobaiai.net")    
                // API前缀
                .pathProvider(new RelativePathProvider(null) {                    @Override
                    public String getApplicationBasePath() {                        return "/prefix";
                    }
                })
                .apiInfo(apiInfo());
    }    
    public ApiInfo apiInfo() {    	// API负责人的联系信息
    	final Contact contact = new Contact(    			"Ethan", "https://xiaobaiai.net", "ycm_hy@163.com");        return new ApiInfoBuilder()        	// API文档标题
            .title("X系统平台接口文档")            // API文档描述
            .description("用户/产品相关API, 更多请关注公众号: 小白AI 或微信小程序:小白AI博客")            // 服务条款URL
            .termsOfServiceUrl("https://github.com/yicm")            // API文档版本
            .version("1.0")            // API负责人的联系信息
            .contact(contact)            // API的许可证Url
            .licenseUrl("http://license.coscl.org.cn/MulanPSL")
            .license("MulanPSL")
            .build();
    }
}

分组配置完成后,重新启动,打开浏览器就可以看到效果了:

Spring Boot从零入门6_Swagger2生成生产环

4.3.2 API精细配置

虽然上面我们已经可以控制API的显示和分组了,但是对于API一些更详细,对组内API再次归类之类的,比如小组的描述信息,以及每个API如何去控制它的参数说明,返回值说明等。这些都是通过注解去实现的,接下来我们讲述常用的注解及作用:

  1. @Api : 将这个注解添加到控制器类上,则可以给控制器添加描述类信息:

相关可设置参数有:

示例:

// Swagger配置类@Configuration@EnableSwagger2public class Swagger2Config {@Bean
    public Docket productsApis() {        return new Docket(DocumentationType.SWAGGER_2)
        		.groupName("产品管理接口")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xiaobaiai.product"))
                .paths(Predicates.or(
                        PathSelectors.ant("/api/v1/products/**"),
                        PathSelectors.ant("/api/v1/products/*")))              
                .build()
                .host("https://xiaobaiai.net")    
                .pathProvider(new RelativePathProvider(null) {                    @Override
                    public String getApplicationBasePath() {                        return "/prefix";
                    }
                })
                .apiInfo(apiInfo())
                .tags(new Tag("产品操作分组1", "产品查询相关操作."),                        new Tag("产品操作分组2", "产品添加或删除相关操作."),                        new Tag("产品操作分组3", "产品更新相关操作."),                        new Tag("产品操作分组4", "产品相关全部操作."));
    }
}
// 控制器类@RestController@RequestMapping("/api/v1")@Api(tags={"产品接口文档列表"})public class ProductServiceController { ... }

效果如下:

Spring Boot从零入门6_Swagger2生成生产环

  1. @ApiIgnore: 作用在REST API控制器方法上,则该API不会被显示出来:

@ApiIgnore@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)public ResponseEntity<object> delete(@PathVariable("id") String id) { ... }
  1. @ApiOperation 注解用于控制器方法上面,用于对方法的描述,相关参数设置描述如下:

示例:

@ApiOperation(value = "获取所有产品", notes = "每调用一次,就耗费流量100M", response = String.class)@GetMapping(value = "/products")public ResponseEntity<object> getProduct() {	return new ResponseEntity&lt;&gt;(productService.getProducts(), HttpStatus.OK);
}

最后效果就是:

Spring Boot从零入门6_Swagger2生成生产环

  1. @ApiImplicitParams@ApiImplicitParam 注解用于控制器方法传入参数的说明。默认情况下,Swagger会根据API方法中的传入参数进行参数说明的生成,不过参数说明默认就是变量名,因为这两个注解不一定需要。相关参数设置说明如下:

示例:

// 如果只有一个参数,则仅仅@ApiImplicitParam就可以了@ApiImplicitParams({	@ApiImplicitParam(name="id", value="产品ID值", required = true),	@ApiImplicitParam(name="product", value="产品内容", required = true)
})@RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)public ResponseEntity<object> updateProduct(@PathVariable("id") String id, @RequestBody Product product) {
	productService.updateProduct(id, product);	return new ResponseEntity&lt;&gt;("Product is updated successsfully", HttpStatus.OK);
}

Spring Boot从零入门6_Swagger2生成生产环

焦作国医堂胃肠医院评价怎么样:http://jz.lieju.com/zhuankeyiyuan/37174965.htm

  1. @ApiParam: 作用同ApiImplicitParam,单个参数描述一般常用该注解,而且该注解只能与JAX-RS 1.x/2.x注解结合使用。参数设置说明如下:

  1. @ApiResponses@ApiResponse: 用于控制器方法返回值的说明,参数设置说明如下:

示例:

@ApiOperation(value = "获取所有产品", notes = "每调用一次,就耗费流量100M",response =Product.class, responseContainer="List")@ApiResponses({    @ApiResponse(code = 200, message = "成功!", response=Product.class),    @ApiResponse(code = 401, message = "未授权!", response=Product.class),    @ApiResponse(code = 404, message = "页面未找到!", response=Product.class),    @ApiResponse(code = 403, message = "出错了!", response=Product.class)
})@GetMapping(value = "/products")public ResponseEntity<object> getProduct() {	return new ResponseEntity&lt;&gt;(productService.getProducts(), HttpStatus.OK);
}

效果如下:

Spring Boot从零入门6_Swagger2生成生产环

  1. @Deprecated: 作用于控制器方法上,标注该方法已经过时,建议开发者采用新的方式之类的。

  2. @ApiModel:作用在JavaBean类上,说明JavaBean的用途,如我们定义的Product.java类。常用参数设置如下:

示例:

@ApiModel(value="Product",description="对产品定义的描述")public class Product { ... }
  1. @ApiModelProperty: 同样用于在JavaBean类的属性上面,说明相关属性。类似于方法上说明的@ApiImplicitParam。设置参数有:

4.4 API历史版本管理

管理不同API版本有好几种方式:

这里我们对第一种方式示例展示:

在Swagger2Config.java中新添加一个用户API Docket:

@Configuration@EnableSwagger2public class Swagger2Config {    @Bean("UsersApis_V1")    public Docket usersApisV1() {        return new Docket(DocumentationType.SWAGGER_2)
        		.groupName("用户管理接口V1")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xiaobaiai.user"))
                .paths(Predicates.or(                        // 过滤版本v1
                        PathSelectors.ant("/api/v1/users/**"),
                        PathSelectors.ant("/api/v1/users/*")))      
                .build()
                .host("https://xiaobaiai.net")    
                .pathProvider(new RelativePathProvider(null) {                    @Override
                    public String getApplicationBasePath() {                        return "/prefix";
                    }
                })
                .apiInfo(apiInfo());
    }    
    @Bean("UsersApis_V21")    public Docket usersApisV2() {        return new Docket(DocumentationType.SWAGGER_2)
        		.groupName("用户管理接口V2")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xiaobaiai.user"))
                .paths(Predicates.or(                        // 过滤版本v1
                        PathSelectors.ant("/api/v2/users/**"),
                        PathSelectors.ant("/api/v2/users/*")))      
                .build()
                .host("https://xiaobaiai.net")    
                .pathProvider(new RelativePathProvider(null) {                    @Override
                    public String getApplicationBasePath() {                        return "/prefix";
                    }
                })
                .apiInfo(apiInfo());
    }    
    @Bean
    public Docket productsApis() {        return new Docket(DocumentationType.SWAGGER_2)
        	.....
    }    
    public ApiInfo apiInfo() {    	final Contact contact = new Contact(    			"Ethan", "https://xiaobaiai.net", "ycm_hy@163.com");        return new ApiInfoBuilder()
            .title("X系统平台接口文档")
            .description("用户/产品相关API, 更多请关注公众号: 小白AI 或微信小程序:小白AI博客")
            .termsOfServiceUrl("https://github.com/yicm")
            .version("1.0")
            .contact(contact)
            .licenseUrl("http://license.coscl.org.cn/MulanPSL")
            .license("MulanPSL")
            .build();
    }
}

然后控制器添加新版本API方法:

@RestController@RequestMapping("/api")public class UserServiceController {	@Autowired
	UserService userService;	
	@DeleteMapping({"/v1/users/{id}", "/v2/users/{id}"})	public ResponseEntity<object> delete(@PathVariable("id") String id) {
		userService.deleteUser(id);		return new ResponseEntity&lt;&gt;("User is deleted successsfully", HttpStatus.OK);
	}	@PutMapping({"/v1/users/{id}", "/v2/users/{id}"})	public ResponseEntity<object> updateUser(@PathVariable("id") String id, @RequestBody User user) {
		userService.updateUser(id, user);		return new ResponseEntity&lt;&gt;("User is updated successsfully", HttpStatus.OK);
	}	@PostMapping({"/v1/users", "/v2/users"})	public ResponseEntity<object> createUser(@RequestBody User user) {
		userService.createUser(user);		return new ResponseEntity&lt;&gt;("User is created successfully", HttpStatus.CREATED);
	}	@GetMapping({"/v1/users"})	@Deprecated
	public ResponseEntity<object> getUser() {		return new ResponseEntity&lt;&gt;(userService.getUsers(), HttpStatus.OK);
	}	
	@GetMapping(value = "/v2/users")	public ResponseEntity<object> getUser(@RequestParam String id) {		return new ResponseEntity&lt;&gt;(userService.getUsers(), HttpStatus.OK);
	}
}

最后效果:

Spring Boot从零入门6_Swagger2生成生产环

推荐阅读:
  1. Java学习(随笔)—Spring boot简介以及Grad
  2. 构建微服务:快速搭建Spring Boot项目

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

spring boot spring boo bo

上一篇:七、yarn基本原理

下一篇:二进制方式快速安装MySQL数据库命令集合

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》