用Swagger生成SpringBoot接口文檔

目錄

一,原始項目說明

二,引入Swagger

三,Swagger首頁

四,Swagger註解使用

1,@Api

2,@ApiOperation

3,@ApiImplicitParam和@ApiImplicitParams

4,@ApiResponse和@ApiResponses

5,@ApiModel和@ApiModelProperty

6,@ResponseHeader


一,原始項目說明

首先,我找了一個Springboot+SpringCloud的項目,裏面沒什麼東西,是個最簡單的服務,比如這樣:

啓動類:

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class ConsumerRibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerRibbonApplication.class, args);
    }

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

一個Controller:

@RestController
public class HiController {

    @Autowired
    RibbonService ribbonService;

    @RequestMapping(value = "/hi")
    public String hi(@RequestParam String name) {
        return ribbonService.hiService(name);
    }
}

一個Service:

@Service
public class RibbonService {

    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiServiceError")
    public String hiService(String name) {
        return restTemplate.getForObject("http://provider-a/hi?name=" + name, String.class);
    }

    public String hiServiceError(String name) {
        return "hi," + name + ",斷路機制啓動,hiServiceError";
    }
}

application.properties文件裏寫的是:

server.port: 8764

spring.application.name: consumer-ribbon

eureka.client.service-url.defaultZone: http://localhost:8761/eureka/

以上代碼,和Swagger有關的也只有端口配置8764了。

 

二,引入Swagger

如果要在項目中加入Swagger,首先要在pom文件中加入:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

然後我們需要一個Swagger的配置類:

package consumer.ribbon;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
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.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;

@EnableSwagger2
@ComponentScan(basePackages = {"consumer.ribbon"})
@Configuration
public class SwaggerConfig extends WebMvcConfigurationSupport {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("這裏填title")//標題
                .description("這裏填description")//描述
                .termsOfServiceUrl("http://www.google.com.hk")//(不可見)條款地址,公司內部使用的話不需要配
                .contact(new Contact("這裏填作者姓名", "這裏填作者url", "這裏填作者email"))//作者信息
                .version("這裏填version")//版本號
                .build();
    }

//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new LoginInterceptor())
//                .addPathPatterns("/**")
//                .excludePathPatterns("/user/login")
//                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
//    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

//        registry.addResourceHandler("/templates/**")
//                .addResourceLocations("classpath:/META-INF/resources/templates/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

注:

1,註解別寫少了,另外@ComponentScan註解中的basePackages參數別寫錯了,這是需要掃描Swagger註解的文件路徑。

2,createRestApi()方法裏的內容基本照抄,不用改。

3,addResourceHandlers()方法是爲了避免Swagger首頁進不去而添加的路徑關聯,這個方法不寫的話進首頁會404。

其中:

registry.addResourceHandler("swagger-ui.html")

是爲了訪問首頁。

registry.addResourceHandler("/webjars/**")

是首頁用到的一些靜態資源。

中間註釋的一段貌似不寫也沒什麼影響。

4,被註釋的addInterceptors()方法網上很多文章說需要加,否則首頁404,不過我試了一下好像也可以不寫。方法中用到的LoginInterceptor類實際上是自定義的一個Interceptor,沒什麼內容:

package consumer.ribbon;

import org.springframework.web.servlet.HandlerInterceptor;

public class LoginInterceptor  implements HandlerInterceptor {
}

 

三,Swagger首頁

做完這些後,啓動SpringBoot服務,在地址欄輸入:

http://127.0.0.1:8764/swagger-ui.html

可以進入Swagger首頁:

可以看到,首頁中已經展示了兩個Controller。

其中BasicErrorController不是自己定義的,點開之後裏面展示的是/error接口的配置,看起來像是請求錯誤地址後的跳轉接口:

另外首頁還展示了hi-controller,這個controller沒有使用任何Swagger專用的註解,但是Swagger依然掃描到了他,可能是用@RestController和@RequestMapping兩種註解掃描的。另外/hi接口沒有配置請求方式,所以Swagger列出了所有格式的/hi接口:

打開某個接口會有參數的說明,返回值說明等:

另外,點擊右上角的Try it out按鈕,還可以實際調用一下該接口,輸入參數值,點擊Execut按鈕調用,就像PostMan一樣:

 

四,Swagger註解使用

 

1,@Api

@Api註解用在Controller上,說明該類的作用。

注意:使用該註解必須與Controller註解一起使用,比如@RestController或@Controller。

 

部分參數:

value:網上說是url路徑值,但是我填了貌似沒啥用,沒見在哪能展示。

