关于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