接口文檔:第二章:使用Swagger接口的文檔在線自動(dòng)生成
上一章:商城接口文檔:第一章:簡(jiǎn)潔版接口文檔?;硕旄懔艘粋€(gè)比較簡(jiǎn)潔的接口文檔,浪費(fèi)時(shí)間不說,寫的也不太好,不滿意。這一章使用Swagger接口的文檔在線自動(dòng)生成省下不少時(shí)間,而且很規(guī)范。
導(dǎo)入Maven
版本號(hào)請(qǐng)根據(jù)實(shí)際情況自行更改。
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>
自定義注釋生成器
package com.macro.mall;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import org.mybatis.generator.internal.util.StringUtility;
import java.util.Properties;
/**
* 自定義注釋生成器
* Created by macro on 2018/4/26.
*/
public class CommentGenerator extends DefaultCommentGenerator {
private boolean addRemarkComments = false;
private static final String EXAMPLE_SUFFIX="Example";
private static final String API_MODEL_PROPERTY_FULL_CLASS_NAME="io.swagger.annotations.ApiModelProperty";
/**
* 設(shè)置用戶配置的參數(shù)
*/
@Override
public void addConfigurationProperties(Properties properties) {
super.addConfigurationProperties(properties);
this.addRemarkComments = StringUtility.isTrue(properties.getProperty("addRemarkComments"));
}
/**
* 給字段添加注釋
*/
@Override
public void addFieldComment(Field field, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
String remarks = introspectedColumn.getRemarks();
//根據(jù)參數(shù)和備注信息判斷是否添加備注信息
if(addRemarkComments&&StringUtility.stringHasValue(remarks)){
// addFieldJavaDoc(field, remarks);
//數(shù)據(jù)庫中特殊字符需要轉(zhuǎn)義
if(remarks.contains("\"")){
remarks = remarks.replace("\"","'");
}
//給model的字段添加swagger注解
field.addJavaDocLine("@ApiModelProperty(value = \""+remarks+"\")");
}
}
/**
* 給model的字段添加注釋
*/
private void addFieldJavaDoc(Field field, String remarks) {
//文檔注釋開始
field.addJavaDocLine("/**");
//獲取數(shù)據(jù)庫字段的備注信息
String[] remarkLines = remarks.split(System.getProperty("line.separator"));
for(String remarkLine:remarkLines){
field.addJavaDocLine(" * "+remarkLine);
}
addJavadocTag(field, false);
field.addJavaDocLine(" */");
}
@Override
public void addJavaFileComment(CompilationUnit compilationUnit) {
super.addJavaFileComment(compilationUnit);
//只在model中添加swagger注解類的導(dǎo)入
if(!compilationUnit.isJavaInterface()&&!compilationUnit.getType().getFullyQualifiedName().contains(EXAMPLE_SUFFIX)){
compilationUnit.addImportedType(new FullyQualifiedJavaType(API_MODEL_PROPERTY_FULL_CLASS_NAME));
}
}
}
創(chuàng)建Swagger2配置類
在Application.java同級(jí)創(chuàng)建Swagger2的配置類Swagger2
package com.swaggerTest;
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.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger2配置類
* 在與spring boot集成時(shí),放在與Application.java同級(jí)的目錄下。
* 通過@Configuration注解,讓Spring來加載該類配置。
* 再通過@EnableSwagger2注解來啟用Swagger2。
*/
@Configuration
@EnableSwagger2
public class Swagger2 {
/**
* 創(chuàng)建API應(yīng)用
* apiInfo() 增加API相關(guān)信息
* 通過select()函數(shù)返回一個(gè)ApiSelectorBuilder實(shí)例,用來控制哪些接口暴露給Swagger來展現(xiàn),
* 本例采用指定掃描的包路徑來定義指定要建立API的目錄。
*
* @return
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.swaggerTest.controller"))
.paths(PathSelectors.any())
.build();
}
/**
* 創(chuàng)建該API的基本信息(這些基本信息會(huì)展現(xiàn)在文檔頁面中)
* 訪問地址:http://項(xiàng)目實(shí)際地址/swagger-ui.html
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2構(gòu)建RESTful APIs")
.description("更多請(qǐng)關(guān)注http://www.baidu.com")
.termsOfServiceUrl("http://www.baidu.com")
.contact("sunf")
.version("1.0")
.build();
}
}
通過createRestApi函數(shù)創(chuàng)建Docket的Bean之后,apiInfo()用來創(chuàng)建該Api的基本信息(這些基本信息會(huì)展現(xiàn)在文檔頁面中)。
Swagger使用的注解及其說明:
@Api:用在類上,說明該類的作用。
@ApiOperation:注解來給API增加方法說明。
@ApiImplicitParams : 用在方法上包含一組參數(shù)說明。
@ApiImplicitParam:用來注解來給方法入?yún)⒃黾诱f明。
@ApiResponses:用于表示一組響應(yīng)
@ApiResponse:用在@ApiResponses中,一般用于表達(dá)一個(gè)錯(cuò)誤的響應(yīng)信息
l code:數(shù)字,例如400
l message:信息,例如"請(qǐng)求參數(shù)沒填好"
l response:拋出異常的類
@ApiModel:描述一個(gè)Model的信息(一般用在請(qǐng)求參數(shù)無法使用@ApiImplicitParam注解進(jìn)行描述的時(shí)候)
l @ApiModelProperty:描述一個(gè)model的屬性
注意:@ApiImplicitParam的參數(shù)說明:
案例1:
package com.swaggerTest.controller;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
/**
* 一個(gè)用來測(cè)試swagger注解的控制器
* 注意@ApiImplicitParam的使用會(huì)影響程序運(yùn)行,如果使用不當(dāng)可能造成控制器收不到消息
*
* @author SUNF
*/
@Controller
@RequestMapping("/say")
@Api(value = "SayController|一個(gè)用來測(cè)試swagger注解的控制器")
public class SayController {
@ResponseBody
@RequestMapping(value ="/getUserName", method= RequestMethod.GET)
@ApiOperation(value="根據(jù)用戶編號(hào)獲取用戶姓名", notes="test: 僅1和2有正確返回")
@ApiImplicitParam(paramType="query", name = "userNumber", value = "用戶編號(hào)", required = true, dataType = "Integer")
public String getUserName(@RequestParam Integer userNumber){
if(userNumber == 1){
return "張三豐";
}
else if(userNumber == 2){
return "慕容復(fù)";
}
else{
return "未知";
}
}
@ResponseBody
@RequestMapping("/updatePassword")
@ApiOperation(value="修改用戶密碼", notes="根據(jù)用戶id修改密碼")
@ApiImplicitParams({
@ApiImplicitParam(paramType="query", name = "userId", value = "用戶ID", required = true, dataType = "Integer"),
@ApiImplicitParam(paramType="query", name = "password", value = "舊密碼", required = true, dataType = "String"),
@ApiImplicitParam(paramType="query", name = "newPassword", value = "新密碼", required = true, dataType = "String")
})
public String updatePassword(@RequestParam(value="userId")
Integer userId, @RequestParam(value="password") String password,
@RequestParam(value="newPassword") String newPassword){
if(userId <= 0 || userId > 2){
return "未知的用戶";
}
if(StringUtils.isEmpty(password) || StringUtils.isEmpty(newPassword)){
return "密碼不能為空";
}
if(password.equals(newPassword)){
return "新舊密碼不能相同";
}
return "密碼修改成功!";
}
}
完成上述代碼添加上,啟動(dòng)Spring Boot程序,訪問:http://localhost:8080/swagger-ui.html
如上圖,可以看到暴漏出來的控制器信息,點(diǎn)擊進(jìn)入可以看到詳細(xì)信息。
兩個(gè)注意點(diǎn):
1. paramType會(huì)直接影響程序的運(yùn)行期,如果paramType與方法參數(shù)獲取使用的注解不一致,會(huì)直接影響到參數(shù)的接收。
例如:
使用Sawgger UI進(jìn)行測(cè)試,接收不到!
2. 還有一個(gè)需要注意的地方:
Conntroller中定義的方法必須在@RequestMapper中顯示的指定RequestMethod類型,否則SawggerUi會(huì)默認(rèn)為全類型皆可訪問, API列表中會(huì)生成多條項(xiàng)目。
如上圖:updatePassword()未指定requestMethod,結(jié)果生成了7條API信息。所以如果沒有特殊需求,建議根據(jù)實(shí)際情況加上requestMethod。