关于swagger:同步Swagger-URL-问题用这个插件就能解决

这个开源的 API 管理工具叫 Postcat, 反对从 Swagger URL 增量同步 API 数据到 Postcat。 应用进入 API 模块,鼠标挪动到主按钮加号,下拉看到从 Swagger 同步 URL 的选项。 填写完配置点击立刻同步即可同步 API 数据。 同步规定新的数据笼罩旧的数据 API Path 和申请形式雷同视为同一 API同名同层级的分组视为同一分组如果你日常会用到 api 管理工具的话,无妨看看我目前参加的这个开源我的项目,Postcat 开源的 API 管理工具,纯国产,收费的,主打插件生态,适宜中小团队以及集体开发者应用,有 API 相干的外围性能。 目前在 Github 上 3k star,如果你感觉这个我的项目还不错的话,无妨点个 star 反对一下~ Github:https://github.com/Postcatlab/postcat Postcat 外围性能:API 文档治理:可视化 API 设计,生成 API 文档API 测试:主动生成测试参数,主动生成测试用例,可视化数据编辑插件拓展:泛滥插件扩大产品性能,打造属于你和团队的 API 开发平台Mock:依据文档主动生成 Mock,或创立自定义 Mock 满足简单场景团队合作:既能实现 API 分享也能能够创立云空间独特合作

May 15, 2023 · 1 min · jiezi

关于swagger:除了-Swagger这个开源-API-工具生成文档更高效

提起 Swagger,常常接触接口开发的敌人,肯定晓得并且都纯熟应用了。 Swagger 是一个用于生成、形容和调用 RESTful 接口的 Web 服务。艰深的来讲,Swagger 就是将我的项目中所有(想要裸露的)接口展示在页面上,并且能够进行接口调用和测试的服务。 咱们不难看出 Swagger 有以下 3 个重要的作用:将我的项目中所有的接口展示在页面上,这样后端程序员就不须要专门为前端使用者编写专门的接口文档;当接口更新之后,只须要批改代码中的 Swagger 形容就能够实时生成新的接口文档了,从而躲避了接口文档老旧不能应用的问题;通过 Swagger 页面,咱们能够间接进行接口调用,升高了我的项目开发阶段的调试老本。但应用 Swagger 的用户有以下几个痛点:测试不不便,有简略的调用测试,然而没有历史也没有鉴权等性能;没有人员治理,无奈合作/告诉/版本治理;对于前端人员不敌对,没有参数形容/值可能性,没有 Mock ;对代码有侵入性。但我这次强烈推荐的工具是能完满解决 Swagger 痛点的开源 API 管理工具,Postcat(现在在github上也有 3.4 k star) 作为代码的上游 API 文档工具,Postcat 解决痛点的同时交融 Swagger 生态。 Postcat 通过以下两种形式反对代码生成文档: 如果你之前应用 Swagger,咱们反对从 Swagger Url 主动同步 Swagger 数据;Jebrains IDE 插件,装置后能够在 IDE 中右键一键同步代码正文中的 API 文档信息到 Postcat。登录 Postcat 官网或者去 github 上找到我的项目,装置插件,体验一下~ 抉择通过 URL 导入同步 API 填写 Swagger URL 地址: 导入胜利,右侧展现了新增的 API ...

April 20, 2023 · 1 min · jiezi

关于swagger:除了-Swagger这个开源-API-管理工具生成文档更高效

提起 Swagger,常常接触接口开发的敌人,肯定晓得并且都纯熟应用了。 Swagger 是一个用于生成、形容和调用 RESTful 接口的 Web 服务。艰深的来讲,Swagger 就是将我的项目中所有(想要裸露的)接口展示在页面上,并且能够进行接口调用和测试的服务。 咱们不难看出 Swagger 有以下 3 个重要的作用: 将我的项目中所有的接口展示在页面上,这样后端程序员就不须要专门为前端使用者编写专门的接口文档;当接口更新之后,只须要批改代码中的 Swagger 形容就能够实时生成新的接口文档了,从而躲避了接口文档老旧不能应用的问题;通过 Swagger 页面,咱们能够间接进行接口调用,升高了我的项目开发阶段的调试老本。但应用 Swagger 的用户有以下几个痛点: 测试不不便,有简略的调用测试,然而没有历史也没有鉴权等性能;没有人员治理,无奈合作/告诉/版本治理;对于前端人员不敌对,没有参数形容/值可能性,没有 Mock ;对代码有侵入性。但我这次强烈推荐的工具是能完满解决 Swagger 痛点的开源 API 管理工具,Postcat(现在在github上也有 3.4k star) 作为代码的上游 API 文档工具,Postcat 解决痛点的同时交融 Swagger 生态。 Postcat 通过以下两种形式反对代码生成文档: 如果你之前应用 Swagger,咱们反对从 Swagger Url 主动同步 Swagger 数据;Jebrains IDE 插件,装置后能够在 IDE 中右键一键同步代码正文中的 API 文档信息到 Postcat。登录 Postcat 官网或者去 github 上找到我的项目,装置插件,体验一下~ 这个我的项目是开源的,如果你感觉这个我的项目还不错的话,无妨点个 Star 反对一下! Github :https://github.com/Postcatlab/postcat 理解 Postcat:Postcat 是一个弱小的开源、跨平台(Windows、Mac、Linux、Browsers...)的 API 开发测试工具,反对 REST、Websocket 等协定(行将反对 GraphQL、gRPC、TCP、UDP),帮忙你减速实现 API 开发和测试工作。 ...

April 19, 2023 · 1 min · jiezi

关于swagger:swaggerknife4j记录

1. pom.xml<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> </parent> <groupId>cn.itcast</groupId> <artifactId>knife4j_demo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies></project>2.application.ymlserver: port: 8081niewj: swagger: enabled: true #是否启用swagger base-package: com.niewj.controller# docket:# user:# title: 用户模块# base-package: com.niewj.controller.user# menu:# title: 菜单模块# base-package: com.niewj.controller.menu3. 配置读取属性类SwaggerPropertiespackage com.niewj.config;import lombok.*;import org.springframework.boot.context.properties.ConfigurationProperties;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;/**配置属性类,用于封装接口文档相干属性,从配置文件读取信息封装成以后对象*/@Data@ConfigurationProperties(prefix = "niewj.swagger")public class SwaggerProperties { private String title = "在线文档"; //题目 private String group = ""; //自定义组名 private String description = "在线文档"; //形容 private String version = "1.0"; //版本 private Contact contact = new Contact(); //联系人 private String basePackage = "com.niewj"; //swagger会解析的包门路 private List<String> basePath = new ArrayList<>(); //swagger会解析的url规定 private List<String> excludePath = new ArrayList<>();//在basePath根底上须要排除的url规定 private Map<String, DocketInfo> docket = new LinkedHashMap<>(); //分组文档 public String getGroup() { if (group == null || "".equals(group)) { return title; } return group; } @Data public static class DocketInfo { private String title = "在线文档"; //题目 private String group = ""; //自定义组名 private String description = "在线文档"; //形容 private String version = "1.0"; //版本 private Contact contact = new Contact(); //联系人 private String basePackage = ""; //swagger会解析的包门路 private List<String> basePath = new ArrayList<>(); //swagger会解析的url规定 private List<String> excludePath = new ArrayList<>();//在basePath根底上须要排除的url public String getGroup() { if (group == null || "".equals(group)) { return title; } return group; } } @Data public static class Contact { private String name = "niewj"; //联系人 private String url = ""; //联系人url private String email = ""; //联系人email }}4. SwaggerConfigpackage com.niewj.config;import com.google.common.base.Predicate;import com.google.common.base.Predicates;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.config.ConfigurableBeanFactory;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;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;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;@Configuration@ConditionalOnProperty(name = "niewj.swagger.enabled", havingValue = "true", matchIfMissing = true)@EnableSwagger2@EnableConfigurationProperties(SwaggerProperties.class)public class SwaggerConfig implements BeanFactoryAware { @Autowired SwaggerProperties swaggerProperties; private BeanFactory beanFactory; @Bean @ConditionalOnMissingBean public List<Docket> createRestApi() { ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory; List<Docket> docketList = new LinkedList<>(); // 没有分组 if (swaggerProperties.getDocket().isEmpty()) { Docket docket = createDocket(swaggerProperties); configurableBeanFactory.registerSingleton(swaggerProperties.getTitle(), docket); docketList.add(docket); return docketList; } // 分组创立 for (String groupName : swaggerProperties.getDocket().keySet()) { SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName); ApiInfo apiInfo = new ApiInfoBuilder() //页面题目 .title(docketInfo.getTitle()) //创建人 .contact(new Contact(docketInfo.getContact().getName(), docketInfo.getContact().getUrl(), docketInfo.getContact().getEmail())) //版本号 .version(docketInfo.getVersion()) //形容 .description(docketInfo.getDescription()) .build(); // base-path解决 // 当没有配置任何path的时候,解析/** if (docketInfo.getBasePath().isEmpty()) { docketInfo.getBasePath().add("/**"); } List<Predicate<String>> basePath = new ArrayList<>(); for (String path : docketInfo.getBasePath()) { basePath.add(PathSelectors.ant(path)); } // exclude-path解决 List<Predicate<String>> excludePath = new ArrayList<>(); for (String path : docketInfo.getExcludePath()) { excludePath.add(PathSelectors.ant(path)); } Docket docket = new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo) .groupName(docketInfo.getGroup()) .select() //为以后包门路 .apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage())) .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath))) .build(); configurableBeanFactory.registerSingleton(groupName, docket); docketList.add(docket); } return docketList; } //构建 api文档的详细信息 private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { return new ApiInfoBuilder() //页面题目 .title(swaggerProperties.getTitle()) //创建人 .contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail())) //版本号 .version(swaggerProperties.getVersion()) //形容 .description(swaggerProperties.getDescription()) .build(); } //创立接口文档对象 private Docket createDocket(SwaggerProperties swaggerProperties) { //API 根底信息 ApiInfo apiInfo = apiInfo(swaggerProperties); // base-path解决 // 当没有配置任何path的时候,解析/** if (swaggerProperties.getBasePath().isEmpty()) { swaggerProperties.getBasePath().add("/**"); } List<Predicate<String>> basePath = new ArrayList<>(); for (String path : swaggerProperties.getBasePath()) { basePath.add(PathSelectors.ant(path)); } // exclude-path解决 List<Predicate<String>> excludePath = new ArrayList<>(); for (String path : swaggerProperties.getExcludePath()) { excludePath.add(PathSelectors.ant(path)); } return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo) .groupName(swaggerProperties.getGroup()) .select() .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())) .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath))) .build(); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; }}5. 业务相干类5.1 返回后果格局封装Resultpackage com.niewj.common.response;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.util.ArrayList;/** * 返回后果格局封装 * * @author nieweijun * @since 2021/6/29 18:43 */@NoArgsConstructor@AllArgsConstructor@Data@ApiModel(description = "返回后果数据封装")public class Result<T> { @ApiModelProperty(value = "返回后果code码") private Integer code; @ApiModelProperty(value = "返回后果信息形容") private String msg; @ApiModelProperty(value = "返回数据胜利标识") private Boolean success; @ApiModelProperty(value = "返回数据详情") private T data; /** * 用枚举来结构 * * @param responseEnum 应用枚举值的code和msg填充Result * @param data 数据对象 * @param ifSuccess 是否申请胜利 */ public Result(ResponseEnum responseEnum, T data, Boolean ifSuccess) { this.setCode(responseEnum.getCode()); this.setMsg(responseEnum.getMsg()); this.setData(data); this.setSuccess(ifSuccess); } /** * success={"code":200,"msg":"胜利","data":"xxx","success":true} * * @param data * @return */ public static <T> Result<T> success(T data) { return new Result<>(ResponseEnum.SUCCESS.getCode(), ResponseEnum.SUCCESS.getMsg(), Boolean.TRUE, data); } /** * success={"code":200,"msg":"胜利","data": null,"success":true} * * @return */ public static <T> Result<T> successWithNull() { return new Result<>(ResponseEnum.SUCCESS.getCode(), ResponseEnum.SUCCESS.getMsg(), Boolean.TRUE, null); } /** * success={"code":200,"msg":"胜利","data": [],"success":true} * * @return */ public static <T> Result<T> successWithEmptyList() { return (Result<T>) Result.success(new ArrayList<T>()); } /** * success=除了返回true指定, 其余的都由参数指定 * * @param code * @param msg * @param data * @param <T> * @return */ public static <T> Result<T> success(Integer code, String msg, T data) { return new Result<>(code, msg, Boolean.TRUE, data); } /** * success等价于new Result(ResponseEnum, T, true) * * @param responseEnum * @param data * @param <T> * @return */ public static <T> Result<T> success(ResponseEnum responseEnum, T data) { return new Result<>(responseEnum, data, Boolean.TRUE); } /** * fail-除了返回false, 其余的参数指定 * 例如: {"code":xxx,"msg":"xxx", "data": "指定的谬误", "success":false} * * @param data * @param <T> * @return */ public static <T> Result<T> fail(Integer code, String msg, T data) { return new Result<>(code, msg, Boolean.FALSE, data); } /** * fail-除了返回false, 其余的参数指定-由枚举类指定 * 例如: {"code":xxx,"msg":"xxx", "data": "指定的谬误", "success":false} * * @param responseEnum * @param <T> * @return */ public static <T> Result<T> fail(ResponseEnum responseEnum, T data) { return new Result<>(responseEnum.getCode(), responseEnum.getMsg(), Boolean.FALSE, data); }}5.2 响应枚举package com.niewj.common.response;/** * 响应枚举:code和message的封装(留神: code申明为int不便比拟; Integer的话须要equals!) * * @author nieweijun * @since 2021/6/29 18:51 */public enum ResponseEnum { SUCCESS(200, "胜利"), REPEAT(201, "反复操作"), BAD_REQUEST(400, "申请参数不合规"), ERROR(500, "服务器异样"), RPC_ERROR(501, "RPC服务器异样"), //=========================业务编码========================= NO_LOGIN(1001, "未登录"), RISK(1002, "零碎忙碌"), RECODE_REPEAT(1003, "有反复数据"), DATA_LACK(1004, "申请数据缺失或超时"), NO_PERMISSION(1005, "用户无权限"), // ========================RPC服务问题======================== RPC_INVOKE_ERROR(2001, "依赖服务产生异样"), RPC_DATA_INVALID(2002, "依赖服务数据有效"), RPC_INVOKE_TIMEOUT(2003, "依赖服务申请超时"), UNDER_REVIEW(2004, "预计10分钟内审核结束,请稍后再从新进入小程序"), RPC_DISASSEMBLY_FAIL(2008, "提交旧机拆解失败"), OTHER(-1, "其余"); // 申明为简略类型是为了不便用==比拟; // 200 == Integer(200) ->true // 200 == 200 -> true // Integer(200) == Integer(200) -> false private int code; private String msg; ResponseEnum(int code, String msg) { this.code = code; this.msg = msg; } public String getMsg() { return msg; } public int getCode() { return code; } public static ResponseEnum getByCode(int code) { for (ResponseEnum responseCode : ResponseEnum.values()) { if (responseCode.getCode() == code) { return responseCode; } } return ERROR; }}5.3 model-1: Menupackage com.niewj.model;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@AllArgsConstructor@NoArgsConstructor@Data@ApiModel(description = "菜单实体")public class Menu { @ApiModelProperty(value = "主键") private int id; @ApiModelProperty(value = "菜单名称") private String name;}5.3 model-2: Userpackage com.niewj.model;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@AllArgsConstructor@NoArgsConstructor@Data@ApiModel(description = "用户实体")public class User { @ApiModelProperty(value = "主键") private int id; @ApiModelProperty(value = "姓名") private String name; @ApiModelProperty(value = "年龄") private int age; @ApiModelProperty(value = "地址") private String address;}5.4 MenuControllerpackage com.niewj.controller;import com.niewj.common.response.Result;import com.niewj.model.Menu;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 java.util.ArrayList;import java.util.List;@RestController@RequestMapping("/menu")@Api(tags = "菜单控制器")@Slf4jpublic class MenuController { @GetMapping("/getMenus") @ApiOperation(value = "查问所有菜单", notes = "查问所有菜单信息") public Result<List<Menu>> getMenus() { log.info("getMenus success!"); List<Menu> list = new ArrayList<>(); list.add(new Menu(100, "menu100")); list.add(new Menu(101, "menu101")); list.add(new Menu(102, "menu102")); return Result.success(list); } @PostMapping("/save") @ApiOperation(value = "新增菜单", notes = "新增菜单信息") public Result<Boolean> save(@RequestBody Menu menu) { log.info("save success!"); return Result.success(Boolean.TRUE); } @PutMapping("/update") @ApiOperation(value = "批改菜单", notes = "批改菜单信息") public Result<Boolean> update(@RequestBody Menu menu) { log.info("update success!"); return Result.success(Boolean.TRUE); } @DeleteMapping("/delete") @ApiOperation(value = "删除菜单", notes = "删除菜单信息") public Result<Boolean> delete(int id) { log.info("update success!"); return Result.success(Boolean.TRUE); } @ApiImplicitParams({ @ApiImplicitParam(name = "pageNum", value = "页码", required = true, type = "Integer"), @ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, type = "Integer"), }) @ApiOperation(value = "分页查问菜单信息") @GetMapping(value = "page/{pageNum}/{pageSize}") public String findByPage(@PathVariable Integer pageNum, @PathVariable Integer pageSize) { List<Menu> list = new ArrayList<>(); list.add(new Menu(100, "menu100")); list.add(new Menu(101, "menu101")); list.add(new Menu(102, "menu102")); return "OK"; }}5.5 UserControllerpackage com.niewj.controller;import com.niewj.common.response.Result;import com.niewj.model.User;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import org.springframework.web.bind.annotation.*;import java.util.ArrayList;import java.util.List;@RestController@RequestMapping("/user")@Api(tags = "用户控制器")public class UserController { @GetMapping("/getUsers") @ApiOperation(value = "查问所有用户", notes = "查问所有用户信息") public Result<List<User>> getAllUsers() { List<User> list = new ArrayList<>(); list.add(new User(100, "小0", 20, "北京")); list.add(new User(101, "小1", 30, "北京")); list.add(new User(102, "小2", 23, "西安")); return Result.success(list); } @PostMapping("/save") @ApiOperation(value = "新增用户", notes = "新增用户信息") public Result<Boolean> save(@RequestBody User user) { return Result.success(Boolean.TRUE); } @PutMapping("/update") @ApiOperation(value = "批改用户", notes = "批改用户信息") public Result<Boolean> update(@RequestBody User user) { return Result.success(Boolean.TRUE); } @DeleteMapping("/delete") @ApiOperation(value = "删除用户", notes = "删除用户信息") public Result<Boolean> delete(int id) { return Result.success(Boolean.TRUE); } @ApiImplicitParams({ @ApiImplicitParam(name = "pageNum", value = "页码", required = true, type = "Integer"), @ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, type = "Integer"), }) @ApiOperation(value = "分页查问用户信息") @GetMapping(value = "page/{pageNum}/{pageSize}") public Result<List<User>> findByPage(@PathVariable Integer pageNum, @PathVariable Integer pageSize) { List<User> list = new ArrayList<>(); list.add(new User(100, "小0", 20, "北京")); list.add(new User(101, "小1", 30, "北京")); list.add(new User(102, "小2", 23, "西安")); return Result.success(list); }}5.6 启动类package com.niewj;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import springfox.documentation.swagger2.annotations.EnableSwagger2;@SpringBootApplicationpublic class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}5.7 启动后拜访拜访地址: http://localhost:8081/doc.html即可 ...

