Swagger 專題

 

隨着互聯網技術的發展,如今的網站架構基本都由原來的後端渲染,變成了:前端渲染、先後端分離的形態,並且前端和後端在各自的技術道路上越走越遠。css

前端和後端的惟一聯繫,變成了API接口;API文檔成了先後端開發人員聯繫的紐帶,變得愈來愈重要, swagger就是一款讓你更好的書寫API文檔的框架。html

文檔工具前端

沒有API文檔工具以前,你們都是手寫API文檔的,在什麼地方書寫的都有,有在 Word上寫的,有在對應的項目目錄下 readme.md上寫的,每一個公司都有每一個公司的玩法,無所謂好壞。java

現現在市場上書寫API文檔的工具備不少,常見的有 postman、yapi、阿里的RAP 可是能稱之爲框架的,估計也只有 swagger了。git

swagger 優缺點github

  • 集成方便,功能強大
  • 在線調試與文檔生成
  • 代碼耦合,須要註解支持,但不影響程序性能

實體類

swagger 提供了很是齊全的註解,爲 POJO提供了 @ApiModel、 @ApiModelProperty,以便更好的渲染最終結果web

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.NotEmpty;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

/**
 * @author tangcheng
 * 2018/05/02
 */
@ApiModel("Swagger使用示例")
@Data
public class SayHelloReq {

    @ApiModelProperty(required = true, value = "UserId", dataType = "int", example = "123")
    @NotNull
    @Min(value = 1, message = "最小值必須大於1")
    private Integer userId;

    @ApiModelProperty(required = true, value = "內容", example = "Best Wish!")
    @NotEmpty
    private String content;

    /**
     * 普通的數組
     * example 中 數組中字符串會自動加上雙引號
     */
    @ApiModelProperty(example = "[http://1.com,http://2.com]")
    @NotEmpty
    private String[] pics;

    @ApiModelProperty(example = "\"{name:開心}\"")
    @NotEmpty
    private String mood;

    @ApiModelProperty(value = "普通的數組。使用@RequestBody註解,會將對象所有轉換成JSON。" +
            "若是請求參數不是JSON格式會報錯HttpMessageNotReadableException:\n" +
            " JSON parse error: Can not deserialize instance of java.lang.Integer[] out of VALUE_STRING token;"
            , example = "[1,2]", dataType = "type:array")
    public Integer[] classIds;

}

 

Why does @ApiModelProperty 「name」 attribute has no effect?spring

更改Swagger網頁上展現的字段名:編程

@JsonProperty("phonenumbers") //生成swagger接口參數時用到
@JSONField(name="phonenumbers") //處理請求時用到,若是沒有這個註解,RequstMappingAdapter在將HTTP請求參數set到Request對象中時,會仍然使用之前的phoneNumberDTOList,而後致使phoneNumberDTOList字段值爲空
@ApiModelProperty(value = "list of phone numbers")
List<PhoneNumberDTO> phoneNumberDTOList = new ArrayList<>();

 



https://github.com/springfox/springfox/issues/1289
https://stackoverflow.com/questions/53082934/why-does-apimodelproperty-name-attribute-has-no-effectjson




 

package com.tangcheng.learning.web.dto.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * spring-boot-cookbook
 *
 * @author tangcheng
 * @date 6/17/2018 11:32 AM
 */
@ApiModel("用戶信息")
@Data
@AllArgsConstructor
public class UserVO {

    @ApiModelProperty("主鍵ID")
    private Long id;

    @ApiModelProperty("用戶名")
    private String username;

