Swagger
一、描述
现代化的研发 组织 架构中,一个研发团队基本包括了 产品组、后端组、前端组、APP端研发、 测试组、 UI 组等,各个细分组织人员各司其职,共同完成产品的全周期工作。如何进行组织架构内的有效高效沟通就显得尤其重要。其中,如何构建一份合理高效的接口文档更显重要。 随着互联网技术的发展,现在的网站架构基本都由原来的后端变成前后端分离。前后端的唯一联系,是通过API接口;API文档变成了前后端开发人员联系的纽带,变得越来越重要。
二、API文档
解决方案:手写文档完成前后端开发。
开发文档手册:
https://wenku.baidu.com/view/f88529d185868762caaedd3383c4bb4cf6ecb707.html
手写文档存在的问题
- 文档需要更新的时候,需要再次发送一份给前端,也就是文档更新交流不及时。
- 接口返回结果不明确
- 不能直接在线测试接口,通常需要使用工具,比如:
Postman
- 接口文档太多,不好进行维护管理
- 文档是接口提供方手动导入的,是静态文档,没有提供接口测试功能
三、 Swagger
1、简介
官网:https://swagger.io/ Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。 Swagger 也就是为了解决这个问题,当然也不能说 Swagger 就一定是完美的,当然也有缺点,最明显的就是代码植入性比较强。
作用:
1. 接口的文档在线自动生成。
2. 功能测试。
2、Swagger组件
Swagger是一组开源项目,其中主要要项目如下:
- Swagger-tools:提供各种与Swagger进行集成和交互的工具。例如模式检验、Swagger 1.2文档转换成Swagger 2.0文档等功能。
- Swagger-core: 用于Java/Scala的的Swagger实现。与JAX-RS(Jersey、Resteasy、CXF...)、Servlets和Play框架进行集成。
- Swagger-js: 用于JavaScript的Swagger实现。
- Swagger-node-express: Swagger模块,用于node.js的Express web应用框架。
- Swagger-ui:一个无依赖的HTML、JS和CSS集合,可以为Swagger兼容API动态生成优雅文档。
- Swagger-codegen:一个模板驱动引擎,通过分析用户Swagger资源声明以各种语言生成客户端代码。
3、Swagger集成
增加 Swagger2 所需依赖
<!-- Swagger2 Begin -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<!-- Swagger2 End -->
创建Swagger2配置类
/**
* @ClassName SwaggerConfig
* author wangpengcheng
*/
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger2配置类 基于SpringBoot
* 通过@Configuration注解,让Spring来加载该类配置。
* 再通过@EnableSwagger2注解来启用Swagger2。
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
/**
* 创建API应用
* apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,
* 本例采用指定扫描的包路径来定义指定要建立API的目录。
*
* @return
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.wpc.springbootssm.controller"))
.paths(PathSelectors.any())
.build();
}
/**
* 创建该API的基本信息(这些基本信息会展现在文档页面中)
* 访问地址:http://项目实际地址/swagger-ui.html
*
* @return
*/
private ApiInfo apiInfo() {
//联系人基本信息
Contact contact = new Contact("wangpengcheng", "url", "pengcheng965@163.com");
return new ApiInfoBuilder()
.title("会议达人 --Swagger2构建API文档")
.description("更多请关注")
.termsOfServiceUrl("http://localhost:8081/swagger-ui.html")
.contact(contact)
.version("1.0")
.build();
}
}
查看swagger2
完成上述代码添加,启动Spring Boot程序
访问:http://localhost:8081/springboot/swagger-ui.html
(有应用名需要加上相应的应用名)
四、swagger2注解说明
代码的植入性(侵入性)比较强。
注解:
Controller JavaBean
1 、类描述
@Api:用在请求的类上,表示对类的说明 tags="说明该类的作用,可以在UI界面上看到的注解" value="该参数没什么意义,在UI界面上也看到,所以不需要配置"
@Controller @RequestMapping("user") @Api(tags = {"用户列表","用户列表控制类"})
2、 方法描述
@ApiOperation:用在请求的方法上,说明方法的用途、作用
value="说明方法的用途、作用" notes="方法的备注说明"
@ApiOperation(value = "查询用户",notes = "根据用户的请求ID查询用户信息")
3、方法参数描述
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面 name:参数名 value:参数的汉字说明、解释 required:参数是否必须传 paramType:参数放在哪个地方 · header --> 请求参数的获取:@RequestHeader · query --> 请求参数的获取:@RequestParam · path(用于restful接口)-->请求参数的获取:@PathVariable [实战中建议不加,用默认] · body(不常用) · form(不常用) dataType:参数类型,默认String,其它值dataType="Integer"
defaultValue:参数的默认值
@ApiOperation(value = "添加用户",notes = "添加用户信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "姓名", required = true, paramType = "query", dataType = "String"),
@ApiImplicitParam(name ="telphone",value ="手机号",required = true,paramType ="query",dataType = "String"),
@ApiImplicitParam(name ="status",value ="状态",required = false,paramType ="query",defaultValue = "0",dataType = "String")
})
@RequestMapping(value ="add",method = RequestMethod.PUT)
public String add(User user,Model model){
}
4、方法响应参数
@ApiResponses:用在请求的方法上,表示一组响应
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息 code:数字,例如400 message:信息,例如"请求参数没填好" response:抛出异常的类
@ApiResponses({
@ApiResponse(code = 400,message = "客户端请求参数填写异常"),
@ApiResponse(code = 404,message = "您所请求的资源无法找到")
})
完整 代码如下:
@ApiOperation(value="获取用户详细信息", notes="根据url的id来获取用户详细信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户ID", required = true,dataType = "String")
})
@ApiResponses({
@ApiResponse(code = 400,message = "客户端请求参数填写异常"),
@ApiResponse(code = 404,message = "您所请求的资源无法找到")
})
@RequestMapping(value = "{id}", method = RequestMethod.GET) // user/id
public ResponseEntity<ResultJson<User>> getUserById (@PathVariable(value = "id") Integer id) {
User user = userService.selectByPrimaryKey(id);
ResultJson<User> resultJson=null;
if(user!=null){
resultJson=new ResultJson<>(200,"success",user);
}else{
resultJson=new ResultJson<>(40013,"invalid id",user);
}
ResponseEntity re=new ResponseEntity(resultJson, HttpStatus.OK);
return re;
}
五、自
定义返回码
1、简介:
模仿 微信开发者文档API调用 示例:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839
2、自定义创建类
ResultJson
package com.wpc.util.resulst;
import lombok.Data;
@Data
public class ResultJson<T> {
/*响应码*/
private String code;
/*消息提示内容文件*/
private String msg;
/*返回指定对象*/
private T data;
/** 成功的方法*/
public ResultJson(T t) {
this.setCode(ResultCode.SUCCESS.getCode());
this.setMsg(ResultCode.SUCCESS.getMsg());
this.setData(t);
}
/**已有的ResultCode 进行返回*/
public ResultJson(T t,ResultCode code){
this.setCode(code.getCode());
this.setMsg(code.getMsg());
this.setData(t);
}
/** 完全自定义返回 */
public ResultJson(T t,String code,String message){
this.setCode(code);
this.setMsg(message);
this.setData(t);
}
}
常量工具类:
ResultCode
package com.wpc.util.resulst;
public enum ResultCode {
//##########TODO 请求成功 2**
/** 成功 */
SUCCESS("2000", "成功"),
/** 操作失败 */
FAIL("2001", "操作失败"),
/** 数据已存在 */
SUCCESS_IS_HAVE("2002", "数据已存在"),
/** 没有结果 */
NOT_DATA("2003", "没有结果"),
//##########TODO 客户端错误 4**
/** 没有登录 */
NOT_LOGIN("4000", "没有登录"),
/** 发生异常 */
EXCEPTION("4001", "发生异常"),
/** 系统错误 */
SYS_ERROR("4002", "系统错误"),
/** 参数错误 */
PARAMS_ERROR("4003", "参数错误 "),
/** 不支持或已经废弃 */
NOT_SUPPORTED("4004", "不支持或已经废弃"),
/** AuthCode错误 */
INVALID_AUTHCODE("4005", "无效的AuthCode"),
/** 太频繁的调用 */
TOO_FREQUENT("4006", "太频繁的调用"),
/** 未知的错误 */
UNKNOWN_ERROR("4007", "未知错误"),
/** 未设置方法 */
NOT_METHOD("4008", "未设置方法");
//##########TODO 服务器错误 5**
private ResultCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
/**对应状态码*/
private String code;
/**返回内容*/
private String msg;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
3、代码调用示例
@RequestMapping(value = "r/{id}",method = RequestMethod.GET) // meetingpub/r/id
public ResultJson selectMeetingpubById1(@PathVariable("id") final String id){
Meetingpub meetingpub=meetingpubService.selectByPrimaryKey(id);
if (meetingpub==null){
return ResultJson.failed("用户ID不存在"); //失败后调用
}
return ResultJson.ok(meetingpub); //成功后调用
}
使用spring ResponseEntity处理http响应
使用Spring-ResponseEntity可以响应json格式的数据,非常方便
ResponseEntity标识整个http相应:状态码、头部信息以及相应体内容。因此我们可以使用其对http响应实现完整配置。
4、代码API调用示例:
@RequestMapping(value = "{id}", method = RequestMethod.GET) // user/id
public ResponseEntity<ResultJson<User>> getUserById (@PathVariable(value = "id") Integer id) {
User user = userService.selectByPrimaryKey(id);
ResultJson<User> resultJson=null;
if(user!=null){
resultJson=new ResultJson<>(200,"success",user);
}else{
resultJson=new ResultJson<>(40013,"invalid id",user);
}
ResponseEntity re=new ResponseEntity(resultJson, HttpStatus.OK);
return re;
}
5、调用显示返回JSON:
成功数据:
{"code":200,"message":"success","data":{"id":1,"name":"1","telphone":"123","status":1}}
失败数据:
{"code":40013,"message":"invalid id","data":null}
尽管ResponseEntity非常强大,但不应该过度使用。在一些简单情况下,还有其他方法能满足我们的需求,使代码更整洁。
替代方法 @ResponseBody 典型spring mvc应用,请求点通常返回html页面。有时我们仅需要实际数据,如使用ajax请求。这时我们能通过@ResponseBody注解标记请求处理方法,审批人能够处理方法结果值作为http响应体。
@ResponseStatus 当请求点成功返回,spring提供http 200(ok)相应。如果请求点抛出异常,spring查找异常处理器,由其返回相应的http状态码。对这些方法增加@ResponseStatus注解,spring会返回自定义http状态码。
6、其它方案:
使用 Spring REST Docs 创建 REST 服务文档
简介:
Spring REST Docs 是一个为 Spring 项目生成 API 文档的框架,它通过在单元测试中额外添加 API 信息描述,从而自动生成对应的文档片段。