December 22, 2022 · 7 min · jiezi

关于swagger:goswagger在windows系统上使用yaml生成server代码

1.环境配置 下载这个 https://github.com/go-swagger/go-swagger/releases/download/v0.29.0/swagger_windows_amd64.exe2.解压进去当前 放到 Go的装置根目录 $GOROOT/bin3.写yaml文件 规定参考这个https://www.it610.com/article...4.swagger generate server -f pkg/swagger/swagger.yaml -t ./pkg -A servername swagger: "2.0"info: description: Model Factory Service version: 1.0.0 title: mf-serverhost: gateway.mlss.mfbasePath: /schemes: - httpconsumes: - application/json - application/octet-stream - text/plain; charset=utf-8produces: - application/json - application/octet-stream - text/plain; charset=utf-8paths: /mf/v1/services: get: summary: 服务列表接口。 description: (v1.20.0) Get Services list. tags: - modelDeploy operationId: listServices. parameters: - name: page in: query description: 分页参数,页码. required: false type: integer format: int - name: size in: query description: 分页参数,每页行数。 required: false type: integer format: int - name: service_name in: query required: false type: string description: 模型服务名称。 - name: service_global_id in: query required: false type: string description: 模型服务全局ID - name: department_id in: query required: false type: integer description: 模型归属用户组的部门ID。 - name: department_name in: query required: false type: string description: 模型归属用户组的部门名称。 - name: group_name in: query required: false type: string description: 模型用户组名称。 - name: group_id in: query required: false type: number format: int64 description: 模型用户组id。 - name: model_name in: query required: false type: string description: 模型服务关联的模型名称。 - name: version in: query required: false type: string description: 模型服务关联的模型版本号。 - name: idc in: query required: false type: string description: 模型服务容器实例的IDC。 - name: dcn in: query required: false type: string description: 模型服务容器实例的DCN。 - name: query_str in: query required: false type: string description: MLSS外部应用,含糊查问参数 - name: cluster in: query required: false type: string description: MLSS外部应用,集群参数 - name: namespace in: query required: false type: string description: MLSS外部应用,命名空间参数 responses: 200: description: OK schema: $ref: '#/definitions/ServicesGetResponse' 401: description: Unauthorized schema: $ref: '#/definitions/Error' 404: description: The Models cannot be found schema: $ref: '#/definitions/Error'5.就能生成代码了 ...

August 15, 2022 · 2 min · jiezi

关于swagger:不用Swagger那我用啥

@[toc]上周松哥写了一篇文章和小伙伴们分享 Swagger3 在 Spring Boot 中的用法,评论中有不少小伙伴举荐 Spring Doc,松哥趁着休息时间抽空看了下,这个货色的确不错,不存在和 Spring Boot 之间的兼容问题,于是就撸了这篇文章和小伙伴们分享。一起来看看这个好玩的文档生成工具吧! 1. OpenApi在正式学习 Spring Doc 之前,先给大家介绍一下 OpenAPI。 OpenApi 是一个业界的 API 文档规范,是一个标准,这个标准目前有两大实现,别离是: SpringFoxSpringDoc其中 SpringFox 其实也就是咱们之前所说的 Swagger,SpringDoc 则是咱们明天要说的内容。 OpenApi 就像 JDBC 一样,制订了各种各样的标准,而 Swagger 和 SpringDoc 则相似于各种各样的数据库驱动,是具体的实现。 所以可能很多小伙伴也发现了,Swagger 和 Spring Doc 有一些类似的中央,这就是因为他们都恪守了雷同的标准。 不过呢,Swagger 更新有点慢悠悠的,为了可能和新版的 Spring Boot 整合,还是 SpringDoc 更值得体验一把。 SpringDoc 反对: OpenAPI 3Spring-boot,全版本都反对。JSR-303 中提供的一些注解,例如 @NotNull、@Min、@Max 以及 @Size 等。Swagger-ui:SpringDoc 提供的接口 JSON 也能够通过 Swagger-ui 展现进去。OAuth 2...2. 引入 SpringDoc小伙伴们晓得,这种生成接口文档的工具,一般来说都是两方面的性能: 生成接口文档 JSON。渲染接口文档 JSON。所以,当咱们应用 SpringDoc 的时候,如果只是想要生成接口文档 JSON,那么只须要增加如下依赖即可: ...

July 28, 2022 · 4 min · jiezi

关于swagger:swagger2使用注意事项

1、@ApiModel 个别须要swagger辨认的实体,须要在实体类的class上增加注解 @ApiModel . 然而,应用的时候要留神(尤其是copy实体类的时候) apimpdel 的 value 能够不写,如果写了,留神不要反复. 不要反复!!! 2、idea中的JRebel插件 在swagger2中,因为它降级了Springfox根底组件,如果大家应用相似JRebel这类热加载插件的时候,会呈现类字段没有的状况,目前官网也没有方法解决springfox我的项目与JRebel插件的抵触,惟一的倡议是不必JRebel来看swagger. 如下图,其实我的object外面是有实体类的,JRebel启动,什么都看不到

April 29, 2022 · 1 min · jiezi

关于swagger:干掉丑陋的swagger堪称开发者的瑞士军刀

动态的Swagger们跟不上频繁变更的代码“为什么改了这个没通知我”,“理论性能和文档上说的不一样啊”。这些话大家做开发的想必耳朵都听出老茧了。真不是故意的,有时候工作比拟急,就先改了代码,想着当前再同步文档,而后就给忘了。我的项目更新又全靠社交软件告诉,人一多不免有一两个没及时沟通到的。的确给单干的小伙伴带来麻烦,但说实话开发也挺冤屈的。这些问题产生的次要起因是,以后大部分研发团队的工作流程是这样的: 这种模式带来的问题是: 1.Swagger,postman,MockJS只能实现软件研发流程中某个环节的性能,造成实现接口设计,文档编写,调试,测试验证等工作须要应用好几个工具; 2.更麻烦的是这些工具数据格式不互通,无奈相互导入,造成用Swagger定义和编写实现接口后,在Postman,MockJS,Jmeter等工具还要再去手动填写一遍能力开始工作,减少了无意义的工作量。 3.沟通老本总是被忽略不计,但实际上不仅占据了很大工夫,各种沟通不及时、沟通不到位还十分让人心累。 4.老板的需要来得急,老板的需要变得快,各种代码批改和变更难以及时告诉和同步到团队成员手中。 埋怨当然政治正确,但有啥用,该加的班还是要加。那么有什么方法能够解决这个问题吗? 有的。 换个工具。 低成本做长期主义的事件我为大家提供的解决方案是一款国内的生产力工具--Apifox。 作为一款研发全流程,接口全周期的生产力工具,这款软件真正实现了数据流的买通,在一个软件上就能实现接口设计--接口文档--接口调试--接口批改--接口mock--接口测试--接口自动化--接口迭代的工作流闭环; 后端,前端,测试各个角色既能各取所需,又能协同单干。 Apifox上的合作流程是这样的:后端在Apifox可视化接口设计界面上定义好我的项目各个接口及对应参数同时编写接口文档阐明前后端一起评审,批改欠缺接口并在同一界面棘手更新接口文档后端应用接口调试性能调试接口前端应用零配置高仿真mock性能对前端页面进行调试,无需手写mock规定后端应用代码生成性能间接生成接口代码测试在接口治理页面一键生成接口参数测试用例,并根据业务场景生成自动化测试用例,一键运行接口用例并生成接口测试报告并分享给相干人员。前后端 都开发完,前端从Mock 数据切换到正式数据,进行联调,因为应用同一个接口数据源,且遵循了接口标准,联调顺利因为bug修复或需要变更,接口产生了变动,后端批改提交后,前端和测试实时同步到了批改后的数据项目经理通过权限设置给研发,产品,测试,内部单干人员调配编辑,只读等各种操作权限,保护了我的项目平安项目经理通过各个接口的状态开发中,测试中,已公布来跟进我的项目的进度状况,把控项目风险。Apifox外围性能和界面是这样的: 36氪报道过,Apifox在Pre-A轮融资就失去了3000万元的融资。 资本市场如此看好这个产品的发展潜力,是因为在经济增速变缓的现阶段, 对企业来说,它能通过进步整体的单干效率来为企业节约老本; 对研发人员来说,能够缩小无意义的工作量和繁冗耗时的沟通老本,将工夫花在能晋升本身竞争力的中央。 Apifox>Swagger+Postman+mockJS+Jmeter,它在传统软件的根底上做了不少操作优化和团队协同提效的性能。 Apifox做的增速提效优化1.接口设计:从代码生成界面到可视化接口设计界面 Apifox 接口文档遵循 OpenApi 3.0 (原 Swagger)、JSON Schema 标准,可生成在线文档;零学习老本即可编写出合乎RESTful格调的接口文档,新人上手快;所见即所得,不易出错。 2.文档保护:从接口与文档拆散到接口与文档合并 当你接手旧我的项目时,发现接口是上周的,接口文档是商周的,上手新我的项目全靠老司机口口相传,心田大略是解体的吧。 接口与文档拆散经常导致保护艰难。Apifox的接口设计界面提供了Markdown格局的文档阐明区,批改完接口就如同commit代码时增加变更阐明般,自然而然地造成肌肉记忆。 3.数据复用:从各自为政到定义一次、屡次复用 接口数据复用:Swagger,Postman,MockJS,Jmeter等软件彼此之间数据不互通,数据格式不统一,接口导入十分耗时麻烦。 而Apifox能身兼多职,包揽上述软件性能,在Apifox中定义一次接口,能被后端间接用来调试,前端间接用来mock界面,测试间接执行接口自动化。 数据模型复用:可复用的数据结构,定义接口返回数据结构及申请参数数据结构(仅 JSON 和 XML 模式)时可间接援用。 4.同步更新,高效沟通:从沟通滞后到数据变更即时同步 以后团队成员之间同步我的项目信息数据,仍旧依附着社交软件,低效、不及时,也容易漏掉某些成员。 Apifox为此提供了同步性能,一旦接口数据有更新产生,就会即时同步更新并告诉到我的项目内所有成员。 5.零配置mock高仿真数据:从苦逼造数据到零配置mock实在数据 Apifox 依据接口定义里的数据结构、数据类型,主动生成 mock 规定。Apifox 内置智能 mock 规定库,依据字段名、字段数据类型,智能优化主动生成的 mock 规定。 用户还能够自定义规定库,满足各种个性化需要。反对应用 正则表达式、通配符 来匹配字段名自定义 mock 规定。 ...