    @ApiModelProperty("密碼")
    private String password;

}

 

  1. @Api:用在請求的類上,表示對類的說明
  2.  
    tags= "說明該類的做用,能夠在UI界面上看到的註解"
  3.  
    value= "該參數沒什麼意義,在UI界面上也看到,因此不須要配置"
  4.  
     
  5.  
    @ApiOperation:用在請求的方法上,說明方法的用途、做用
  6.  
    value= "說明方法的用途、做用"
  7.  
    notes= "方法的備註說明"
  8.  
     
  9.  
    @ApiImplicitParams:用在請求的方法上,表示一組參數說明
  10.  
    @ApiImplicitParam:用在@ApiImplicitParams註解中,指定一個請求參數的各個方面
  11.  
    name:參數名
  12.  
    value:參數的漢字說明、解釋
  13.  
    required:參數是否必須傳
  14.  
    paramType:參數放在哪一個地方
  15.  
    · header --> 請求參數的獲取: @RequestHeader
  16.  
    · query --> 請求參數的獲取: @RequestParam
  17.  
    · path(用於restful接口)--> 請求參數的獲取: @PathVariable
  18.  
    · body(不經常使用)
  19.  
    · form(不經常使用)
  20.  
    dataType:參數類型,默認String,其它值dataType= "Integer"
  21.  
    defaultValue:參數的默認值
  22.  
     
  23.  
    @ApiResponses:用在請求的方法上,表示一組響應
  24.  
    @ApiResponse:用在@ApiResponses中,通常用於表達一個錯誤的響應信息
  25.  
    code:數字,例如 400
  26.  
    message:信息,例如 "請求參數沒填好"
  27.  
    response:拋出異常的類
  28.  
     
  29.  
    @ApiModel:用於響應類上,表示一個返回響應數據的信息
  30.  
    (這種通常用在post建立的時候,使用 @RequestBody這樣的場景,
  31.  
    請求參數沒法使用 @ApiImplicitParam註解進行描述的時候)
  32.  
    @ApiModelProperty:用在屬性上,描述響應類的屬性
  33.  
    ---------------------
  34.  
    做者:xiaojin21cen
  35.  
    來源:CSDN
  36.  
    原文:https: //blog.csdn.net/xiaojin21cen/article/details/78654652?utm_source=copy
  37.  
    版權聲明:本文爲博主原創文章,轉載請附上博文連接!

 

一、@Api:用在請求的類上,說明該類的做用
     tags="說明該類的做用"
     value="該參數沒什麼意義,因此不須要配置"
示例:

@Api(tags="APP用戶註冊Controller")



二、@ApiOperation:用在請求的方法上,說明方法的做用
@ApiOperation:"用在請求的方法上,說明方法的做用"
    value="說明方法的做用"
    notes="方法的備註說明"
示例:

@ApiOperation(value="用戶註冊",notes="手機號、密碼都是必輸項,年齡隨邊填,但必須是數字")


三、@ApiImplicitParams:用在請求的方法上,包含一組參數說明
     @ApiImplicitParams:用在請求的方法上,包含一組參數說明
     @ApiImplicitParam:用在 @ApiImplicitParams 註解中,指定一個請求參數的配置信息       
        name:參數名
        value:參數的漢字說明、解釋
        required:參數是否必須傳
        paramType:參數放在哪一個地方
            · header --> 請求參數的獲取:@RequestHeader
            · query --> 請求參數的獲取:@RequestParam
            · path(用於restful接口)--> 請求參數的獲取:@PathVariable
            · body(不經常使用)
            · form(不經常使用)    
        dataType:參數類型,默認String,其它值dataType="Integer"       
        defaultValue:參數的默認值


示列:

  1.  
    @ApiImplicitParams({
  2.  
        @ApiImplicitParam(name="mobile",value="手機號",required=true,paramType="form"),
  3.  
        @ApiImplicitParam(name="password",value="密碼",required=true,paramType="form"),
  4.  
        @ApiImplicitParam(name="age",value="年齡",required=true,paramType="form",dataType="Integer")
  5.  
    })
  6.  
     

