接口文檔:第二章:使用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。