April 14, 2022 · 1 min · jiezi

关于swagger:swagger生成文档在线工具

地址:https://tools.kalvinbg.cn/dev... 地址参考下图,F12 看数据里是这个构造的接口,粘过去生成就能够了 开源我的项目参考:https://gitee.com/abocode-sou...

March 4, 2022 · 1 min · jiezi

关于swagger:Swagger简介

由来无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端常常埋怨后端给的接口文档与理论状况不统一。后端又感觉编写及保护接口文档会消耗不少精力,常常来不及更新。其实无论是前端调用后端,还是后端调用后端,都冀望有一个好的接口文档。 简介Swagger 是一个标准且残缺的框架,用于生成、形容、调用和可视化 RESTful 格调的 Web 服务。Swagger 的指标是对 REST API 定义一个规范且和语言无关的接口,能够让人和计算机领有毋庸拜访源码、文档或网络流量监测就能够发现和了解服务的能力。当通过 Swagger 进行正确定义,用户能够了解近程服务并应用起码实现逻辑与近程服务进行交互。与为底层编程所实现的接口相似,Swagger 打消了调用服务时可能会有的猜想。后盾人员,无需关注Swagger形容文件和接口文档,有需要变更导致接口变动,间接写代码就好了。把调用层的代码做个批改,而后生成新的形容文件和接口文档后,给到前端即可。真正做到了一劳永逸。实现代码和接口文档的一致性流程 劣势反对 API 主动生成同步的在线文档:应用 Swagger 后能够间接通过代码生成文档,不再须要本人手动编写接口文档了,对程序员来说十分不便,能够节约写文档的工夫去学习新技术。提供 Web 页面在线测试 API:Swagger 生成的文档还反对在线测试。参数和格局都定好了,间接在界面上输出参数对应的值即可在线测试接口。

February 21, 2022 · 1 min · jiezi

关于swagger:Spring-Boot-集成-SpringDoc-Swagger-3

背景Spring boot 曾经更新到了 v2.6+,如果你还在应用Springfox提供swagger接口文档,你会遇到以下谬误: org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException ...Caused by: java.lang.NullPointerException: null at springfox.documentation.spring.web.WebMvcPatternsRequestConditionWrapper.getPatterns(WebMvcPatternsRequestConditionWrapper.java:56) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0] at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113) ~[springfox-core-3.0.0.jar:3.0.0]Springfox的更新速度太慢了,为了适配新版本Spring boot,将其替换为SpringDoc是个更优的抉择。 配置集成 SpringDoc 实现 swagger接口文档步骤1. pom中引入SpringDoc依赖 <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.5.12</version></dependency>步骤2. 增加配置类 // 示例配置类@Configurationpublic class OpenApiConfig { @Bean public OpenAPI initOpenAPI() { return new OpenAPI().info( new Info().title("My Project API").description("OpenAPI").version("v1.0") ); }}步骤1&2为swagger的失常配置,如果零碎有接口URL的安全检查,须要将以下接口配置为容许匿名拜访,以使swagger相干url能够拜访到。步骤3. 设置swagger相干的匿名url配置,使swagger不被拦挡, 如下: /swagger**/**/v3/**如果应用了diboot-IAM组件,相干配置示例如下: diboot.iam.anon-urls=/swagger**/**,/v3/**swagger3 相干注解阐明加在Controller类及办法上的注解 (@Tag & @Operation):import io.swagger.v3.oas.annotations.tags.Tag;import io.swagger.v3.oas.annotations.Operation;//...@Tag(name = "用户接口", description = "用户相干CRUD接口")public class UserController{ @Operation(summary = "获取用户列表数据") @GetMapping("/list") public JsonResult getViewObjectListMapping() throws Exception{ //... }}加在Entity/Model类及属性上的注解 (@Schema):import io.swagger.v3.oas.annotations.media.Schema;import java.io.Serializable;@Schema(name = "用户", description = "用户实体定义")public class User implements Serializable { private static final long serialVersionUID = 111222L; /** * 名称 */ @Schema(description = "名称", required = true, example = "张三") private String name;}swagger 接口文档拜访入口地址:swagger接口文档入口地址: /{contextPath}/swagger-ui.html示例成果如图: ...

November 23, 2021 · 1 min · jiezi

关于swagger:OpenAPITools-实践

OpenAPITools 能够根据 REST API 形容文件,主动生成服务端桩(Stub)代码、客户端 SDK 代码,及文档等。其是社区版的 Swagger ,差别可见:OpenAPI Generator vs Swagger Codegen。 本文将从零开始设计和编写 API 文件,并生成 Go Gin 服务端代码,与 Python SDK 代码。更多语言或框架,也是一样操作的。 疾速开始先相熟下工具,间接用官网 Docker 镜像生成 Petstore 样例的 Go SDK 代码: docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \-i https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml \-g go \-o /local/out/go生成代码在当前目录的 ./out/go 。 关上 Swagger Editor File > Import URL 查看 petstore.yaml API: 查看 openapi-generator-cli 用法: docker run --rm -it \-v "${PWD}:/local" \--entrypoint /bin/bash \openapitools/openapi-generator-cliln -s /usr/local/bin/docker-entrypoint.sh /usr/local/bin/openapi-generatoropenapi-generator helpopenapi-generator help generate入手实际设计 RESTful API关上 Swagger Editor 设计 API: ...

November 5, 2021 · 3 min · jiezi

关于swagger:swaggo基本使用

1.装置swag cli : go get -u github.com/swaggo/swag/cmd/swaggin-swagger 中间件: go get github.com/swaggo/gin-swaggerswagger 内置文件: go get github.com/swaggo/gin-swagger/swaggerFiles2.样例具体正文信息请参考 http://www.topgoer.com/%E5%85... package mainimport ( "github.com/gin-gonic/gin" _ "golangdemo/docs" "net/http")var swagHandler gin.HandlerFunc// @title xiayuedu backend api// @version 1.0// @description this is xiayuedu backend server// @termsOfService https://xiayuedu.com//// @contact.name xiayuedu.com// @contact.url https://xiayuedu.com// @contact.name www.xiayuedu.com//// @contact.email// @license.name Apache 2.0// @license.url https://xiayuedu.com// @host 127.0.0.1:8089// @BasePath /api/v1func main() { engine := gin.Default() if swagHandler != nil { engine.GET("/swagger/*any",swagHandler) } v1 := engine.Group("/api/v1") { v1.GET("/hello", HelloHandler) } engine.Run(":8089")}// @Summary hellohandler// @Description hellohandler// @Tags 测试// @Accept json// @Produce json// @Param name query string true "名字"// @Param age query string true "年龄"// @Success 200 {string} string "{"msg":""hello razeen"}"// @Failure 400 {string} string "{"msg":""who are you"}"// @Router /hello [get]func HelloHandler(ctx *gin.Context){ name := ctx.Query("name") age := ctx.Query("age") if name == "" { ctx.JSON(http.StatusBadRequest,gin.H{"message":"who are you"}) return } ctx.JSON(http.StatusOK,gin.H{"message":"hello " + name + " " + age})}执行命令 ...

August 3, 2021 · 1 min · jiezi

关于swagger:swagger

罕用注解:- @Api()用于类; 示意标识这个类是swagger的资源 - @ApiOperation()用于办法; 示意一个http申请的操作 - @ApiParam()用于办法,参数,字段阐明; 示意对参数的增加元数据(阐明或是否必填等) - @ApiModel()用于类 示意对类进行阐明,用于参数用实体类接管 - @ApiModelProperty()用于办法,字段 示意对model属性的阐明或者数据操作更改 - @ApiIgnore()用于类,办法,办法参数 示意这个办法或者类被疏忽 - @ApiImplicitParam() 用于办法 示意独自的申请参数 - @ApiImplicitParams() 用于办法,蕴含多个 @ApiImplicitParam查考文档https://blog.csdn.net/wyb8805...

July 12, 2021 · 1 min · jiezi

关于swagger:Swagger2启动出现Unable-to-scan-documentation-context-default解决方法

一、问题本地我的项目做了Swagger2的配置,在启动时报如下谬误: DocumentationPluginsBootstrapper : Unable to scan documentation context default测试的Controller文件: package com.quantsmart.controller;import com.quantsmart.model.R;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.Authorization;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;/** * @author: kaiyi * @Date 2021/5/21 13:57 */@RestController@Api(tags = "CoinCommon外面的测试接口")public class TestController { @GetMapping("/common/test") @ApiOperation(value = "测试方法", authorizations = {@Authorization("Authorization")}) @ApiImplicitParams({ @ApiImplicitParam(name = "param", value = "参数1", dataType = "String", paramType = "query", example = "paramValue"), @ApiImplicitParam(name = "param1", value = "参数2", dataType = "String", paramType = "query", example = "paramValue") }) public R<String> testMethod(String param, String param2){ return R.ok("ok,哈哈哈,测试哇"); }}Swagger2配置/config/swagger/SwaggerProperties.java ...

May 21, 2021 · 2 min · jiezi

关于swagger:Swagger异常定位纪实是用的不对还是Swagger本身设计问题

前言swagger ui是一个采纳注解驱动的接口文档工具,目前已反对规范的open api v3标准协定,所以不仅能够在java我的项目里应用,每个语言都有相应的open api实现。我的项目集成swagger后,能够生成导出open api v3格式化的元数据集,有了这个接口元数据,你能够在任何反对v3协定的ui上展现你的api信息。在前后端拆散的我的项目中,swagger ui的呈现,大大提高了前后端联调的效率。swagger ui在解析注解标注的元数据信息时,特地场景下会抛异样,而且抛的异样没有直观的有价值的异样信息,所以深刻的debug了一番,尽管最初问题解决很简略,然而过程十分波折。故将bug定位过程记录在此。 影响的Swagger版本:1.5.xSwagger core:https://github.com/swagger-api/swagger-coreOpenApi v3标准:https://github.com/OAI/versions/3.0.0.md异样信息这个异样只会在加载swagger-ui的页面时会抛出,每次刷新页面,获取一次api接口就会触发一次异样。 异样剖析@JsonProperty("x-example")public Object getExample() { if (example == null) { return null; } try { if (BaseIntegerProperty.TYPE.equals(type)) { return Long.valueOf(example); } else if (DecimalProperty.TYPE.equals(type)) { return Double.valueOf(example); } else if (BooleanProperty.TYPE.equals(type)) { if ("true".equalsIgnoreCase(example) || "false".equalsIgnoreCase(defaultValue)) { return Boolean.valueOf(example); } } } catch (NumberFormatException e) { LOGGER.warn(String.format("Illegal DefaultValue %s for parameter type %s", defaultValue, type), e); } return example;}如上是异样相干的代码。从异样信息表象来看,是一个强转导致的问题,代码试图将一个空的字符串转换成数值类型导致异样抛出。并且是getExample时抛出的异样,这里须要理解swagger ui的加载过程和基础架构能力间接定位。swagger中的example是为了在生成的api doc中,给出相干字段的调用示例,并在触发接口调用时,默认主动填充example的值。这里显然是哪个中央的example设置不合理导致的异样。那么,接下来要做的就是找到这个空字符串的原始代码。 ...

December 9, 2020 · 1 min · jiezi

关于swagger:swagger-简单使用