四、@ApiResponses:用於請求的方法上,表示一組響應
     @ApiResponses:用於請求的方法上,表示一組響應
     @ApiResponse:用在@ApiResponses中,通常用於表達一個錯誤的響應信息
        code:數字,例如400
        message:信息,例如"請求參數沒填好"
        response:拋出異常的類
示例:

  1.  
    @ ApiOperation(value = "select1請求",notes = "多個參數,多種的查詢參數類型")
  2.  
    @ApiResponses({
  3.  
        @ ApiResponse(code=400,message="請求參數沒填好"),
  4.  
        @ApiResponse(code= 404,message="請求路徑沒有或頁面跳轉路徑不對")
  5.  
    })
  6.  
     


五、@ApiModel:用於響應類上,表示一個返回響應數據的信息
     @ApiModel:用於響應類上,表示一個返回響應數據的信息
            (這種通常用在post建立的時候,使用@RequestBody這樣的場景,
            請求參數沒法使用@ApiImplicitParam註解進行描述的時候)
     @ApiModelProperty:用在屬性上,描述響應類的屬性


示例:

  1.  
    import io.swagger.annotations.ApiModel;
  2.  
    import io.swagger.annotations.ApiModelProperty;
  3.  
     
  4.  
    import java.io.Serializable;
  5.  
     
  6.  
    @ ApiModel(description= "返回響應數據")
  7.  
    public class RestMessage implements Serializable{
  8.  
     
  9.  
        @ ApiModelProperty(value = "是否成功")
  10.  
        private boolean success=true;
  11.  
        @ ApiModelProperty(value = "返回對象")
  12.  
        private Object data;
  13.  
        @ ApiModelProperty(value = "錯誤編號")
  14.  
        private Integer errCode;
  15.  
        @ ApiModelProperty(value = "錯誤信息")
  16.  
        private String message;
  17.  
     
  18.  
        /* getter/setter */
  19.  
    }

 

轉自:http://www.javashuo.com/article/p-xoxiqszl-dn.html

 

 

 

用postman能用,可是swagger的datatype不知道怎麼寫

 

 

 

restful 風格接口

註解描述

  • @Api 描述 Controller

  • @ApiIgnore 忽略該 Controller,指不對當前類作掃描

  • @ApiOperation 描述 Controller類中的 method接口

  • @ApiParam 單個參數描述,與 @ApiImplicitParam不一樣的是,他是寫在參數左側的。如( @ApiParam(name="username",value="用戶名")Stringusername

  • @ApiModel 描述 POJO對象

  • @ApiProperty 描述 POJO對象中的屬性值

  • @ApiImplicitParam 描述單個入參信息

  • @ApiImplicitParams 描述多個入參信息

  • @ApiResponse 描述單個出參信息

  • @ApiResponses 描述多個出參信息

  • @ApiError 接口錯誤所返回的信息

package com.tangcheng.learning.web.api;

import com.tangcheng.learning.web.dto.req.SayHelloReq;
import com.tangcheng.learning.web.dto.vo.UserVO;
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.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;

/**
 * @author tangcheng
 * 2018/05/02
 */
@Api(tags = "Case:MVC參數校驗DSL ", description = "MVC參數校驗DSL")
@Slf4j
@RestController
@RequestMapping("dsl")
public class MVC_DSL_TestController {

    @GetMapping
    @ApiOperation(value = "條件查詢")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用戶名", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密碼", dataType = "string", paramType = "query"),
    })
    public UserVO query(String username, String password) {
        log.info("多個參數用  @ApiImplicitParams");
        return new UserVO(1L, username, password);
    }

    @GetMapping("/{id}")
    @ApiOperation(value = "獲取單條信息詳情")
    @ApiImplicitParam(name = "id", value = "用戶編號", dataType = "long", paramType = "path")
    public ResponseEntity<UserVO> get(@PathVariable Long id) {
        log.info("單個參數用  @ApiImplicitParam");
        UserVO userVO = new UserVO(id, "swagger", "swagger");
        return ResponseEntity.ok(userVO);
    }

    @ApiOperation(value = "RequestBody 校驗DSL", notes = "RequestBody 校驗DSL")
    @PostMapping("/say/hello")
    public ResponseEntity<String> sayHello(@Valid @RequestBody SayHelloReq request) {
        log.info("若是是 POST PUT 這種帶 @RequestBody 的能夠不用寫 @ApiImplicitParam ,swagger 也會使用默認的參數名做爲描述信息");

        Integer[] classIds = request.getClassIds();
        if (classIds == null) {
            throw new IllegalArgumentException("classIds is null");
        }
        return ResponseEntity.ok(request.getUserId() + request.getContent() + request.getMood());
    }


    @ApiOperation(value = "upload", notes = "若是添加@RequestBody註解,會報錯:org.springframework.web.HttpMediaTypeNotSupportedException" +
            "Content type 'multipart/form-data;boundary=----WebKitFormBoundaryKz1zt5cbBPPXkMrt;charset=UTF-8' not supported")
    @PostMapping("/upload")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile multipartFile) {
        log.info("name:{}", multipartFile.getName());//@RequestParam("file") ,引自會返回 file
        return ResponseEntity.ok(multipartFile.getName() + "  " + multipartFile.getOriginalFilename() + " " + multipartFile.getContentType() + " " + multipartFile.getSize());
    }

    /**
     * attribute 'value' and its alias 'name' are present with values of [headerArg] and [Header中傳的參數], but only one is permitted.
     *
     * @param headerArg
     * @return
     */
    @ApiOperation(value = "@RequestHeader", notes = "@RequestHeader")
    @GetMapping("header")
    public ResponseEntity<String> sayHello(@RequestHeader(value = "headerArg", defaultValue = "helloworld") String headerArg) {
        return ResponseEntity.ok("headerArg:" + headerArg);
    }

}

 

 

 

 