tags:應該理解爲Controller的名字,可以選擇填Controller類名,或者Controller的Url路徑。網上說此參數會覆蓋value,但是即使沒有此參數value也顯示不出來。

description:描述信息。

position:在Swagger上的排序位置,有多個@Api的時候可以配。

hidden:爲true時隱藏該文檔,但是我設置了沒啥用。

 

寫個代碼:

@Api(tags = "SwaggerController", description = "Swagger測試Controller", position = 0)
@RestController
@RequestMapping(value = "/swagger", method = RequestMethod.POST)
public class SwaggerController {
    @RequestMapping(value = "/hi")
    public String hi(@RequestParam String name) {
        return "name=" + name;
    }
}

Swagger裏顯示的是這樣的:

 

2,@ApiOperation

@ApiOperation註解用在Controller中的方法上,用於說明方法的作用。

 

部分參數:

tags:方法名。可以選擇寫方法名或url路徑。

notes:描述信息。

 

寫個代碼:

@ApiOperation(value = "getUser", notes = "獲取用戶接口", response = java.lang.String.class)
@RequestMapping(value = "/hi")
public String getUser(@RequestParam String name) {
    return "name=" + name;
}

Swagger裏顯示的是這樣的:

 

3,@ApiImplicitParam和@ApiImplicitParams

@ApiImplicitParam註解用在單參數方法上,或者多參數方法的 @ApiImplicitParams註解中。

 

部分參數:

paramType:參數類型,可選項有:

  1. path:以地址的形式提交數據。此類型的參數必須由@PathVariable註解來獲取。
  2. query:直接跟參數完成自動映射賦值。此類型的參數必須由@RequestParam註解來獲取。
  3. body:以流的形式提交,僅支持POST。
  4. header:參數在request headers裏提交。此類型的參數必須由@RequestHeader註解來獲取。
  5. form:以form表單的形式提交,僅支持POST

dataType:參數數據類型:可選值有Integer和String。

name:參數名,最好寫成和Java方法中實際的參數名一致。

value:參數描述。

required:參數是否必填,可選值有true和false。

defaultValue:默認值,這個默認值是使用Swagger發起調用時用的,和SpringMVC提供的參數默認值不是一個概念。

 

Swagger和Spring對參數的控制方式完全不同

Swagger對參數的控制是文檔層面的,並不能真正控制接口本身,而Spring可以真正控制接口的定義,二者各管一邊互不干擾。

以required爲例,在Swagger中是這麼用的:

@ApiImplicitParam(name = "userName", value = "用戶名", required = true)

該配置代表Swagger認爲userName參數必填,這一點將體現在Swagger生成的文檔上,另外,如果在Swagger首頁上使用Try it out發起調用,這個配置也會生效,如果不填userName的話請求就發不出去。然而,以上這些和接口的實際要求並沒有什麼關係,從配置上來說二者完全可以對不上。

相比之下,Spring提供restful接口時是這樣使用required的:

@RequestParam(required = true) String userName

該配置代表Spring認爲接口的userName參數是必填項,那麼這個參數就真的是必填的,如果沒填那麼請求將被返回400的錯誤。

同理,Swagger和Spring對默認值的使用也有同樣的情況,Swagger的默認值就是能在文檔上看看。

 

@ApiImplicitParam中的name,最好寫成和Java方法中實際的參數名一致,否則在Swagger上會分別展示,比如:

@ApiOperation(value = "getUser", notes = "獲取用戶接口", response = java.lang.String.class)
@ApiImplicitParam(name = "name", value = "用戶名value", required = true, defaultValue = "abcde", paramType = "form", dataType = "String")
@RequestMapping(value = "/getUser", method = RequestMethod.POST)
public String getUser(@RequestParam String userName) {
    return "userName=" + userName;
}

在Swagger上的效果是:

圖8

上面的name參數就是我們用@ApiImplicitParam註解定義的,下面的userName是在Java方法中定義的參數,而且和@RequestParam註解無關。使用Try it out來發起調用的時候,我們自定義的name和方法的真實參數userName都可以使用輸入值,但是隻有真實參數纔是有效的:

 

@ApiImplicitParam註解的另一個用法,是用在@ApiImplicitParams註解中,比如:

@ApiOperation(value = "getUser2", notes = "獲取用戶接口", response = java.lang.String.class)
@ApiImplicitParams({
        @ApiImplicitParam(name = "userName", value = "用戶名", required = true, defaultValue = "abcde", paramType = "query", dataType = "String"),
        @ApiImplicitParam(name = "age", value = "用戶年齡", required = false, defaultValue = "12", paramType = "query", dataType = "Integer")
})
@RequestMapping(value = "/getUser2", method = RequestMethod.POST)
public String getUser2(@RequestParam String userName,
                      Integer age) {
    return "userName=" + userName + " age=" + age;
}