1.导入依赖 <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>3.0.0</version></dependency><!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>3.0.0</version></dependency><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version></dependency>2.创立配置类 @Configuration@EnableSwagger2public class SwaggerConf { @Bean public Docket petApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.tao.swagger.controller")) //指定提供接口所在的基包 .build(); } /** * 该套 API 阐明,蕴含作者、简介、版本、host、服务URL * @return */ private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("demo api 阐明") .contact(new Contact("allen","null","name@example.com")) .version("0.1") .termsOfServiceUrl("https://segmentfault.com") .description("demo api") .build(); }}留神配置类上的@EnableSwagger2注解3.编写测试controller @Api("hello controller 接口测试")@Controllerpublic class HelloController { @ApiOperation("hello 接口,返回hello success") @GetMapping("/hello") public String hello(){ return "hello success"; }}关上swagger页面http://localhost:8080/swagger-ui/index.html ...

November 5, 2020 · 1 min · jiezi

关于swagger:手把手教你AspNetCore-WebApiSwaggerApi文档

前言小明曾经实现“待办事项”的增删改查,并美滋滋向负责前端的小红介绍Api接口,小红很忙,临时没有工夫听小明介绍,心愿小明能给个Api文档。对于码农小明来说能不写文档就尽量不要写,不过这也难不倒小明,他晓得Swagger不仅能够主动生成Api文档,并还能够用Swagger进行接口测试。 Swagger是什么?Swagger用于形容 REST API。 它容许计算机和人员理解服务的性能,而无需间接拜访实现(源代码、网络拜访、文档)。 包装置右键单击“解决方案资源管理器” > “治理 NuGet 包”中的我的项目将“包源”设置为“nuget.org”确保启用“包含预发行版”选项在搜寻框中输出“Swashbuckle.AspNetCore”从“浏览”选项卡中抉择最新的“Swashbuckle.AspNetCore”包,而后单击“装置”增加Swagger生成器将Swagger生成器增加到 Startup.ConfigureServices 办法中的服务汇合中: services.AddSwaggerGen();配置Swagger中间件在 Startup.Configure 办法中,启用中间件为生成的 JSON 文档和 Swagger UI 提供服务: app.UseSwagger();app.UseSwaggerUI(c =>{ c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");});XML正文在“解决方案资源管理器”中右键单击该我的项目,而后抉择“编辑<project_name>.csproj” 。手动将PropertyGroup增加:<GenerateDocumentationFile>true</GenerateDocumentationFile>更改services.AddSwaggerGen();代码如下: services.AddSwaggerGen((c =>{ var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath);}));成果 小结目前为止,小明终于把API文档也搞定了,摸了摸润滑的脑袋,小明美滋滋把API地址给小红发去,心想这样小红必定很称心了吧,但对不能与小红面对面的交换接口也有一丝丝淡淡的悲观。

October 11, 2020 · 1 min · jiezi

关于swagger:SpringBoot写后端接口看这一篇就够了

摘要:本文演示如何构建起一个优良的后端接口体系,体系构建好了天然就有了标准,同时再构建新的后端接口也会非常轻松。一个后端接口大抵分为四个局部组成:接口地址(url)、接口申请形式(get、post等)、申请数据(request)、响应数据(response)。如何构建这几个局部每个公司要求都不同,没有什么“肯定是最好的”规范,但一个优良的后端接口和一个蹩脚的后端接口比照起来差别还是蛮大的,其中最重要的关键点就是看是否标准! 本文就一步一步演示如何构建起一个优良的后端接口体系,体系构建好了天然就有了标准,同时再构建新的后端接口也会非常轻松。 所需依赖包这里用的是SpringBoot配置我的项目,本文解说的重点是后端接口,所以只须要导入一个spring-boot-starter-web包就能够了: <!--web依赖包,web利用必备--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>本文还用了swagger来生成API文档,lombok来简化类,不过这两者不是必须的,可用可不必。 参数校验一个接口个别对参数(申请数据)都会进行平安校验,参数校验的重要性天然不用多说,那么如何对参数进行校验就有考究了。 业务层校验首先咱们来看一下最常见的做法,就是在业务层进行参数校验: public String addUser(User user) { if (user == null || user.getId() == null || user.getAccount() == null || user.getPassword() == null || user.getEmail() == null) { return "对象或者对象字段不能为空"; } if (StringUtils.isEmpty(user.getAccount()) || StringUtils.isEmpty(user.getPassword()) || StringUtils.isEmpty(user.getEmail())) { return "不能输出空字符串"; } if (user.getAccount().length() < 6 || user.getAccount().length() > 11) { return "账号长度必须是6-11个字符"; } if (user.getPassword().length() < 6 || user.getPassword().length() > 16) { return "明码长度必须是6-16个字符"; } if (!Pattern.matches("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$", user.getEmail())) { return "邮箱格局不正确"; } // 参数校验结束后这里就写上业务逻辑 return "success"; }这样做当然是没有什么错的,而且格局排版参差也高深莫测,不过这样太繁琐了,这还没有进行业务操作呢光是一个参数校验就曾经这么多行代码,切实不够优雅。 ...

September 15, 2020 · 3 min · jiezi

关于swagger:MOor使用Spring-Boot整合Swagger2

一、Swagger?1.1 什么是Swagger?官网说法:Swagger是一个标准和残缺的框架,用于生成、形容、调用和可视化 RESTful 格调的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的办法,参数和模型严密集成到服务器端的代码,容许API来始终保持同步1.2 什么是SpringFox?官网定义为: Automated JSON API documentation for API's built with Spring,是一个开源的API Doc的框架, 它的前身是swagger-springmvc,能够将咱们的Controller中的办法以文档的模式展示下文中须要导入的几个maven依赖就是通过SpringFox整合Swagger,以此来反对在Spring框架下进行应用1.3 Swagger2的作用这里指的Swagger2为,springfox-swagger2。通过这个依赖就可在spring中应用swagger的注解能够生成文档模式的api,提供给不同团队不便自测,不便领导查阅无需过多冗余的word文档或网页文档二、导入的maven依赖<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version></dependency><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version></dependency>三、自定义配置类@Configurationpublic class Swagger2Config { public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.im.controller"))//须要生成文档所在的包 .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("springboot应用swagger2构建api文档")//文档题目 .description("简略优雅的restful格调,http://blog.csdn.net/saytime")//形容 .termsOfServiceUrl("http://blog.csdn.net/saytime") .version("1.0") .build(); }}四、测试4.1 User实体类@ApiModel(value = "用户实体")@NoArgsConstructor@AllArgsConstructor@Getter@Setter@ToStringpublic class User { @JsonIgnore @ApiModelProperty(name = "用户车辆",dataType = "Car" ,notes = "用户车辆") private Car car; public User(Integer userId, String userName, String password, String email, String birthDate) { this.userId = userId; this.userName = userName; this.password = password; this.email = email; this.birthDate = birthDate; } @ApiModelProperty(name = "用户id", dataType = "Integer", notes = "用户id") private Integer userId; @ApiModelProperty(name = "用户名", dataType = "String", notes = "用户名") private String userName; @ApiModelProperty(name = "明码", dataType = "String", notes = "明码") private String password; @ApiModelProperty(name = "邮箱", dataType = "String", notes = "邮箱") private String email; @ApiModelProperty(name = "生日", dataType = "String", notes = "生日") private String birthDate;}PS:实体类中曾经用了@AllArgsConstructor,但还是写了一个带参结构器,是因为笔者自测时用了static{}动态代码块来初始化对象,static{}的优先级是高于注解的,所以若没有本人写带参结构器是无奈通过编译的4.2 UserController@RestController@RequestMapping("/user")@Api(value = "用户服务", description = "用户的基本操作")public class UserController { @ApiOperation(value = "用户列表服务", notes = "查詢所有用戶的列表信息") @RequestMapping(value = "/list", method = RequestMethod.GET) public List<User> list() { List<User> userList = new ArrayList<>(); for (String key : DataNode.users.keySet()) { userList.add(DataNode.users.get(key)); } return userList; } @ApiOperation(value ="依据用户ID查问用户信息",notes="依据url的id来获取用户详细信息") @ApiImplicitParam(name="userId",value = "用户ID",required = true,dataType ="Integer",paramType = "path") @RequestMapping(value = "/findOneById/{userId}",method = RequestMethod.GET) public User findOneById(@PathVariable("userId") Integer userId) { for(String key: DataNode.users.keySet()) { User user = DataNode.users.get(key); if(user.getUserId().equals(userId)) { return user; } } return null; } @ApiOperation(value = "依据用户名获取用户信息") @RequestMapping(value = "/findOneUserName/{userName}",method = RequestMethod.GET) @ApiImplicitParam(name = "userName",value = "用户名",required = true,dataType = "String",paramType = "path") public User findOneByName( @PathVariable("userName") String userName) { for(String key: DataNode.users.keySet()) { User user = DataNode.users.get(key); if(userName.equals(user.getUserName())) { return user; } } return null; } @ApiOperation(value = "依据用户名获取用户信息") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "int", paramType = "query"), @ApiImplicitParam(name = "userName", value = "用户名称", required = true, dataType = "String", paramType = "query") }) @RequestMapping(value = "/findOneByIdAndName",method = RequestMethod.GET) public User findOneByIdAndName(@RequestParam String userName, @RequestParam Integer id) { for(String key: DataNode.users.keySet()) { User user = DataNode.users.get(key); if(user.getUserName().equals(userName) && id.equals(user.getUserId())) { return user; } } return null; } @ApiOperation(value = "依据查问条件获取用户信息") @RequestMapping(value = "/findOneByCondition",method = RequestMethod.GET) public User findOneByCondition(UserCondition userCondition) { for(String key: DataNode.users.keySet()) { User user = DataNode.users.get(key); if(user.getUserName().equals(userCondition.getUserName()) && user.getUserId().equals(userCondition.getUserId())) { Car car = new Car(); car.setName("奥迪"); user.setCar(car); return user; } } return null; }}4.3 测试样列 ...

August 10, 2020 · 2 min · jiezi

Spring-Boot-十五-优雅的使用-API-文档工具-Swagger2

1. 引言各位在开发的过程中肯定遇到过被接口文档折磨的经历,由于 RESTful 接口的轻量化以及低耦合性,我们在修改接口后文档更新不及时,导致接口的调用方(无论是前端还是后端)经常抱怨接口与文档不一致。程序员的特点是特别不喜欢写文档,但是又同时特别不喜欢别人不写文档。所以 API 文档工具这时就应运而生了,本篇文章我们将会介绍 API 文档工具 Swagger2 。 2. 快速上手既然 Swagger2 是一个 API 文档工具,我们就在代码中看一下这个文档工具在 Spring Boot 中是如何使用的吧。 2.1 引入依赖代码清单:spring-boot-swagger/pom.xml <!-- swagger工具包 --><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version></dependency><!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version></dependency>这里选用的版本是 2.9.2 ,同时也是目前最新的一个版本。 2.2 配置类 SwaggerConfig代码清单:spring-boot-swagger/src/main/java/com/springboot/springbootswagger/config/SwaggerConfig.java @Configuration@EnableSwagger2public class SwaggerConfig { @Value("${swagger.show}") private boolean swaggerShow; @Bean public Docket swaggerSpringMvcPlugin() { return new Docket(DocumentationType.SWAGGER_2) .enable(swaggerShow) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.springboot.springbootswagger")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Swagger2 演示接口RESTful APIs") .version("1.0") .build(); }}由于 Swagger 是一个 API 文档工具,我们肯定不能在生产环境中开启,所以笔者这里在配置中增加了 swagger.show ,在不同环境的配置文件中配置不同的值,或者如果有配置中心,这个配置可以添加到配置中心中,笔者这里示例简单起见就添加在 application 配置文件中了。这样,我们就可以优雅的开启或者关闭 Swagger 的功能。 ...

October 17, 2019 · 2 min · jiezi

前后端分离mock-server方案2-swagger-editor整合

如果想最小的编写配置文件进行mock,

July 2, 2019 · 1 min · jiezi

Gradle环境下导出Swagger为PDF

更多精彩博文,欢迎访问我的个人博客 说明我个人是一直使用Swagger作为接口文档的说明的。但是由于在一些情况下,接口文档说明需要以文件的形式交付出去,如果再重新写一份文档难免有些麻烦。于是在网上看到了Swagger2Markup + asciidoctor导出PDF的方法,百度一番后感觉网上的文章还是有很多没有描述清楚的地方,遂还是硬着头皮把官方的英文文档大致浏览了一下,按照自己的思路整理出具体的步骤。 本文用到的工具: Gradle - 4.10.3SpringBoot - 2.1.6.RELEASESwagger - 2.9.2Swagger2Markup - 1.3.3asciidoctorspring-restdocs-mockmvc准备Swagger数据SpringBoot中使用Swagger的过程就不再赘述了,下面是本文使用的范例: @Configuration@EnableSwagger2class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.jptangchina.gradle.controller")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Swagger2Markup Test Api") .version("1.0") .build(); }}@RestController@RequestMapping("/user")@Api(tags = "用户接口")public class UserController { @ApiOperation("用户登录") @ResponseBody @PostMapping("/login") public Result<Void> login( @ApiParam(value = "用户名", example = "jptangchina", required = true) @RequestParam String username, @ApiParam(value = "密码", example = "jptangchina", required = true) @RequestParam String password) { return Result.ok(); }}使用org.asciidoctor.convert生成PDF(个人不推荐使用)官方教程地址:https://github.com/Swagger2Ma...仅为了简单的导出PDF而言,本文针对官方案例均有所改动,去掉了部分没有用到的配置。 ...

June 25, 2019 · 3 min · jiezi

前后端分离ssm配置swagger接口文档