Spring Boot下,一個好用的starter

<dependency>
    <groupId>com.spring4all</groupId>
    <artifactId>swagger-spring-boot-starter</artifactId>
    <version>1.7.1.RELEASE</version>
</dependency>

https://github.com/SpringForAll/spring-boot-starter-swagger

 

 

@Data
@NoArgsConstructor
public class TodoDetailReqVO {

    private Long categoryId = 1L;

    @Min(1)
    @ApiModelProperty(required = true, value = "權重")
    private Integer weight = 1;

    @NotEmpty
    @Size(min = 2, max = 200)
    @ApiModelProperty(required = true, value = "摘要")
    private String digest;

    @Size(max = 1000)
    @ApiModelProperty(required = true, value = "詳細內容")
    private String content;

}

 

 

Swagger中設置默認值:

    @JSONField(jsonDirect = true)
    @ApiModelProperty(value = "標籤", dataType = "json")
    private String tags;

    @ApiModelProperty(value = "經驗", example = "{}")
    private String exps;

 

Swagger-ui.html中展現狀況:


 

Data Types

The data type of a schema is defined by the type keyword, for example, type: string.

OpenAPI defines the following basic types:

These types exist in most programming languages, though they may go by different names. Using these types, you can describe any data structures.

Note that there is no null type; instead, the nullable attribute is used as a modifier of the base type.

Additional type-specific keywords can be used to refine the data type, for example, limit the string length or specify an enum of possible values.

https://swagger.io/docs/specification/data-models/data-types/

 

 

 

前言

Swagger 是一款RESTFUL接口的文檔在線自動生成+功能測試功能軟件。本文簡單介紹了在項目中集成swagger的方法和一些常見問題。若是想深刻分析項目源碼,瞭解更多內容,見參考資料。

Swagger 是一個規範和完整的框架,用於生成、描述、調用和可視化 RESTful 風格的 Web 服務。整體目標是使客戶端和文件系統做爲服務器以一樣的速度來更新。文件的方法,參數和模型緊密集成到服務器端的代碼,容許API來始終保持同步。Swagger 讓部署管理和使用功能強大的API從未如此簡單。