在Swagger上的效果是:

依然需要注意參數名和java方法實際的參數名要一致。

 

4,@ApiResponse和@ApiResponses

@ApiResponse註解用在方法上,並且用在@ApiResponses註解中,是對返回信息的說明。

@ApiResponse註解直接用在方法上時貌似不會起作用。

 

部分參數:

code:http響應狀態碼

message:描述信息

response:響應類,默認void

注:關於response參數,可能本身設計的初衷是爲了維護某些錯誤的http請求時的響應類,不過實際上此參數也可以用來描述正常http請求(code=200)的響應類。另外,響應類的參數可以設置爲public,或者設置爲private並且寫好get/set方法。

比如:

@ApiOperation(value = "getUser3", notes = "獲取用戶接口", response = java.lang.String.class)
@ApiResponses({
    @ApiResponse(code = 200, message = "請求正常", response = ErrorResponse.class),
    @ApiResponse(code = 400, message = "參數錯誤", response = ErrorResponse.class)
})
@RequestMapping(value = "/getUser3", method = RequestMethod.POST)
public String getUser3(@RequestParam String userName,
                       Integer age) {
    return "userName=" + userName + " age=" + age;
}

其中ErrorResponse類是這樣的:

public class ErrorResponse {
    private int code;
    private String message;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

在Swagger裏效果是這樣的:

 

5,@ApiModel和@ApiModelProperty

@ApiModel用於響應類上,是返回響應類的說明。

@ApiModelProperty用於響應類的屬性上,是對響應類屬性的描述。

 

@ApiModel註解的部分參數:

value:名稱

description:描述

parent:父類class,爲了可以描述從父類繼承來的屬性。

 

@ApiModelProperty註解的部分參數:

value:參數名

 

舉個例子:

@ApiOperation(value = "getUser4", notes = "獲取用戶接口", response = consumer.swagger.UserResponse.class)
@RequestMapping(value = "/getUser4", method = RequestMethod.POST)
public UserResponse getUser4(@RequestParam String userName,
                             Integer age) {
    UserResponse userResponse = new UserResponse();
    userResponse.setId(123);
    userResponse.setAge(age);
    userResponse.setName(userName);
    return userResponse;
}

其中的響應類UserResponse是這樣的:

package consumer.swagger;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "UserResponse",description = "用戶信息",parent = consumer.swagger.UserResponseParent.class)
public class UserResponse extends UserResponseParent{

    @ApiModelProperty(value = "用戶id")
    private int id;

    @ApiModelProperty(value = "用戶名")
    private String name;

    @ApiModelProperty(value = "年齡")
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

有父類UserResponseParent,此類定義如下:

package consumer.swagger;

import io.swagger.annotations.ApiModelProperty;

public class UserResponseParent {

    @ApiModelProperty(value = "父級姓名")
    private String parentName;

    public String getParentName() {
        return parentName;
    }

    public void setParentName(String parentName) {
        this.parentName = parentName;
    }
}

父類可以不用@ApiModel註解,只需要在屬性上添加@ApiModelProperty註解。

於是在Swagger上是這樣的效果:

注意,在code=200的那一欄裏,此時默認選中的是Example Value這一項,所以顯示了UserResponse類的一個例子,如果我們選擇Model這一項,就會顯示UserResponse類的說明:

可見,父類的屬性也被列出來了,如果父類屬性添加了@ApiModelProperty註解,註解就會生效,否則就只有屬性名。

 

6,@ResponseHeader

@ResponseHeader註解用於設置響應頭,可以用在@ApiResponse註解中。

 

部分參數:

name:響應頭名稱

description:描述

response:響應類,默認Void。

比如:

@ApiOperation(value = "getUser5", notes = "獲取用戶接口", response = java.lang.String.class)
@ApiResponses({
        @ApiResponse(code = 400, message = "參數錯誤", response = ErrorResponse.class,responseHeaders = {
                @ResponseHeader(name = "Location", description = "The URL to retrieve created resource", response = String.class)
        })
})
@RequestMapping(value = "/getUser5", method = RequestMethod.POST)
public String getUser5(@RequestParam String userName,
                       Integer age) {
    return "userName=" + userName + " age=" + age;
}

在Swagger中的效果是這樣的:

 

其實Swagger的功能還是蠻強大的,不只是生成文檔這麼簡單,上面提到的註解和參數也只是冰山一角,待後面慢慢學習。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章