diff --git a/spring-boot-demo-swagger/README.md b/spring-boot-demo-swagger/README.md new file mode 100644 index 0000000..c978fd4 --- /dev/null +++ b/spring-boot-demo-swagger/README.md @@ -0,0 +1,257 @@ +# spring-boot-demo-swagger + +> 此 demo 主要演示了 Spring Boot 如何集成原生 swagger ,自动生成 API 文档。 + +# pom.xml + +```xml + + + 4.0.0 + + spring-boot-demo-swagger + 1.0.0-SNAPSHOT + jar + + spring-boot-demo-swagger + Demo project for Spring Boot + + + com.xkcoding + spring-boot-demo + 1.0.0-SNAPSHOT + + + + UTF-8 + UTF-8 + 1.8 + 2.9.2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.springfox + springfox-swagger2 + ${swagger.version} + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + + org.projectlombok + lombok + true + + + + + spring-boot-demo-swagger + + + org.springframework.boot + spring-boot-maven-plugin + + + + + +``` + +## Swagger2Config.java + +```java +/** + *

+ * Swagger2 配置 + *

+ * + * @package: com.xkcoding.swagger.config + * @description: Swagger2 配置 + * @author: yangkai.shen + * @date: Created in 2018-11-29 11:14 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Configuration +@EnableSwagger2 +public class Swagger2Config { + + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.xkcoding.swagger.controller")) + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder().title("spring-boot-demo") + .description("这是一个简单的 Swagger API 演示") + .contact(new Contact("Yangkai.Shen", "http://xkcoding.com", "237497819@qq.com")) + .version("1.0.0-SNAPSHOT") + .build(); + } + +} +``` + +## UserController.java + +> 主要演示API层的注解。 + +```java +/** + *

+ * User Controller + *

+ * + * @package: com.xkcoding.swagger.controller + * @description: User Controller + * @author: yangkai.shen + * @date: Created in 2018-11-29 11:30 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@RestController +@RequestMapping("/user") +@Api(tags = "1.0.0-SNAPSHOT", description = "用户管理", value = "用户管理") +@Slf4j +public class UserController { + @GetMapping + @ApiOperation(value = "条件查询(DONE)", notes = "备注") + @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "用户名", dataType = DataType.STRING, paramType = ParamType.QUERY, defaultValue = "xxx")}) + public ApiResponse getByUserName(String username) { + log.info("多个参数用 @ApiImplicitParams"); + return ApiResponse.builder().code(200) + .message("操作成功") + .data(new User(1, username, "JAVA")) + .build(); + } + + @GetMapping("/{id}") + @ApiOperation(value = "主键查询(DONE)", notes = "备注") + @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "用户编号", dataType = DataType.INT, paramType = ParamType.PATH)}) + public ApiResponse get(@PathVariable Integer id) { + log.info("单个参数用 @ApiImplicitParam"); + return ApiResponse.builder().code(200) + .message("操作成功") + .data(new User(id, "u1", "p1")) + .build(); + } + + @DeleteMapping("/{id}") + @ApiOperation(value = "删除用户(DONE)", notes = "备注") + @ApiImplicitParam(name = "id", value = "用户编号", dataType = DataType.INT, paramType = ParamType.PATH) + public void delete(@PathVariable Integer id) { + log.info("单个参数用 ApiImplicitParam"); + } + + @PostMapping + @ApiOperation(value = "添加用户(DONE)") + public User post(@RequestBody User user) { + log.info("如果是 POST PUT 这种带 @RequestBody 的可以不用写 @ApiImplicitParam"); + return user; + } + + @PostMapping("/multipar") + @ApiOperation(value = "添加用户(DONE)") + public List multipar(@RequestBody List user) { + log.info("如果是 POST PUT 这种带 @RequestBody 的可以不用写 @ApiImplicitParam"); + + return user; + } + + @PostMapping("/array") + @ApiOperation(value = "添加用户(DONE)") + public User[] array(@RequestBody User[] user) { + log.info("如果是 POST PUT 这种带 @RequestBody 的可以不用写 @ApiImplicitParam"); + return user; + } + + @PutMapping("/{id}") + @ApiOperation(value = "修改用户(DONE)") + public void put(@PathVariable Long id, @RequestBody User user) { + log.info("如果你不想写 @ApiImplicitParam 那么 swagger 也会使用默认的参数名作为描述信息 "); + } + + @PostMapping("/{id}/file") + @ApiOperation(value = "文件上传(DONE)") + public String file(@PathVariable Long id, @RequestParam("file") MultipartFile file) { + log.info(file.getContentType()); + log.info(file.getName()); + log.info(file.getOriginalFilename()); + return file.getOriginalFilename(); + } +} +``` + +## ApiResponse.java + +> 主要演示了 实体类 的注解。 + +```java +/** + *

+ * 通用API接口返回 + *

+ * + * @package: com.xkcoding.swagger.common + * @description: 通用API接口返回 + * @author: yangkai.shen + * @date: Created in 2018-11-29 11:30 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "通用PI接口返回", description = "Common Api Response") +public class ApiResponse implements Serializable { + private static final long serialVersionUID = -8987146499044811408L; + /** + * 通用返回状态 + */ + @ApiModelProperty(value = "通用返回状态", required = true) + private Integer code; + /** + * 通用返回信息 + */ + @ApiModelProperty(value = "通用返回信息", required = true) + private String message; + /** + * 通用返回数据 + */ + @ApiModelProperty(value = "通用返回数据", required = true) + private T data; +} +``` + +## 参考 + +1. swagger 官方网站:https://swagger.io/ + +2. swagger 官方文档:https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Getting-started + +3. swagger 常用注解:https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Annotations diff --git a/spring-boot-demo-swagger/pom.xml b/spring-boot-demo-swagger/pom.xml index f5a921e..525313d 100644 --- a/spring-boot-demo-swagger/pom.xml +++ b/spring-boot-demo-swagger/pom.xml @@ -20,12 +20,13 @@ UTF-8 UTF-8 1.8 + 2.9.2 org.springframework.boot - spring-boot-starter + spring-boot-starter-web @@ -33,9 +34,28 @@ spring-boot-starter-test test + + + io.springfox + springfox-swagger2 + ${swagger.version} + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + + org.projectlombok + lombok + true + + spring-boot-demo-swagger org.springframework.boot diff --git a/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/SpringBootDemoSwaggerApplication.java b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/SpringBootDemoSwaggerApplication.java index 79e6ab4..dbc1c78 100644 --- a/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/SpringBootDemoSwaggerApplication.java +++ b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/SpringBootDemoSwaggerApplication.java @@ -3,6 +3,19 @@ package com.xkcoding.swagger; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +/** + *

+ * 启动器 + *

+ * + * @package: com.xkcoding.swagger + * @description: 启动器 + * @author: yangkai.shen + * @date: Created in 2018-11-29 13:25 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ @SpringBootApplication public class SpringBootDemoSwaggerApplication { diff --git a/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/ApiResponse.java b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/ApiResponse.java new file mode 100644 index 0000000..523a8b6 --- /dev/null +++ b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/ApiResponse.java @@ -0,0 +1,47 @@ +package com.xkcoding.swagger.common; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * 通用API接口返回 + *

+ * + * @package: com.xkcoding.swagger.common + * @description: 通用API接口返回 + * @author: yangkai.shen + * @date: Created in 2018-11-29 11:30 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "通用PI接口返回", description = "Common Api Response") +public class ApiResponse implements Serializable { + private static final long serialVersionUID = -8987146499044811408L; + /** + * 通用返回状态 + */ + @ApiModelProperty(value = "通用返回状态", required = true) + private Integer code; + /** + * 通用返回信息 + */ + @ApiModelProperty(value = "通用返回信息", required = true) + private String message; + /** + * 通用返回数据 + */ + @ApiModelProperty(value = "通用返回数据", required = true) + private T data; +} diff --git a/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/DataType.java b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/DataType.java new file mode 100644 index 0000000..0caf4ae --- /dev/null +++ b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/DataType.java @@ -0,0 +1,30 @@ +package com.xkcoding.swagger.common; + +/** + *

+ * 方便在 @ApiImplicitParam 的 dataType 属性使用 + *

+ * + * @package: com.xkcoding.swagger.common + * @description: 方便在 @ApiImplicitParam 的 dataType 属性使用 + * @author: yangkai.shen + * @date: Created in 2018-11-29 13:23 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +public final class DataType { + + public final static String STRING = "String"; + public final static String INT = "int"; + public final static String LONG = "long"; + public final static String DOUBLE = "double"; + public final static String FLOAT = "float"; + public final static String BYTE = "byte"; + public final static String BOOLEAN = "boolean"; + public final static String ARRAY = "array"; + public final static String BINARY = "binary"; + public final static String DATETIME = "dateTime"; + public final static String PASSWORD = "password"; + +} \ No newline at end of file diff --git a/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/ParamType.java b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/ParamType.java new file mode 100644 index 0000000..438cea8 --- /dev/null +++ b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/common/ParamType.java @@ -0,0 +1,24 @@ +package com.xkcoding.swagger.common; + +/** + *

+ * 方便在 @ApiImplicitParam 的 paramType 属性使用 + *

+ * + * @package: com.xkcoding.swagger.common + * @description: 方便在 @ApiImplicitParam 的 paramType 属性使用 + * @author: yangkai.shen + * @date: Created in 2018-11-29 13:24 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +public final class ParamType { + + public final static String QUERY = "query"; + public final static String HEADER = "header"; + public final static String PATH = "path"; + public final static String BODY = "body"; + public final static String FORM = "form"; + +} \ No newline at end of file diff --git a/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/config/Swagger2Config.java b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/config/Swagger2Config.java new file mode 100644 index 0000000..04d0924 --- /dev/null +++ b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/config/Swagger2Config.java @@ -0,0 +1,48 @@ +package com.xkcoding.swagger.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + *

+ * Swagger2 配置 + *

+ * + * @package: com.xkcoding.swagger.config + * @description: Swagger2 配置 + * @author: yangkai.shen + * @date: Created in 2018-11-29 11:14 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Configuration +@EnableSwagger2 +public class Swagger2Config { + + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.xkcoding.swagger.controller")) + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder().title("spring-boot-demo") + .description("这是一个简单的 Swagger API 演示") + .contact(new Contact("Yangkai.Shen", "http://xkcoding.com", "237497819@qq.com")) + .version("1.0.0-SNAPSHOT") + .build(); + } + +} \ No newline at end of file diff --git a/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/controller/UserController.java b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/controller/UserController.java new file mode 100644 index 0000000..db6cd11 --- /dev/null +++ b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/controller/UserController.java @@ -0,0 +1,100 @@ +package com.xkcoding.swagger.controller; + +import com.xkcoding.swagger.common.ApiResponse; +import com.xkcoding.swagger.common.DataType; +import com.xkcoding.swagger.common.ParamType; +import com.xkcoding.swagger.entity.User; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + *

+ * User Controller + *

+ * + * @package: com.xkcoding.swagger.controller + * @description: User Controller + * @author: yangkai.shen + * @date: Created in 2018-11-29 11:30 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@RestController +@RequestMapping("/user") +@Api(tags = "1.0.0-SNAPSHOT", description = "用户管理", value = "用户管理") +@Slf4j +public class UserController { + @GetMapping + @ApiOperation(value = "条件查询(DONE)", notes = "备注") + @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "用户名", dataType = DataType.STRING, paramType = ParamType.QUERY, defaultValue = "xxx")}) + public ApiResponse getByUserName(String username) { + log.info("多个参数用 @ApiImplicitParams"); + return ApiResponse.builder().code(200) + .message("操作成功") + .data(new User(1, username, "JAVA")) + .build(); + } + + @GetMapping("/{id}") + @ApiOperation(value = "主键查询(DONE)", notes = "备注") + @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "用户编号", dataType = DataType.INT, paramType = ParamType.PATH)}) + public ApiResponse get(@PathVariable Integer id) { + log.info("单个参数用 @ApiImplicitParam"); + return ApiResponse.builder().code(200) + .message("操作成功") + .data(new User(id, "u1", "p1")) + .build(); + } + + @DeleteMapping("/{id}") + @ApiOperation(value = "删除用户(DONE)", notes = "备注") + @ApiImplicitParam(name = "id", value = "用户编号", dataType = DataType.INT, paramType = ParamType.PATH) + public void delete(@PathVariable Integer id) { + log.info("单个参数用 ApiImplicitParam"); + } + + @PostMapping + @ApiOperation(value = "添加用户(DONE)") + public User post(@RequestBody User user) { + log.info("如果是 POST PUT 这种带 @RequestBody 的可以不用写 @ApiImplicitParam"); + return user; + } + + @PostMapping("/multipar") + @ApiOperation(value = "添加用户(DONE)") + public List multipar(@RequestBody List user) { + log.info("如果是 POST PUT 这种带 @RequestBody 的可以不用写 @ApiImplicitParam"); + + return user; + } + + @PostMapping("/array") + @ApiOperation(value = "添加用户(DONE)") + public User[] array(@RequestBody User[] user) { + log.info("如果是 POST PUT 这种带 @RequestBody 的可以不用写 @ApiImplicitParam"); + return user; + } + + @PutMapping("/{id}") + @ApiOperation(value = "修改用户(DONE)") + public void put(@PathVariable Long id, @RequestBody User user) { + log.info("如果你不想写 @ApiImplicitParam 那么 swagger 也会使用默认的参数名作为描述信息 "); + } + + @PostMapping("/{id}/file") + @ApiOperation(value = "文件上传(DONE)") + public String file(@PathVariable Long id, @RequestParam("file") MultipartFile file) { + log.info(file.getContentType()); + log.info(file.getName()); + log.info(file.getOriginalFilename()); + return file.getOriginalFilename(); + } +} diff --git a/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/entity/User.java b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/entity/User.java new file mode 100644 index 0000000..3862b9b --- /dev/null +++ b/spring-boot-demo-swagger/src/main/java/com/xkcoding/swagger/entity/User.java @@ -0,0 +1,45 @@ +package com.xkcoding.swagger.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * 用户实体 + *

+ * + * @package: com.xkcoding.swagger.entity + * @description: 用户实体 + * @author: yangkai.shen + * @date: Created in 2018-11-29 11:31 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "用户实体", description = "User Entity") +public class User implements Serializable { + private static final long serialVersionUID = 5057954049311281252L; + /** + * 主键id + */ + @ApiModelProperty(value = "主键id", required = true) + private Integer id; + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名", required = true) + private String name; + /** + * 工作岗位 + */ + @ApiModelProperty(value = "工作岗位", required = true) + private String job; +} diff --git a/spring-boot-demo-swagger/src/main/resources/application.properties b/spring-boot-demo-swagger/src/main/resources/application.properties deleted file mode 100644 index e69de29..0000000 diff --git a/spring-boot-demo-swagger/src/main/resources/application.yml b/spring-boot-demo-swagger/src/main/resources/application.yml new file mode 100644 index 0000000..a02fbde --- /dev/null +++ b/spring-boot-demo-swagger/src/main/resources/application.yml @@ -0,0 +1,4 @@ +server: + port: 8080 + servlet: + context-path: /demo \ No newline at end of file