1、使用介紹

什麼是 Swagger?

Swagger™的目標是爲REST APIs 定義一個標準的,與語言無關的接口,令人和計算機在看不到源碼或者看不到文檔或者不能經過網絡流量檢測的狀況下能發現和理解各類服務的功能。當服務經過Swagger定義,消費者就能與遠程的服務互動經過少許的實現邏輯。相似於低級編程接口,Swagger去掉了調用服務時的不少猜想。 
瀏覽 Swagger-Spec 去了解更多關於Swagger 項目的信息,包括附加的支持其餘語言的庫。

如何集成Swagger-springmvc到咱們的項目中?

依賴:
Maven

<dependency>
      <groupId>com.mangofactory</groupId>
      <artifactId>swagger-springmvc</artifactId>
      <version>0.9.4</version>
</dependency>
Gradle
repositories {
jcenter()
}

compile "com.mangofactory:swagger-springmvc:0.9.4"

 

使用:

要最快捷地啓動swagger-springmvc項目而且使用默認設置,推薦的方式是使用SwaggerSpringMvc插件

Spring Java Configuration

@Configuration
@EnableWebMvc
@EnableSwagger
@ComponentScan("com.myapp.packages")
public class WebAppConfig {
 ...
}

 

Spring xml Configuration

<mvc:annotation-driven/> <!-- Required so swagger-springmvc can access spring's RequestMappingHandlerMapping  -->
<bean class="com.mangofactory.swagger.configuration.SpringSwaggerConfig" />

 

SwaggerSpringMvcPlugin XML Configuration

爲了使用這個插件,你須要創造一個spring Java配置類。使用spring的 @Configuration ,這個配置類必須被定義到你的xml上下文

<!-- Required so swagger-springmvc can access spring's RequestMappingHandlerMapping  -->
<mvc:annotation-driven/>
 

<bean class="com.yourapp.configuration.MySwaggerConfig"/>

 

@Configuration
@EnableSwagger //Loads the spring beans required by the framework
public class MySwaggerConfig {

private SpringSwaggerConfig springSwaggerConfig;

/**
* Required to autowire SpringSwaggerConfig
*/
@Autowired
public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
  this.springSwaggerConfig = springSwaggerConfig;
}

/**
* Every SwaggerSpringMvcPlugin bean is picked up by the swagger-mvc framework - allowing for multiple
* swagger groups i.e. same code base multiple swagger resource listings.
 */
@Bean
public SwaggerSpringMvcPlugin customImplementation(){
  return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
          .includePatterns(".*pet.*");
}

}

 

SwaggerSpringMvcPlugin Spring Java Configuration

使用@EnableSwagger註解 
自動注入SpringSwaggerConfig 
定義一個或多個SwaggerSpringMvcPlugin實例,經過springs @Bean註解

@Configuration
@EnableWebMvc
@EnableSwagger
@ComponentScan("com.myapp.controllers")
public class CustomJavaPluginConfig {

private SpringSwaggerConfig springSwaggerConfig;

@Autowired
public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
  this.springSwaggerConfig = springSwaggerConfig;
}

@Bean //Don't forget the @Bean annotation
public SwaggerSpringMvcPlugin customImplementation(){
  return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
        .apiInfo(apiInfo())
        .includePatterns(".*pet.*");
}

private ApiInfo apiInfo() {
  ApiInfo apiInfo = new ApiInfo(
          "My Apps API Title",
          "My Apps API Description",
          "My Apps API terms of service",
          "My Apps API Contact Email",
          "My Apps API Licence Type",
          "My Apps API License URL"
    );
  return apiInfo;
}
}

 

2、碰到的問題

關於@API註解

在Swagger Annotation中: 

 