之前配置过springboot,相比ssm要简单很多,现在记录一下ssm的配置 在pom.xml中加入依赖<!--swagger本身不支持spring mvc的,springfox把swagger包装了一下,让他可以支持springmvc--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version> </dependency>添加配置类SwaggerConfig.java@WebAppConfiguration@EnableSwagger2@EnableWebMvc@ComponentScan(basePackages = "com.maxcore.controller")public class SwaggerConfig { @Bean public Docket customDocket() { // return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { Contact contact = new Contact("娜", "https://www.baidu.me", "baidu_666@icloud.com"); return new ApiInfo("仿简书前台API接口",//大标题 title "Swagger测试demo",//小标题 "0.0.1",//版本 "www.baidu.com",//termsOfServiceUrl contact,//作者 "Blog",//链接显示文字 "https://www.baidu.me"//网站链接 ); }}在dispatcher-servlet.xml(springmvc的配置文件)中加入如下配置 <bean class="com.maxcore.config.SwaggerConfig" /> <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" /> <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/" />要在controller层添加注解 最后启动项目,访问swagger接口文档的路径一定要对,不然一直报404,你以为你没配置对,其实是你路径不对,笔者在这里表示有很痛的领悟笔者的本地的访问路径是 http://localhost/jianShuSSM_w... 一般都是http://ip地址:端口(默认80,不显示)/项目名/swagger-ui.html ...

June 22, 2019 · 1 min · jiezi

从0手写springCloud项目二-框架代码详解

写在前面前面一篇将springCloud所需的几个组件搭建起来了,接下来以user模块为例子主要记录一下项目中集成的技术,框架,和使用方式。我想从以下几个地方总结: mybatis-plus3lcn5.0.2liquibaseoauth2others(es,rabbitmq,全局异常处理,feign之间异常处理,logback,mysql,redis)集成mybatis-plus3可能有些同学常用的持久层框架是jpa,但是就我实践而言,mybatisplus好用的不是一丁点,个人建议用mybatisplus...现在plus3的版本支持的还是蛮多的:乐观锁,版本号,代码生成器,分页插件,热加载,通用枚举,自动填充,动态数据源....详见官网(https://mp.baomidou.com),而且3.0集成也比2.x简单了不少,最简单的只需要加一个pom坐标即可,但是如果需要个性化配置,我们还是要写config,当然也不麻烦,很简单的。 pom <!--mybatis-plus--><dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.0</version></dependency>yml //可以看到我的各个文件存放的路径分别在哪里 mybatis: type-aliases-package: cn.iamcrawler.crawler_common.domain.goddess mapper-locations: cn/iamcrawler/crawlergoddess/mapper/*Mapper.xml type-handlers-package: cn.iamcrawler.crawlergoddess.mapper.typehandler global-config: refresh-mapper: true 那么接下来继承plus的两个方法就可以了 /** * Created by liuliang on 2019/3/21. */public interface DataUserMapper extends BaseMapper<DataUser> {}@Service@Slf4jpublic class DataUserService extends ServiceImpl<DataUserMapper,DataUser>{}ps:大家可以想一想,spring的controller,service,mapper需要使用注解将其标识为bean才能扫描得到,而这里的mapper却没有添加@Repository注解,这是因为我在注解类上加了一个注解,指定spring启动的时候扫描到这个包下,所以这里就可以不用添加@Repository注解,也可以被spring扫描到啦。主类的注解如下: @SpringBootApplication@EnableEurekaClient@EnableFeignClients@EnableTransactionManagerServer@MapperScan("cn.iamcrawler.crawlergoddess.mapper")//上面说的,就是这个注解!public class CrawlerGoddessApplication { public static void main(String[] args) { SpringApplication.run(CrawlerGoddessApplication.class, args); }}是的,就是这么简单。plus最简单的集成就完成了,接下来继承mapper接口,service接口就可以写sql了。具体详见mybatis-plus官网。 ps:最后还有一个小知识点,其实大家可以看到,我的xml是放在和mapper一起的(默认是放在resource下面,打包成jar的时候路径就是我们常说的classpath),而我们知道,在maven打包jar的时候,是不会扫描这个java下的.xml文件的,为什么我打包jar也可以扫描呢?是因为我在maven里面配置了一个将java下的xml也打包的程序,如下: <build> <finalName>crawler-goddess</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <!---我上面说的就是下面这个配置哦--> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> </build>集成lcn5.0.2微服务集成分布式事务框架已经不是一个新鲜的事情,在这方面,我前面也写过好几个文章介绍过,其中有springboot1.5.9+lcn4.1.0( https://segmentfault.com/a/11... ), 有springboot2.1.3+lcn5.0.2( https://segmentfault.com/a/11... )。大家可以按需阅读并配置,当然这里我这个demo配置的是5.0.2版本.毕竟这个版本比4.1.0强大了不少,并且配置也更加方便。具体大家也可以参照lcn官网,描述的非常详细(http://www.txlcn.org) ...

June 18, 2019 · 1 min · jiezi

Wizard-开源文档管理系统10发布啦

Wizard 是一款开源文档管理系统,项目地址为 https://github.com/mylxsw/wizard。这个项目是 我 在2017年就开始开发的,起初只是想做一款能够在公司内部把Swagger文档管理起来的工具,但在这近两年的时间里,一直断断续续的为其添加各种功能,现在终于下决心发布1.0版本了,目前支持三种类型的文档管理 Markdown:也是Wizard最主要的文档类型,研发团队日常工作中交流所采用的最常用文档类型,在 Wizard 中,对 Editor.md 项目进行了功能扩展,增加了文档模板,Json 转表格,图片粘贴上传等功能 Swagger:支持 OpenAPI 3.0 规范,嵌入了 Swagger 官方的编辑器,通过定制开发,使其融入到 Wizard 项目当中,支持文档模板,全屏编辑,文档自动同步功能 Table:这种文档类型是类似于 Excel 电子表格,采用了 x-spreadsheet 项目,将该项目嵌入到了 Wizard 中,目前还不是很完善 目前主要包含以下功能 Swagger,Markdown,Table 类型的文档管理文档修改历史管理文档修改差异对比用户权限管理项目分组管理LDAP 统一身份认证文档搜索,标签搜索阅读模式文档评论消息通知文档分享统计功能如果想快速体验一下Wizard的功能,有两种方式 在线体验请访问 http://wizard.aicode.cc/ ,目前只提供部分功能的体验,功能预览和使用说明请参考 Wiki。使用Docker来创建一个完整的Wizard服务进入项目的根目录,执行 docker-compose up,就可以快速创建一个Wizard服务了,访问地址 http://localhost:8080 。 起源为了鼓励大家写开发文档,最开始我们选择了 ShowDoc 项目来作为文档管理工具,当时团队规模也非常的小,大家都是直接用 Markdown 写一些简单的开发文档。后来随着团队的壮大,前后端分离,团队分工的细化,仅仅采用 Markdown 开始变得捉襟见肘,这时候,我们首先想到了使用开源界比较流行的 Swagger 来创建开发文档。但是 Swagger 文档多了,总得有个地方维护起来吧? 项目中的文档仅仅用Swagger也是不够的,它只适应于API文档的管理,还有很多其它文档,比如设计文档,流程图,架构文档,技术方案,数据库变更等各种文档需要一起维护起来。因此,我决定利用业余时间开发一款 支持 Markdown 和 Swagger 的文档管理工具,也就是 Wizard 项目了。 起初打算用 Go 语言来开发,但是没过几天发现使用 Golang 来做 Web 项目开发效率太低(快速开发效率,并非指性能,Golang做API接口开发还是很不错的),很多常用的功能都需要自己去实现,遂放弃使用 Golang,转而使用 PHP 的 Laravel 框架来开发。所以虽然项目创建的时间为 2017年7月27日,但是实际上真正开始的时间应该算是 2017年7月31日。 ...

May 6, 2019 · 1 min · jiezi

SpringBoot结合swagger2快速生成简单的接口文档

1. pom.xml中加入依赖 <dependency> <groupId>com.spring4all</groupId> <artifactId>swagger-spring-boot-starter</artifactId> <version>1.8.0.RELEASE</version> </dependency>2. 在启动类(即带@SpringBootApplication这个注解的类)上添加@EnableSwagger2Doc注解3. 在application.properties中配置如下swagger.enabled=trueswagger.title=spring-boot-mybatis module apiswagger.description=Starter for swagger 2.xswagger.license=Apache License, Version 2.0swagger.licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.htmlswagger.termsOfServiceUrl=https://github.com/pbw123/spring-boot-demoswagger.contact.name=mqXuswagger.contact.url=https://www.jianshu.com/u/2f60beddf923swagger.contact.email=2635225112@qq.comswagger.base-package=com.springboot.mybatis.controllerswagger.base-path=/**swagger.exclude-path=/error, /ops/**经我多次尝试application.properties中不加任何swagger配置也可生成文档进行正常测试 另一种用swagger自动生成文档的方式请前往个人网站

May 5, 2019 · 1 min · jiezi

spring boot 集成swagger并且使用拦截器的配置问题

最近同事问我,spring boot集成了swagger,但是在使用拦截器的时候遇到了问题,页面无法访问。经过研究解决了这个问题。配置问题解决集成swagger就不啰嗦了,网上到处都是,直接看配置。同事从网上找到的配置:import com.xxx.xxxx.xxx.xxx.LoginInterceptor;import com.fasterxml.classmate.TypeResolver;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.ResponseEntity;import org.springframework.web.context.request.async.DeferredResult;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.schema.WildcardType;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;import java.util.Collections;import static springfox.documentation.schema.AlternateTypeRules.newRule;@Configuration@EnableSwagger2public class Swagger2Config extends WebMvcConfigurationSupport { @Autowired private TypeResolver typeResolver; @Bean public Docket productApi() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(“com.xxx.xxx.controller”)) .paths(PathSelectors.any()) .build() .apiInfo(metaData()) .alternateTypeRules( //自定义规则,如果遇到DeferredResult,则把泛型类转成json newRule(typeResolver.resolve(DeferredResult.class, typeResolver.resolve(ResponseEntity.class, WildcardType.class)), typeResolver.resolve(WildcardType.class))) ; } private ApiInfo metaData() { return new ApiInfoBuilder() .title(“通用服务 APIs”) /.description(""REST API for Online Store"")/ .version(“1.0.0”) /* .license(“Apache License Version 2.0”) .licenseUrl(“https://www.apache.org/licenses/LICENSE-2.0"”)/ .contact(new Contact(“易保科技”, “”, “mail@mail”)) .build(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(“swagger-ui.html”) .addResourceLocations(“classpath:/META-INF/resources/”); registry.addResourceHandler("/webjars/") .addResourceLocations(“classpath:/META-INF/resources/webjars/”); super.addResourceHandlers(registry); }}这是他从网上找到的拦截器的配置:@Configurationpublic class WebMvcConfig extends WebMvcConfigurationSupport { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) // addPathPatterns 用于添加拦截规则 , 先把所有路径都加入拦截, 再一个个排除 .addPathPatterns("/") .excludePathPatterns(Collections.singletonList("/swagger-ui.html")); super.addInterceptors(registry); }}现在的测试结果就是,打开http://host:port/path/swagger-ui.html,就是一个空白页面,无法使用,现在要解决的就是这个问题。打开谷歌浏览器的调试控制台,查看network,如图:可以明显看出,页面加载数据的时候,并没有报什么错误,只是加载的资源都被拦截器拦截了,无法加载资源,可想而知,资源都被拦截器拦截了。我分析了一下,加载资源的路径,修改了一下拦截器资源配置: @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) // addPathPatterns 用于添加拦截规则 , 先把所有路径都加入拦截, 再一个个排除 .addPathPatterns("/") .excludePathPatterns("/swagger-ui.html") .excludePathPatterns("/swagger-resources/") .excludePathPatterns("/error") .excludePathPatterns("/webjars/"); }另外两个类实际是同一个作用,所以合并两个类:@Configuration@EnableSwagger2public class TestMVCConfig extends WebMvcConfigurationSupport { @Resource private TypeResolver typeResolver; @Resource private LoginInterceptor loginInterceptor; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(“swagger-ui.html”) .addResourceLocations(“classpath:/META-INF/resources/”); registry.addResourceHandler("/webjars/") .addResourceLocations(“classpath:/META-INF/resources/webjars/”); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) // addPathPatterns 用于添加拦截规则 , 先把所有路径都加入拦截, 再一个个排除 .addPathPatterns("/") .excludePathPatterns("/swagger-ui.html") .excludePathPatterns("/swagger-resources/") .excludePathPatterns("/error") .excludePathPatterns("/webjars/**"); } @Bean public Docket productApi() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(“com.xxx.xxx.controller”)) .paths(PathSelectors.any()) .build() .apiInfo(metaData()) .alternateTypeRules( //自定义规则,如果遇到DeferredResult,则把泛型类转成json newRule(typeResolver.resolve(DeferredResult.class, typeResolver.resolve(ResponseEntity.class, WildcardType.class)), typeResolver.resolve(WildcardType.class))) ; } private ApiInfo metaData() { return new ApiInfoBuilder() .title(“通用服务 APIs”) /.description(""REST API for Online Store"")/ .version(“1.0.0”) / .license(“Apache License Version 2.0”) .licenseUrl(“https://www.apache.org/licenses/LICENSE-2.0"”)/ .contact(new Contact(“易保科技”, “”, “mail@mail”)) .build(); }}这样就没有问题了。另外的解决方案网上还有另外一种说法,可以实现WebMvcConfigurer接口,代码如下:@Configuration@EnableWebMvc@EnableSwagger2public class WebMVCConfig implements WebMvcConfigurer{ @Resource private TypeResolver typeResolver; @Resource private LoginInterceptor loginInterceptor; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(“swagger-ui.html”) .addResourceLocations(“classpath:/META-INF/resources/”); registry.addResourceHandler("/webjars/") .addResourceLocations(“classpath:/META-INF/resources/webjars/”); } @Override public void addInterceptors(InterceptorRegistry registry) { List<String> excludePathPatterns = new ArrayList<>(); excludePathPatterns.add("/swagger-ui.html"); excludePathPatterns.add("/swagger-resources/"); excludePathPatterns.add("/error"); excludePathPatterns.add("/webjars/"); // addPathPatterns 用于添加拦截规则 , 先把所有路径都加入拦截, 再一个个排除 registry.addInterceptor(loginInterceptor) .addPathPatterns("/") .excludePathPatterns(excludePathPatterns); } @Bean public Docket productApi() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(“com.xx.sss.controller”)) .paths(PathSelectors.any()) .build() .apiInfo(metaData()) .alternateTypeRules( //自定义规则,如果遇到DeferredResult,则把泛型类转成json newRule(typeResolver.resolve(DeferredResult.class, typeResolver.resolve(ResponseEntity.class, WildcardType.class)), typeResolver.resolve(WildcardType.class))) ; } private ApiInfo metaData() { return new ApiInfoBuilder() .title(“通用服务 APIs”) /.description(""REST API for Online Store"")/ .version(“1.0.0”) / .license(“Apache License Version 2.0”) .licenseUrl(“https://www.apache.org/licenses/LICENSE-2.0"”)*/ .contact(new Contact(“易保科技”, “”, “mail@mail”)) .build(); }}但是这种配置想要生效,必须加@EnableWebMvc注解,不然不起作用。为什么?官方源码注释:/** * Defines callback methods to customize the Java-based configuration for * Spring MVC enabled via {@code @EnableWebMvc}. * * <p>{@code @EnableWebMvc}-annotated configuration classes may implement * this interface to be called back and given a chance to customize the * default configuration. *通过@enableWebMVC启用Spring MVC,自定义基于Java config 定义回调方法。@EnableWebMVC带注释的配置类可以实现这个接口自定义默认配置。当然如果你觉得自己的配置没问题,但是仍然不起作用,这时候改怎么办?请按照一下步骤debug:1、找到InterceptorRegistration类;2、找到addInterceptor方法和excludePathPatterns方法,打上断点;3、debug模式启动项目;如果没有进入断点,那就说明你的配置根本没有起到作用,看看注解是否没写。如果进入了断点,就要看看断点处传进来的参数是否是你配置的参数,不是那就是有问题,这时候再根据参数查找问题。这样基本就能解决问题了。总结网上很多东西都是抄来抄去,也不知道有没有验证,让很多人摸不着头脑。 ...

April 18, 2019 · 2 min · jiezi

SpringBoot + Swagger + ReDoc 笔记

前言在开始使用 Swagger 之前,我们先来了解下几个概念。名词释义SwaggerSwagger 是一个 RESTful 接口规范,现在流行的版本有 2.0 和 3.0 。OpenAPIOpenAPI 规范就是之前的 Swagger 规范,只是换了个名字。swagger.json/swagger.yamlswagger.json 或 swagger.yaml 是符合 Swagger 规范的接口描述文件。文件名称随意,这里只是举例。SpringfoxSpringfox 套件可以为 Spring 系列项目自动生成 swagger.json,还可以集成 Swagger UI。Swagger UISwagger UI 通过解析 swagger.[json/yaml],来生成在线接口文档。ReDocReDoc 是另一个 Swagger UI 工具。SpringfoxSpringfox 当前有两个主要版本:正式版 2.9.2 和 快照版 3.0.0-SNAPSHOT。建议读者先试用正式版。Maven 依赖(2.9.2)<properties> <springfox.version>2.9.2</springfox.version></properties><dependencies> <!– 生成 Swagger 文档 –> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${springfox.version}</version> </dependency> <!– 添加 Springfox Swagger UI 支持 –> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${springfox.version}</version> </dependency></dependencies>Maven 依赖(3.0.0-SNAPSHOT)编写 Swagger 配置类在 SpringBoot 启动类同级目录下添加该配置类。配置类 SwaggerConfig 上添加 @Configuration 注解,是为了让 Spring 识别到这是一个配置类。package org.qadoc.wiremock.web;import com.google.common.base.Predicates;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;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 java.util.ArrayList;/** * Swagger 配置类 <br> * 创建时间:2019/4/10 15:35<br> * @author 李云 /@Configurationpublic class SwaggerConfig { @Bean public Docket mocklabAPI(){ return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) //.apis(not(withClassAnnotation(CustomIgnore.class))) .paths(Predicates.not(PathSelectors.regex("/error."))) //不展示 Spring 自带的 error Controller .build() //.pathMapping("/") //.directModelSubstitute(LocalDate.class,String.class) //.genericModelSubstitutes(ResponseEntity.class) .useDefaultResponseMessages(false) //.tags(new Tag(“tagName”,“description”)) .apiInfo(apiInfo()) ; } private ApiInfo apiInfo(){ Contact contact = new Contact("","",""); return new ApiInfo( “MockLab API 文档”, “MockLab API 文档(Web端)”, “1.0.0”, “”, contact, “”, “”, new ArrayList<>() ); }}启用 Swagger在 SpringBoot 的启动类上添加 @EnableSwagger2 注解。package org.qadoc.wiremock.web;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import springfox.documentation.swagger2.annotations.EnableSwagger2;@SpringBootApplication@EnableSwagger2public class MockLabWebApplication { public static void main(String[] args) { SpringApplication.run(MockLabWebApplication.class, args); }}Swagger 文档注解Swagger 的文档注解有三类:resource(Controller 类) 注解operation(API 方法)注解API models(实体类)注解注解概览注解描述@Api标记一个类为 Swagger 资源。@ApiImplicitParam表示 API Operation 中的单个参数。@ApiImplicitParams包装注解,包含多个 @ApiImplicitParam 注解@ApiModel提供 Swagger models 的附加信息@ApiModelProperty添加和操作 model 属性的数据。@ApiOperation描述一个特定路径的 operation(通常是 HTTP 方法)@ApiParam为 operation 参数添加额外的 meta-data。@ApiResponse描述 operation 可能的响应。@ApiResponses包装注解,包含多个 @ApiResponse 注解。@ResponseHeader表示响应头。Resource API 声明@Api声明该 API 接口类需要生成文档。@Api(tags = {“应用健康检查”})@RestController@RequestMapping(value = “/healthcheck”)public class HealthCheckController { …}属性列表属性描述tags属性用来对接口进行分组管理。当然你可以添加多个 tag,那么该类下的接口会在这两个分组里出现。注意事项:如果没有指定响应的 Content-Type ,springfox 的默认值是 /。有两种指定方式。在 Controller 类或方法上的 @RequestMapping 注解中增加 produces 属性值。@RequestMapping(value = “/healthcheck”,produces = MediaType.APPLICATION_JSON_VALUE)在 Swagger 配置类中指定默认值。docket… .produces(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE)) .consumes(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))…@ApiIgnore声明该 API 接口类不需要生成文档。@ApiIgnore(“过时的API”)@ConditionalOnExpression(“false”)@RestController@RequestMapping(value = “/record/xianbank”)public class RecordXianBankController { …}Operation 声明@ApiOperation用于接口方法上,描述该接口相关信息。@ApiOperation( nickname = “healthCheckUsingGet”, value = “应用健康检查”, notes = “用于检查应用是否可以正常访问。”, produces = MediaType.APPLICATION_JSON_VALUE, response = HealthCheckRes.class)@GetMapping()public BaseResult<HealthCheckRes.AppStatus> healthCheck() { …}属性列表属性描述nicknameoperationID,接口唯一标识value接口名称notes接口描述信息produces响应 Content-Type,示例:“application/json, application/xml"consumes请求 Content-Type,示例:“application/json, application/xml"responseresponse body Model,响应体结构及单个字段示例参考资料:@ApiModelProperty throwing NumberFormatException if example value is not set ...

April 14, 2019 · 2 min · jiezi

springcloud gateway聚合swagger2

问题描述在搭建分布式应用时,每个应用通过nacos在网关出装配了路由,我们希望网关也可以将所有的应用的swagger界面聚合起来。这样前端开发的时候只需要访问网关的swagger就可以,而不用访问每个应用的swagger。框架springcloud+gateway+nacos+swagger问题分析swagger页面是一个单页面应用,所有的显示的数据都是通过和springfox.documentation.swagger.web.ApiResponseController进行数据交互,首先通过/swagger-resources获取swagger资源信息,获取的信息格式如下:[{name: “default”, url: “/v2/api-docs”, swaggerVersion: “2.0”, location: “/v2/api-docs”}],其中name代表swagger生成的接口组的组名,如图所示:url代表swagger接口组的详细信息可以通过 localhost:8081/v2/api-docs来获取,如下图:在网关处,如果访问/swagger-resources能够获取到所有应用的swagger的资源信息,那么我们的问题就可以解决了,所以我们需要做的是修改/swagger-resources接口的处理方式,使得这个接口能够按照我们的需求返回swagger资源。解决方案我们首先在网关处引入swagger的相关依赖,然后实现一个获取其他应用的swagger资源的组件: /** * 聚合各个服务的swagger接口 * * @author ksyzz * @since <pre>2019/04/09</pre> / @Component public class MySwaggerResourceProvider implements SwaggerResourcesProvider { /* * swagger2默认的url后缀 / private static final String SWAGGER2URL = “/v2/api-docs”; /* * 网关路由 / private final RouteLocator routeLocator; /* * 网关应用名称 / @Value("${spring.application.name}") private String self; @Autowired public MySwaggerResourceProvider(RouteLocator routeLocator) { this.routeLocator = routeLocator; } @Override public List<SwaggerResource> get() { List<SwaggerResource> resources = new ArrayList<>(); List<String> routeHosts = new ArrayList<>(); // 由于我的网关采用的是负载均衡的方式,因此我需要拿到所有应用的serviceId // 获取所有可用的host:serviceId routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null) .filter(route -> !self.equals(route.getUri().getHost())) .subscribe(route -> routeHosts.add(route.getUri().getHost())); // 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上 Set<String> dealed = new HashSet<>(); routeHosts.forEach(instance -> { // 拼接url,样式为/serviceId/v2/api-info,当网关调用这个接口时,会自动通过负载均衡寻找对应的主机 String url = “/” + instance + SWAGGER2URL; if (!dealed.contains(url)) { dealed.add(url); SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setUrl(url); swaggerResource.setName(instance); resources.add(swaggerResource); } }); return resources; } }然后定义一个接口类: /* * swagger聚合接口,三个接口都是swagger-ui.html需要访问的接口 * * @author ksyzz * @since <pre>2019/04/09</pre> */ @RestController @RequestMapping("/swagger-resources") public class SwaggerResourceController { private MySwaggerResourceProvider swaggerResourceProvider; @Autowired public SwaggerResourceController(MySwaggerResourceProvider swaggerResourceProvider) { this.swaggerResourceProvider = swaggerResourceProvider; } @RequestMapping(value = “/configuration/security”) public ResponseEntity<SecurityConfiguration> securityConfiguration() { return new ResponseEntity<>(SecurityConfigurationBuilder.builder().build(), HttpStatus.OK); } @RequestMapping(value = “/configuration/ui”) public ResponseEntity<UiConfiguration> uiConfiguration() { return new ResponseEntity<>(UiConfigurationBuilder.builder().build(), HttpStatus.OK); } @RequestMapping public ResponseEntity<List<SwaggerResource>> swaggerResources() { return new ResponseEntity<>(swaggerResourceProvider.get(), HttpStatus.OK); } }然后启动网关,访问 http://网关地址/swagger-ui.html,可以看到在箭头处,可以切换不同应用的swagger页面。 ...

April 10, 2019 · 1 min · jiezi

关于Swagger2和SpringBoot整合使用

一、为什么要使用Swagger2现代化的研发组织架构中,一个研发团队基本包括了产品组、后端组、前端组、APP端研发、 测试组、 UI组等,各个细分组织人员各司其职,共同完成产品的全周期工作。如何进行组织架构内的有效高效沟通就显得尤其重要。其中,如何构建一份合理高效的接口文档更显重要。二、常用的注解三、使用步骤1、导入依赖<!– swagger2 配置 –> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.4.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.4.0</version> </dependency>2、编写Swagger2的配置类@Configuration@EnableSwagger2public class Swagger2 { /** * @Description:swagger2的配置文件,这里可以配置swagger2的一些基本的内容,比如扫描的包等等 / @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() .apis(RequestHandlerSelectors.basePackage(“com.imooc.controller”)) .paths(PathSelectors.any()).build(); } /* * @Description: 构建 api文档的信息 */ private ApiInfo apiInfo() { return new ApiInfoBuilder() // 设置页面标题 .title(“使用swagger2构建短视频后端api接口文档”) // 设置联系人 .contact(new Contact(“imooc-Nathan”, “http://www.imooc.com”, “scau_zns@163.com”)) // 描述 .description(“欢迎访问短视频接口文档,这里是描述信息”) // 定义版本号 .version(“1.0”).build(); }}访问http://localhost:8080/swagger-ui.html3、配置某个Controller@RestController@RequestMapping("/video")@Api(value = “视频相关业务的接口”,tags = {“视频相关业务的controller”})public class VideoController {}4、配置某个接口方法@ApiOperation(value = “上传视频”,notes = “上传视频的接口”) @ApiImplicitParams({ @ApiImplicitParam(name = “userId”, value = “用户id”, required = true, dataType = “String”, paramType = “form”), @ApiImplicitParam(name = “bgmId”, value = “背景音乐id”, required = false, dataType = “String”, paramType = “form”), @ApiImplicitParam(name = “videoSeconds”, value = “背景音乐的播放长度”, required = true, dataType = “String”, paramType = “form”), @ApiImplicitParam(name = “videoWidth”, value = “视频宽度”, required = true, dataType = “String”, paramType = “form”), @ApiImplicitParam(name = “videoHeight”, value = “视频高度”, required = true, dataType = “String”, paramType = “form”), @ApiImplicitParam(name = “desc”, value = “视频描述”, required = false, dataType = “String”, paramType = “form”) }) @PostMapping(value = “/upload”, headers = “content-type=multipart/form-data”) public IMoocJSONResult upload(String userId, String bgmId, double videoSeconds, int videoWidth, int videoHeight, String desc, @ApiParam(value = “短视频”, required = true) MultipartFile file) throws Exception {} 注意到消息头headers = “content-type=multipart/form-data”,那么前端传过来的参数 formData:{ userId: userInfo.id, bgmId: bgmId, desc: desc, videoSeconds: duration, videoWidth: tmpWidth, videoHeight: tmpHeight }5、用对象来接收参数可以在pojo上做配置@ApiModel(value = “用户对象”,description = “这是用户对象 “)public class Users { @ApiModelProperty(hidden = true) private String id; @ApiModelProperty(value = “用户名”, name = “username”,example = “imoocuser”,required = true) private String username; @ApiModelProperty(value = “密码”, name = “password”,example = “123456”,required = true) private String password; @ApiModelProperty(hidden = true) private String faceImage; private String nickname; @ApiModelProperty(hidden = true) private Integer fansCounts; @ApiModelProperty(hidden = true) private Integer followCounts; @ApiModelProperty(hidden = true) private Integer receiveLikeCounts;}如果设置了hidden = true,那么文档里面上传的参数就不会显示出来6、测试接口 ...

April 7, 2019 · 2 min · jiezi

Spring Boot 集成 Swagger,生成接口文档就这么简单!

之前的文章介绍了《推荐一款接口 API 设计神器!》,今天栈长给大家介绍下如何与优秀的 Spring Boot 框架进行集成,简直不能太简单。你所需具备的基础告诉你,Spring Boot 真是个牛逼货!Spring Boot 核心配置文件详解Spring Boot 开启的 2 种方式Spring Boot 自动配置原理、实战Spring Boot 2.x 启动全过程源码分析更多请在Java技术栈微信公众号后台回复关键字:boot。Spring Boot 集成 Swagger1、添加依赖Maven依赖示例:<!– Swagger –><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId></dependency><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId></dependency>2、在 Spring Boot 配置文件中添加配置参数。swagger: title: API标题 description: API描述 version: 1.0 terms-of-service-url: http://www.javastack.cn/ base-package: cn.javastack.test.web contact: name: Javastack url: http://www.javastack.cn/ email: admin@javastack.cn3、添加配置类@Getter@Setter@Configuration@EnableSwagger2@ConditionalOnClass(EnableSwagger2.class)@ConfigurationProperties(prefix = “swagger”)public class SwaggerConfig { /** * API接口包路径 / private String basePackage; /* * API页面标题 / private String title; /* * API描述 / private String description; /* * 服务条款地址 / private String termsOfServiceUrl; /* * 版本号 / private String version; /* * 联系人 */ private Contact contact; @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage(basePackage)) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title(title) .description(description) .termsOfServiceUrl(termsOfServiceUrl) .version(version) .contact(contact) .build(); }}如何使用Swagger 默认会根据配置的包,扫描所有接口并生成对应的 API 描述和参数信息,但这样不是很直观,需要对每个接口和参数进行自定义描述。常用的 Swagger 注解如下。注解名称使用说明@Api描述一个 API 类@ApiImplicitParam描述一个请求参数@ApiImplicitParams描述一组请求参数@ApiModel描述一个返回的对象@ApiModelProperty描述一个返回的对象参数@ApiOperation描述一个 API 方法@ApiParam描述一个方法的参数@ApiResponse描述一个请求响应@ApiResponses描述一组请求响应使用示例如:@Api(description = “登录模块”)@RestControllerpublic class LoginController { @ApiOperation(value = “登录”, httpMethod = “POST”) @ApiImplicitParams({ @ApiImplicitParam(name = “username”, value = “用户名”, dataType = “string”, paramType = “query”), @ApiImplicitParam(name = “password”, value = “密码”, dataType = “string”, paramType = “query”)}) @PostMapping(value = “/login”) public Object login(@RequestParam(“username”) String username, @RequestParam(“password”) String password) { // … }}http://localhost:8080/swagger-ui.html打开 swagger-ui 界面,可以看到所有的 API 接口定义,也可以在上面发起接口测试。关注Java技术栈微信公众号,在后台回复:工具,获取栈长整理的更多的工具绝技,都是实战干货,以下仅为部分预览。Java 开发必知道的国外 10 大网站免费在线创作流程图、思维导图软件推荐一款代码神器,代码量至少省一半!推荐一款接口 API 设计神器!超详细的 Git 实战教程,傻瓜一看也会!……本文原创首发于微信公众号:Java技术栈(id:javastack),关注公众号在后台回复 “工具” 可获取更多,转载请原样保留本信息。 ...

March 19, 2019 · 1 min · jiezi

Swagger2 构建 RESTful APIs的使用

@Api 的使用Api 作用在 Controller 类上,做为 Swagger 文档资源,该注解将一个 Controller(Class)标注为一个 Swagger 资源(API)。Swagger-Core 默认只会扫描解析具有 @Api 注解的类,而会自动忽略其他类别资源。属性配置如表所示:

March 16, 2019 · 1 min · jiezi

推荐一款接口 API 设计神器!

今天栈长给大家推荐一款接口 API 设计神器,传说中的,牛逼哄洪的 Swagger,它到底是什么?今天为大家揭开谜底!Swagger是什么?官网:https://swagger.io/Swagger 如官网所示,它是最好的 API 构建工具。它是一个围绕 OpenAPI 规范构建的开源工具,它可以帮助我们设计、构建、记录和使用 REST API 接口。Swagger 包含的主要套件:Swagger Editor - 基于浏览器的编辑器,用来编写 OpenAPI 规范。Swagger UI - 基于 OpenAPI 规范动态生成 API 规范文档。Swagger Codegen - 个模板驱动引擎,用来生成客户端代码。图片来源见博客水印。OpenAPI是什么?上面有说到 Swagger 是一个围绕 OpenAPI 规范构建的开源工具,那么 OpenAPI 是什么呢?OpenAPI 规范,以前叫 Swagger 规范。它是一个为 REST APIs的接口定义的规范。OpenAPI 可以定义的 API 实体内容包括以下几个部分。请求地址(如:/user)请求类型(如:GET、POST 等)请求参数响应参数验证方式文档信息:如联系人、许可证、服务条件等这个 OpenAPI 规范可以用 YAML 或者 JSON 来编写,这种格式非常易于学习,可读性对开发人员非常友好。完整的 OpenAPI 规范可以去官网看一下。https://github.com/OAI/OpenAP…编写文档地址:http://editor.swagger.io/为什么需要Swagger?现在的互联网架构都是前后端分离的模式,还有现在是移动互联网时代了,APP 需要与后端服务器通信也需要维护一套接口,API文档自然就成了前后端开发人员联系的纽带。编写 API 文档的方式也各有不同,有用 WORD 编写的,有用 confluence 等编写的,但这些方式都不能动态更新,每次接口变更都需要手动维护文档,甚是麻烦。有了 Swagger,可以先做完接口,通过 Swagger 来动态生成和更新 API 文档。后面的文章会继续介绍如何使用 Swagger 注解来自动生成 API 文档,及如何集成 Spring Boot 来应用实战,关注Java技术栈微信公众号,在后台回复关键字 “工具” 可获取所有历史 Java 工具类文章教程及更新。本文原创首发于微信公众号:Java技术栈(id:javastack),关注公众号在后台回复 “工具” 可获取更多,转载请原样保留本信息。 ...

February 20, 2019 · 1 min · jiezi

swagger-ui 转换成文档

最近在用swagger写API手册,写一堆注解后,启动Java工程,API文档就自动生成了,打开swagger-ui.html,效果是这样的。上面可以执行RestAPI,但是用来阅读,非常不得劲。因为,我们想要下面这样的,哪里不会点哪里。怎么得到这种效果呢?swagger2markup + AsciiDoc可以帮你达成目标。Swagger2markupswagger2markup是一个Java库,用来将Swagger自动生成的文档转换成几种流行的格式以便于静态部署和使用,比如:AsciiDoc、Markdown。但是这种方式进行swagger to markup的转换要编码初始化,做一堆事情,侵入性较大。swagger2markup-cli 是一种将 swagger json文件转换为 Markdown 或 AsciiDoc 的命令行工具。不需要写代码,就可以进行转换。我更喜欢swagger2markup-cli这种侵入性小的转换方式,它的主要操作步骤如下下载swagger2markup-cli到本地(本地已安装jre) 去github https://github.com/Swagger2Ma… , 下载最新代码,编译一个jar包即可。 默认的swagger2markup-cli生成英文的AsciiDoc文档,如果要生成中文markdown文档,需要将语言设置为中文,将文档格式设置为Markdown。 配置如下,建议将这些配置保存到文档config.properties中。swagger2markup.markupLanguage=MARKDOWNswagger2markup.outputLanguage=ZH获取swagger-json文件的路径采用swagger 注解的Spring Boot工程启动后,就可以从 URL “base路径”/v2/api-docs接口可以获得 swagger-json文件执行命令 swagger2markup-cli 生成markdown java -jar swagger2markup-cli-1.3.3.jar convert -i http://127.0.0.1:8090/api/v1/v2/api-docs -c ./config.properties -f lsm -i 指定swagger json文件可以是url地址 -c 指定配置文件 -f 指定目标文件地址,注意不需要带后缀执行命令后你就可以得到markdown文件或AsciiDoc文件,但markdown显示后的效果是这样的,并没有我们期待的侧边栏。AsciiDoctorAsciidoc 是一种文档写作语言,可以展示出比markdown更好的格式效果。确实如此,我本来想先生成markdown再将markdown格式化,但搜索了半天,没有好但方案。于是我就选用了AsciiDoc,AsciiDoc有比较好但工具软件AsciiDoctor。基于这个工具可以简单快捷但生成类JavaDoc html文件,并且显示效果更好。安装Asciidoctor 使用ruby写的,我安装是使用gem安装的,gem install Asciidoctor即可。其他环境安装方法请到Asciidoctor官网查询。https://asciidoctor.org/docs/…转换 执行如下命令,即可得到 lsm.html,显示效果如下图 asciidoctor -d book -a toc=left -a sectnums lsm.adoc -d 生成文件类型 -a toc=left 指定目录到左侧 -a sectnums 指定生成的文件带section编至此搞定收工,希望你也能拥有一个满意的API 文档。

January 13, 2019 · 1 min · jiezi

Lumen微服务生成Swagger文档

作为一名phper,在使用Lumen框架开发微服务的时候,API文档的书写总是少不了的,比较流行的方式是使用swagger来写API文档,但是与Java语言原生支持 annotation 不同,php只能单独维护一份swagger文档,或者在注释中添加annotations来实现类似的功能,但是注释中书写Swagger注解是非常痛苦的,没有代码提示,没有格式化。本文将会告诉你如何借助phpstorm中annotations插件,在开发Lumen微服务项目时(Laravel项目和其它php项目方法类似)快速的在代码中使用注释来创建swagger文档。本文将会持续修正和更新,最新内容请参考我的 GITHUB 上的 程序猿成长计划 项目,欢迎 Star,更多精彩内容请 follow me。框架配置我们使用当前最新的 Lumen 5.7 来演示。演示代码放到了github,感兴趣的可以参考一下https://github.com/mylxsw/lumen-swagger-demo安装依赖在Lumen项目中,首先需要使用 composer 安装SwaggerLume项目依赖composer require darkaonline/swagger-lume项目配置在bootstrap/app.php文件中,去掉下面配置的注释(大约在26行),启用Facades支持。$app->withFacades();启用SwaggerLume 项目的配置文件,在 Register Container Bindings部 分前面,添加$app->configure(‘swagger-lume’);然后,在 Register Service Providers 部分,注册 SwaggerLume 的ServiceProvider$app->register(\SwaggerLume\ServiceProvider::class);在项目的根目录,执行命令 php artisan swagger-lume:publish 发布swagger相关的配置执行该命令后,主要体现以下几处变更在 config/ 目录中,添加了项目的配置文件 swagger-lume.php在 resources/views/vendor 目录中,生成了 swagger-lume/index.blade.php 视图文件,用于预览生成的API文档从配置文件中我们可以获取以下关键信息api.title 生成的API文档显示标题routes.api 用于访问生成的API文档UI的路由地址默认为 /api/documentationroutes.docs 用于访问生成的API文档原文,json格式,默认路由地址为 /docspaths.docs 和 paths.docs_json 组合生成 api-docs.json 文件的地址,默认为 storage/api-docs/api-docs.json,执行php artisan swagger-lume:generate命令时,将会生成该文件语法自动提示纯手写swagger注释肯定是要不得的,太容易出错,还需要不停的去翻看文档参考语法,因此我们很有必要安装一款能够自动提示注释中的注解语法的插件,我们常用的IDE是 phpstorm,在 phpstorm 中,需要安装 PHP annotation 插件安装插件之后,我们在写Swagger文档时,就有代码自动提示功能了书写文档Swagger文档中包含了很多与具体API无关的信息,我们在 app/Http/Controllers 中创建一个 SwaggerController,该控制器中我们不实现业务逻辑,只用来放置通用的文档信息<?phpnamespace App\Http\Controllers;use OpenApi\Annotations\Contact;use OpenApi\Annotations\Info;use OpenApi\Annotations\Property;use OpenApi\Annotations\Schema;use OpenApi\Annotations\Server;/** * * @Info( * version=“1.0.0”, * title=“演示服务”, * description=“这是演示服务,该文档提供了演示swagger api的功能”, * @Contact( * email=“mylxsw@aicode.cc”, * name=“mylxsw” * ) * ) * * @Server( * url=“http://localhost”, * description=“开发环境”, * ) * * @Schema( * schema=“ApiResponse”, * type=“object”, * description=“响应实体,响应结果统一使用该结构”, * title=“响应实体”, * @Property( * property=“code”, * type=“string”, * description=“响应代码” * ), * @Property(property=“message”, type=“string”, description=“响应结果提示”) * ) * * * @package App\Http\Controllers /class SwaggerController{}接下来,在业务逻辑控制器中,我们就可以写API了<?phpnamespace App\Http\Controllers;use App\Http\Responses\DemoAdditionalProperty;use App\Http\Responses\DemoResp;use Illuminate\Http\Request;use OpenApi\Annotations\Get;use OpenApi\Annotations\MediaType;use OpenApi\Annotations\Property;use OpenApi\Annotations\RequestBody;use OpenApi\Annotations\Response;use OpenApi\Annotations\Schema;class ExampleController extends Controller{ /* * @Get( * path="/demo", * tags={“演示”}, * summary=“演示API”, * @RequestBody( * @MediaType( * mediaType=“application/json”, * @Schema( * required={“name”, “age”}, * @Property(property=“name”, type=“string”, description=“姓名”), * @Property(property=“age”, type=“integer”, description=“年龄”), * @Property(property=“gender”, type=“string”, description=“性别”) * ) * ) * ), * @Response( * response=“200”, * description=“正常操作响应”, * @MediaType( * mediaType=“application/json”, * @Schema( * allOf={ * @Schema(ref="#/components/schemas/ApiResponse"), * @Schema( * type=“object”, * @Property(property=“data”, ref="#/components/schemas/DemoResp") * ) * } * ) * ) * ) * ) * * @param Request $request * * @return DemoResp / public function example(Request $request) { // TODO 业务逻辑 $resp = new DemoResp(); $resp->name = $request->input(’name’); $resp->id = 123; $resp->age = $request->input(‘age’); $resp->gender = $request->input(‘gender’); $prop1 = new DemoAdditionalProperty(); $prop1->key = “foo”; $prop1->value = “bar”; $prop2 = new DemoAdditionalProperty(); $prop2->key = “foo2”; $prop2->value = “bar2”; $resp->properties = [$prop1, $prop2]; return $resp; }}这里,我们在响应结果中,引用了在SwaggerController中定义的 ApiResponse,还引用了一个没有定义的ExampleResp对象,我们可以 app\Http\Responses 目录(自己创建该目录)中实现该ExampleResp对象,我们将响应对象都放在这个目录中<?phpnamespace App\Http\Responses;use OpenApi\Annotations\Items;use OpenApi\Annotations\Property;use OpenApi\Annotations\Schema;/* * @Schema( * title=“demo响应内容”, * description=“demo响应内容描述” * ) * * @package App\Http\Responses /class DemoResp extends JsonResponse{ /* * @Property( * type=“integer”, * description=“ID” * ) * * @var int / public $id = 0; /* * @Property( * type=“string”, * description=“用户名” * ) * * @var string / public $name; /* * @Property( * type=“integer”, * description=“年龄” * ) * * @var integer / public $age; /* * @Property( * type=“string”, * description=“性别” * ) * * @var string / public $gender; /* * @Property( * type=“array”, * @Items(ref="#/components/schemas/DemoAdditionalProperty") * ) * * @var array / public $properties = [];}返回对象引用其它对象<?phpnamespace App\Http\Responses;use OpenApi\Annotations\Property;use OpenApi\Annotations\Schema;/* * * @Schema( * title=“额外属性”, * description=“额外属性描述” * ) * * @package App\Http\Responses /class DemoAdditionalProperty{ /* * @Property( * type=“string”, * description=“KEY” * ) * * @var string / public $key; /* * @Property( * type=“string”, * description=“VALUE” * ) * * @var string */ public $value;}生成文档执行下面的命令,就可以生成文档了,生成的文档在storage/api-docs/api-docs.json。php artisan swagger-lume:generate预览文档打开浏览器访问 http://访问地址/docs,可以看到如下内容访问 http://访问地址/api/documentation,我们看到接口详细信息展开更多本文简述了如何在Lumen项目中使用代码注释自动生成Swagger文档,并配合phpstorm的代码提示功能,然而,学会了这些还远远不够,你还需要去了解Swagger文档的语法结构,在 swagger-php 项目的 Examples 目录中包含很多使用范例,你可以参考一下。团队项目中使用了swagger文档,但是总得有个地方管理文档吧,这里推荐一下 Wizard 项目,该项目是一款用于团队协作的文档管理工具,支持Markdown文档和Swagger文档,感兴趣的不妨尝试一下。 ...

January 2, 2019 · 3 min · jiezi

使用API自动生成工具优化前端工作流

在工作中,我们的前端工作流一般开始于前后端协商好Api文档之后,再针对这个Api文档做mock模拟数据,然后用做好的mock进行开发,后端开发完毕之后再改一下API数据的BaseURL切换到正式API进行联调;如下本文介绍的一个工具(或者说方法),来将这个工作流优化一下,也是我平时工作正在用的方法,当做自己的笔记,也跟大家一起分享一下这个方法的主要思路就是开发人员在某个api工具中按要求填好文档,然后导出swagger.json配置文件,再把这个配置文件导入到easy-mock中,再用工具自动生成前端api的js文件以供调用。本文中所使用的工具:sosoApi、Easy-mock、Swagger、Easy-mock-api-template、axios1. 使用Api管理平台导出swagger.json文件一般我们前后端通过各种平台或者工具来管理Api,比如免费的可视化Api管理平台 sosoApi、Yapi等,一般来说这些工具都可以生成swagger.json的Api,我们可以用它来直接生成一个漂亮的可视化Api文档,也可以用它来作为配置文件导入其他工具中,比如Easy-mock;比如在sosoApi中就可以导出为swagger文档(swagger.json):我们先导出一个swagger.json备用;2. 使用swagger.json导入easy-mockMock平台我们可以使用Easy-mock,轻量又简洁,虽然没有Api的分组功能,但平时应付应付不太大的应用、个人应用等场景足够了;Easy-mock官网的服务被不少人直接拿到开发环境用,经常被挤爆,这个情况可以用本地部署来解决这个问题,参考 windows本地安装部署 Easy Mock 。我们将Api管理平台中导出的swagger.json文件在新建project的时候导入:这样刚刚Api平台中配置的Api就被同步到我们的Easy-mock配置中了,比如sosoApi的示例项目导出的结果就是:这时我们就可以用它来进行数据mock了,怎么样,是不是很轻松easy-mock项目面板上面会有个 Project ID,这个记下来后面要用;3. 使用easy-mock-cli生成js格式Api有了easy-mock之后一般情况下我们要写前端的api文件了,一般api工具用axios,这里提供一个封装:// utils/fetch.jsimport axios from ‘axios’ const service = axios.create({ baseURL: ‘https://easy-mock.com/project/5bf6a23c92b5d9334494e884', timeout: 5000}) // request拦截器service.interceptors.request.use( config => {…}, err => {…}) // respone拦截器service.interceptors.response.use( res => {…}, err => {…}) export default service我们可以用easy-mock-cli来生成api,模板文件如果不想用原来的模板的话,可以使用我fork之后改写的一个模板easy-mock-api-template,生成的Api文件是这样的:// api/index.jsimport fetch from ‘utils/fetch’; /* 活动查询 /const activityQuery = ({ activityDate }) => fetch({ method: ‘get’, url: ‘/activity/query’, params: { activityDate }}); /* 活动保存 /const activitySave = () => fetch({ method: ‘post’, url: ‘/activity/save’}); /* 活动提交 */const activitySubmit = ({ activityId, content }) => fetch({ method: ‘post’, url: ‘/activity/submit’, data: { activityId, content }}); export { activityQuery, // 活动查询 activitySave, // 活动保存 activitySubmit // 活动提交};然后在文件中就可以:import * as Api from ‘api/index.js’; // 调用Api.activitySubmit({ activityId: 2 }) .then(…)简单介绍一下配置文件,更复杂的配置要参考原来的文档;// .easy-mock.js 配置文件 { host: ‘http://localhost:8080/’, // easy-mock的源,没有本地部署的话不用写,本地部署则填本地服务地址 output: “../”, // 生成 API 的基础目录 template: “../”, // 指定模板,这里用本地写的模板 projects: [ // 可以有多个模板来源 { “id”: “你要创建的 Easy Mock 项目的 id”, // 刚刚记下来的 Project ID “name”: “api” // 生成的output目录下的文件名 } ]}然后npm run create-api就可以在根目录下生成一个api/index.js文件了网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出参考:用swagger.json自动生成axios api访问代码 - 简书Easy-mock-cli/README.md推介阅读:windows本地安装部署 Easy Mock - 掘金 ...

November 23, 2018 · 1 min · jiezi

浅谈easy-mock 最好的备胎没有之一

引言 今天我们来聊聊Mock,随着互联网发展,这两年前后端分离的开发模式兴起,Mock也从以住的幕后走上了台面,让更多的人而得知,以前传统的开发方式Mock大多局限在后端人员接触较多一些。 Mock已经是老生常谈了,网上一搜索就很多,各位前辈们都讲的很到位,但今天我只讲它——easy-mock。 为什么会突然来聊它,这个就说来话长了,个人简介里就说过,专注于分享工作中遇到的坑,但这一次不是我的坑,来源于QQ群友(# 如果您有想知道的故事,而正好我也会,那么就由我为您讲出来吧,欢迎留言哦 # ),请看下图:这里是@IT·平头哥联盟,我是首席填坑官—苏南,用心分享 做有温度的攻城狮。什么是Mock 什么是Mock?? Mock其实就是真实数据存在之前,即调试期间的代替品,是个虚拟的存在,用人话讲它就是个备胎,如女生长的好看,追她的人多,但又不是很满意但也不拒绝,在自己心仪的小哥哥出现之前,一直吊着你????!如何Mock数据?不要告诉我 new 一个哦,对象可以 new,备胎可new不出来呢????;方法一:最low的方式将 Mock 数据写在代码里、json文件里;方法二:利用 Charles 、Fiddler等代理工具,将 URL 映射到本地文件;方法三:本地起 Mock Server,即mockjs,有点麻烦每次修改了后还要重启服务,nodemon能解决,但开的东西多了,电脑卡出翔,维护也麻烦;方法四:规范些的公司自己已经集成了一套mock数据体系;重点来了:easy-mock一个在线 Mock 平台,活儿好又性感是你备胎的最佳选择。当然优秀的你可能还有很多其他的方式,欢迎补充。//mock 基本使用示例import Mock from “mockjs”;Mock.mock({ “code”: 0, “message”: “请求成功”, “data|20”: [{ “name”: “@cname”,//cname 中文,name 英文 “userId”: “@id”, “lastDate”: “@datetime” }]})什么是easy-mock,能给我们带来什么?Easy Mock 是一个可视化,并且能快速生成 模拟数据 的持久化服务,Easy Mock 支持基于 Swagger 创建项目,以节省手动创建接口的时间;简单点说:Easy Mock就是一个在线创建mock的服务平台,帮你省去你 配置、安装、起服务、维护、多人协作Mock数据不互通等一系列繁琐的操作, 它能在不用1秒钟的时间内给你所要的一切,呼之即来、挥之即去的2018最优秀备胎没有之一,完全不用担心负任何责任哦。更多优点它在等你去发现哦……深入浅出 - 简介就跟人一样长的再好看,了解过后才懂,一样东西也是如何,谁用谁知道;Easy Mock支持团队协作,也可以是个人项目,以下以个人项目为例,与多人协作没有区别,只是少了成员邀请;深入浅出 - Mock语法回顾@ip -> 随机输出一个ip;@id -> 随机输出长度18的字符,不接受参数;“array|1-10” -> 随机输出1-10长度的数组,也可以直接是固定长度;“object|2” -> 输出一个两个key值的对象,"@image()" 返回一个占位图url,支持size, background, foreground, format, text;等等,这里就不再一一介绍。深入浅出 - 创建一个接口它的写法,跟Mock.js一模一样,上面代码已经展示过,更多示例使用Easy Mock创建一个接口,请看下图:深入浅出 - 高阶用法 Function在线编辑,它也能支持 function ,是不是很优秀,能获取到全部请求头,可以让我们像写在js里一样写逻辑,写运算,当然它肯定是还有很多局限性的,如并不支持ES6,有一点需要注意的是 function 里要写传出Mock对象,不能直接@…,来看示例:对象描述MockMock 对象_req.url获得请求 url 地址_req.method获取请求方法_req.params获取 url 参数对象_req.querystring获取查询参数字符串(url中?后面的部分),不包含 ?_req.query将查询参数字符串进行解析并以对象的形式返回,如果没有查询参数字字符串则返回一个空对象_req.body当 post 请求以 x-www-form-urlencoded 方式提交时,我们可以拿到请求的参数对象…_req.cookies、ip、host等等,我只是一个代码的搬运,更详细请看这里//简单模拟登录,根据用户传入的参数,返回不同逻辑数据{ defaultName:function({_req}){ return _req.query.name; }, code: function({_req}){ return this.defaultName ? 0 : -97; }, message: function({_req}) { return this.defaultName ? “登录成功” : “参数错误”; }, data: function({req,Mock}){ return this.defaultName ? { token: Mock.mock("@guid()"), userId: Mock.mock("@id(5)"), cname: Mock.mock("@cname()"), name: Mock.mock("@name()"), avatar: Mock.mock("@image(200x100, #FF6600)"), other:"@IT·平头哥联盟-首席填坑官∙苏南 带你再谈Mock数据之easy-mock" }:{} }}深入浅出 - 在线调试再优秀的工程师写出的代码也一样要测试,没有人敢说自己的代码无Bug,Easy Mock 它是真的懂你的,已经为你准备好了,接口编写好后,立马就能让你测试,是不是觉得很棒棒呢??如果是你自己本地写mock数据,你需要重启服务、手动写参数、可能还需要整个测试页,知道你已经非常饥渴迫切的想要知道,具体的调试方式了:看不清吗??已经为你备好在线调试链接,支持POST、GET、PUT等方式,因gif图加载比较大,就不一一演示了结尾: 天下无不散之宴席,又到说再见的时候了,以上就是今天苏南为大家带来的分享,您GET到了吗?Easy Mock更多强大之处自己去折腾吧,#用心分享 做有温度的攻城狮#,希望今天的分享能给您带来些许成长,如果觉得不错记得点个赞哦,,顺便关注下方公众号就更棒了呢,每周为您推最新分享????????。更多文章:immutability因React官方出镜之使用总结分享!小程序项目之做完项目老板给我加了6k薪资~小程序项目之填坑小记面试踩过的坑,都在这里了~你应该做的前端性能优化之总结大全!如何给localStorage设置一个过期时间?动画一点点 - 如何用CSS3画出懂你的3D魔方?动画一点点 - 手把手教你如何绘制一辆会跑车SVG Sprites Icon的使用技巧作者:苏南 - 首席填坑官链接:https://blog.csdn.net/weixin…交流群:912594095、公众号:honeyBadger8本文原创,著作权归作者所有。商业转载请联系@IT·平头哥联盟获得授权,非商业转载请注明原链接及出处。 ...

November 7, 2018 · 1 min · jiezi

Swagger 生成 PHP API 接口文档

Swagger 生成 PHP API 接口文档标签(空格分隔): php1、概况有同学反馈写几十个接口文档需要两天的工作量, 随着多部门之间的协作越来越频繁, 维护成本越来越高, 文档的可维护性越来越差, 需要一个工具来管理这些接口的文档, 并能够充当mock server给调用方使用。有同学推荐了swagger+easymock,Swagger是一个简单但功能强大的API表达工具。 这里介绍使用swagger-php生成PHP API文档的方法。2、安装与使用2.1 安装swagger-php包git clone https://github.com/zircote/swagger-php.gitcomposer install// 全局的composer global require zircote/swagger-php// 项目中composer global require zircote/swagger-php2.2 laravel项目安装使用 L5 Swagger https://github.com/DarkaOnLine/L5-Swagger具体安装过程请参考此文档: https://github.com/DarkaOnLin...2.3 编写API注解# 创建文件 demo/customer.php<?php/** * @OA\Info(title=“My First API”, version=“0.1”) /class Customer{ /* * @OA\Get( * path="/customer/info", * summary=“用户的个人信息”, * description=“这不是个api接口,这个返回一个页面”, * @OA\Parameter(name=“userId”, in=“query”, @OA\Schema(type=“string”), required=true, description=“用户ID”), * @OA\Response( * response=“200”, * description=“An example resource” * ) * ) */ public function info(int $userId, string $userToken) { }}2.4 生成swagger API 文件./swagger-php/bin/openapi demo -o ./docsAPI 内容如下:# docs/openapi.yamlopenapi: 3.0.0info: title: ‘My First API’ version: ‘0.1’paths: /customer/info: get: summary: 用户的个人信息 description: ‘这不是个api接口,这个返回一个页面’ operationId: ‘Customer::info’ parameters: - name: userId in: query description: 用户ID required: true schema: type: string responses: ‘200’: description: ‘An example resource'3、展示git clone https://github.com/swagger-api/swagger-ui.gitcomposer install直接通过Dockerfile构建、启动项目, 或者使用docker-compose进行服务管理。version: ‘2’services: swagger-ui: build: . ports: - “8080:8080” volumes: - ./dist/:/usr/share/nginx/html/ restart: on-failure访问 http://localhost:8080/ 即可到 swagger 编辑器预览界面。./swagger-php/bin/openapi demo -o ./swagger-ui/dist/将 api文档输出值swagger ui的根目录下,可通过 http://localhost:8080/openapi.yaml 访问此api文档。执行 Explore 结果如图:4、参考资料Swagger 生成 PHP restful API 接口文档如何编写基于 Swagger-PHP 的 API 文档https://github.com/zircote/swagger-phphttps://github.com/swagger-api/swagger-uiEasy MockLaravel(PHP)使用Swagger生成API文档不完全指南 ...

October 19, 2018 · 1 min · jiezi