API表示一個開放的API,能夠經過description簡要描述該API的功能。 
在一個@API下,可有多個@ApiOperation,表示針對該API的CRUD操做。在ApiOperation Annotation中能夠經過value,notes描述該操做的做用,response描述正常狀況下該請求的返回對象類型。 
在一個ApiOperation下,能夠經過ApiResponses描述該API操做可能出現的異常狀況。 

 

ApiParam用於描述該API操做接受的參數類型

 

再接着,爲項目的Model對象添加Swagger Annotation,這樣Swagger Scanner能夠獲取更多關於Model對象的信息。

@ApiModel(value = "A SayingRepresentation is a representation of greeting") @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) public class SayingRepresentation { private long id; @ApiModelProperty(value = "greeting content", required = true) private String content; public SayingRepresentation(long id, String content) { this.id = id; this.content = content; } public long getId() { return id; } public String getContent() { return content; } 

經過上面的步驟,項目已經具有了提供Swagger格式的API信息的能力,接下來,咱們把這些信息和Swagger UI集成,以很是美觀,實用的方式把這些API信息展現出來。

和Swagger UI的集成

首先,從github(https://github.com/wordnik/swagger-ui)上下載Swagger-UI, 把該項目dist目錄下的內容拷貝到項目的resources的目錄assets下。

而後,修改index.html, 把Swagger UI對象中的URL替換爲本身的API路徑。

window.swaggerUi = new SwaggerUi({ url: "/api/api-docs", dom_id: "swagger-ui-container", 

最後,爲了能訪問到該頁面,還須要在Service的Initialize方法中,添加AssetsBundle

public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) { //指定配置文件的名字 bootstrap.setName("helloWorld"); bootstrap.addBundle(new AssetsBundle("/assets", "/", "index.html")); } 

最後的效果圖: 

3、評價

Swagger能夠充當先後端交流的重要橋樑,方便快捷。很實用。

Swagger項目容許你生產,顯示和消費你本身的RESTful服務。不須要代理和第三方服務。是一個依賴自由的資源集合,它能經過Swagger API動態的生成漂亮的文檔和沙盒,由於Swagger UI沒有依賴,你能夠把他部署到任何服務器環境或者是你本身的機器。

4、參考資料

官網:http://swagger.io/

http://blog.csdn.net/wangnan9279/article/details/44541665

 

supportHeaderParams默認爲false,而我用的是swagger2,不須要配置靜態的那些東西,因此我在SwaggerConfig添加了幾行代碼:

 

 

[java]  view plain  copy
 
  1. @EnableSwagger2  
  2. @EnableWebMvc  
  3. @ComponentScan("com.g.web")  
  4. public class SwaggerConfig {  
  5.     @Bean  
  6.     public Docket api(){  
  7.         ParameterBuilder tokenPar = new ParameterBuilder();  
  8.         List<Parameter> pars = new ArrayList<Parameter>();  
  9.         tokenPar.name("x-access-token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();  
  10.         pars.add(tokenPar.build());  
  11.         return new Docket(DocumentationType.SWAGGER_2)  
  12.             .select()  
  13.             .apis(RequestHandlerSelectors.any())  
  14.             .paths(PathSelectors.regex("/api/.*"))  
  15.             .build()  
  16.             .globalOperationParameters(pars)  
  17.             .apiInfo(apiInfo());  
  18.     }  
  19.   
  20.     private ApiInfo apiInfo() {  
  21.         return new ApiInfoBuilder()  
  22.             .title("後臺接口文檔與測試")  
  23.             .description("這是一個給app端人員調用server端接口的測試文檔與平臺")  
  24.             .version("1.0.0")  
  25.             .termsOfServiceUrl("http://terms-of-services.url")  
  26.             //.license("LICENSE")  
  27.             //.licenseUrl("http://url-to-license.com")  
  28.             .build();  
  29.     }  
  30. }  


前四行代碼是添加head參數的,前臺效果是這樣的:

 

相關文章
相關標籤/搜索