天天看點

Setting Up Swagger 2 with a Spring REST API

摘要:SpringMVC內建SwaggerUI

一:SpringMVC介紹

Spring Web MVC架構提供了模型 - 視圖 - 控制器(MVC)體系結構和可用于開發靈活和松散耦合的Web應用程式的元件。 MVC模式導緻分離應用程式的不同方面(輸入邏輯,業務邏輯和UI邏輯),同時提供這些元素之間的松散耦合。

模型封裝了應用程式資料,通常它們将包含POJO。

View負責渲染模型資料,通常它會生成用戶端浏覽器可以解釋的HTML輸出。

Controller負責處理使用者請求并建構适當的模型,并将其傳遞給視圖進行渲染。

1.1.The DispatcherServlet

Spring Web模型 - 視圖 - 控制器(MVC)架構是圍繞一個DispatcherServlet設計的,它處理所有的HTTP請求和響應。 Spring Web MVC DispatcherServlet的請求處理工作流程如下圖所示 

Setting Up Swagger 2 with a Spring REST API

以下是與傳入的到DispatcherServlet的HTTP請求相對應的事件序列 

接收到HTTP請求後,DispatcherServlet會查詢HandlerMapping來調用相應的Controller。

Controller接收請求并根據使用的GET或POST方法調用适當的服務方法。 服務方法将根據定義的業務邏輯設定模型資料,并将視圖名稱傳回給DispatcherServlet。

DispatcherServlet将從ViewResolver擷取幫助以擷取請求的已定義視圖。

View完成後,DispatcherServlet将模型資料傳遞給最終在浏覽器中呈現的視圖。

所有上述元件,即HandlerMapping,Controller和ViewResolver都是WebApplicationContext的一部分,它是plainApplicationContext的擴充,并帶有Web應用程式所需的一些額外功能。

1.2.所需的配置

您需要映射您希望DispatcherServlet處理的請求,方法是使用web.xml檔案中的URL映射。 以下是顯示HelloWorld-SpringMVC-SwaggerUI DispatcherServlet示例的聲明和映射的示例 -

Setting Up Swagger 2 with a Spring REST API

web.xml檔案将儲存在Web應用程式的webapp/ WEB-INF目錄中。 HelloWorld-SpringMVC-SwaggerUI DispatcherServlet初始化後,架構将嘗試從位于應用程式的webapp/ WEB-INF目錄中的名為[servlet-name] -servlet.xml的檔案加載應用程式上下文。 在這種情況下,我們的檔案将是HelloWorld-SpringMVC-SwaggerUI-servlet.xml。

接下來,<servlet-mapping>标簽訓示哪個URL将由哪個DispatcherServlet處理。 這裡所有以.jsp結尾的HTTP請求都将由HelloWorld-SpringMVC-SwaggerUI DispatcherServlet處理。

如果您不想使用預設檔案名作為[servlet-name] -servlet.xml和預設位置為webapp/ WEB-INF,則可以通過在web.xml檔案中添加servlet偵聽器ContextLoaderListener來自定義此檔案名和位置 如下 -

Setting Up Swagger 2 with a Spring REST API

現在,讓我們檢查放置在Web應用程式的webapp/ WEB-INF目錄中的HelloWorld-SpringMVC-SwaggerUI-servlet.xml檔案所需的配置 -

Setting Up Swagger 2 with a Spring REST API

以下是關于HelloWorld-SpringMVC-SwaggerUI-servlet.xml檔案的要點 - 

[servlet-name] -servlet.xml檔案将用于建立定義的bean,覆寫在全局範圍内定義的具有相同名稱的任何bean的定義。

<context:component-scan ...>标簽将用于激活Spring MVC注釋掃描功能,允許使用@Controller和@RequestMapping等注釋。

InternalResourceViewResolver将具有定義的規則來解析視圖名稱。 按照上面定義的規則,名為hello的邏輯視圖被委托給位于/WEB-INF/jsp/hello.jsp的視圖實作。

以下部分将向您展示如何建立實際的元件,即Controller,Model和View。

1.3.定義一個控制器

DispatcherServlet将請求委托給控制器執行特定的功能。 @Controllerannotation表示一個特定的類服務于控制器的角色。 @RequestMapping注解用于将URL映射到整個類或特定的處理程式方法。

Setting Up Swagger 2 with a Spring REST API

@Controller批注将該類定義為一個Spring MVC控制器。 在這裡,@RequestMapping的第一個用法表示這個控制器上的所有處理方法都是相對于/ hello路徑的。 下一個注釋@ RequestMapping(method = RequestMethod.GET)用于聲明printHello()方法作為控制器的預設服務方法來處理HTTP GET請求。 您可以定義另一個方法來處理同一個URL上的任何POST請求。

你可以用另一種形式寫上述控制器,你可以在@RequestMapping中添加其他屬性,如下所示 -

Setting Up Swagger 2 with a Spring REST API

值屬性訓示處理程式方法映射到的URL,方法屬性定義處理HTTP GET請求的服務方法。 關于上面定義的控制器,要注意以下幾點:

您将在服務方法中定義所需的業務邏輯。 您可以根據需要調用此方法中的另一個方法。

根據定義的業務邏輯,您将在此方法中建立一個模型。 您可以使用setter不同的模型屬性,這些屬性将被視圖通路以呈現最終結果。 這個例子建立了一個屬性為“message”的模型。

定義的服務方法可以傳回一個字元串,其中包含要用于呈現模型的視圖的名稱。 這個例子傳回“hello”作為邏輯視圖名稱。

1.4.建立JSP視圖

Spring MVC為不同的表示技術支援多種類型的視圖。 這些包括:JSP,HTML,PDF,Excel工作表,XML,Velocity模闆,XSLT,JSON,Atom和RSS feeds,JasperReports等。但是最常用的是使用JSTL編寫的JSP模闆。

讓我們在/WEB-INF/hello/hello.jsp中寫一個簡單的hello視圖 -

<html>
    <head>
        <title>HelloWorld-SpringMVC-SwaggerUI</title>
    </head>
    <body>
        <h2>${message}</h2>
    </body>
</html>      

這裡$ {message}是我們在Controller中設定的屬性。 您可以在視圖中顯示多個屬性。

二:Swagger和Swagger UI

Swagger是全球最大的OpenAPI規範(OAS)API開發工具架構,支援從設計和文檔到測試和部署的整個API生命周期的開發。

Swagger UI允許任何人 - 無論是你的開發團隊還是你的最終使用者 - 都可以在沒有任何實作邏輯的情況下對API資源進行可視化和互動。 它是根據Swagger規範自動生成的,通過可視化文檔使後端實作和用戶端消耗變得容易。

2.1将Swagger UI內建到Spring MVC中

2.2增加swagger和swagger-ui的依賴

<!--swagger2 start-->
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.5.0</version>
    </dependency>
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.5.0</version>
    </dependency>
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-staticdocs</artifactId>
      <version>2.5.0</version>
    </dependency>
    <!--swagger2 start-->      

2.3編寫一個自定義的Swagger配置類

package com.micai.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
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;

/**
 * 描述:Swagger配置類
 * <p>
 * Author: 趙新國
 * Date: 2017/12/18 13:27
 */
@Configuration
@EnableSwagger2
public class MySwaggerConfig extends WebMvcConfigurerAdapter {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.micai.controller"))
                .paths(PathSelectors.ant("/api/**"))
                .build()
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring 中使用Swagger2建構RESTful APIs")
                .termsOfServiceUrl("http://localhost:8080/HelloWorld-SpringMVC-SwaggerUI/v2/api-docs")
                .contact("My Swagger")
                .version("1.0.0")
                .build();
    }

}      

2.4編寫需要通過swagger-ui展示的類

package com.micai.controller;

import com.micai.constant.Constants;
import com.micai.constant.Result;
import com.micai.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;

/**
 * 描述:
 * <p>
 * Author: 趙新國
 * Date: 2017/12/18 17:10
 */
@Api(value = "使用者管理", description = "使用者管理")
@RestController
@RequestMapping("/api/user")
public class UserController {

    private static final Map<String, List<User>> map;

    private static List<User> users = new ArrayList<User>();

    static {
        map = new HashMap<String, List<User>>(16);
        User user1 = new User();
        user1.setId(1);
        user1.setName("張三");
        user1.setAge(23);
        User user2 = new User();
        user2.setId(2);
        user2.setName("李四");
        user2.setAge(25);
        User user3 = new User();
        user3.setId(3);
        user3.setName("王五");
        user3.setAge(26);
        users.add(user1);
        users.add(user2);
        users.add(user3);
        map.put("users", users);
    }

    @ApiOperation(value = "擷取全部使用者", notes = "擷取全部使用者")
    @RequestMapping(value = "/getUsers", method = RequestMethod.GET)
    public Result<Map<String, List<User>>> getUsers() {
        return new Result<Map<String, List<User>>>(Constants.SUCCESS, Constants.MSG_SUCCESS, map);
    }

    @ApiOperation(value = "添加使用者", notes = "添加使用者")
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public Result<User> addUser(@ApiParam(name = "id",value = "使用者ID",required = true) @RequestParam(name = "id",required = true) Integer id,
                                @ApiParam(name = "name",value = "使用者名稱",required = true) @RequestParam(name = "name",required = true) String name,
                                @ApiParam(name = "age",value = "使用者年齡",required = true) @RequestParam(name = "age",required = true) Integer age) {
        User user = new User();
        user.setId(id);
        user.setName(name);
        user.setAge(age);
        users.add(user);
        map.put("users", users);
        return new Result<User>(Constants.SUCCESS, Constants.MSG_SUCCESS, user);
    }

    @ApiOperation(value = "根據ID擷取使用者", notes = "根據ID擷取使用者")
    @RequestMapping(value = "/getUser/{id}", method = RequestMethod.GET)
    public Result<User> getUser(@Valid @PathVariable("id") int id) {
        Set<Map.Entry<String, List<User>>> entries = map.entrySet();
        Iterator<Map.Entry<String, List<User>>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, List<User>> next = iterator.next();
            List<User> users = next.getValue();
            for (User user : users) {
                if (user.getId().equals(id)) {
                    return new Result<User>(Constants.SUCCESS, Constants.MSG_SUCCESS, user);
                }
            }
        }
        return new Result<User>(Constants.SUCCESS, Constants.MSG_SUCCESS, null);
    }

    @ApiOperation(value = "根據ID修改使用者", notes = "根據ID修改使用者")
    @RequestMapping(value = "/updateUser/{id}", method = RequestMethod.PUT)
    public Result<User> updateUser(@Valid @PathVariable("id") int id, @RequestBody User record) {
        Set<Map.Entry<String, List<User>>> entries = map.entrySet();
        Iterator<Map.Entry<String, List<User>>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, List<User>> next = iterator.next();
            List<User> users = next.getValue();
            for (User user : users) {
                if (user.getId().equals(id)) {
                    users.remove(user);
                    User user1 = new User();
                    user1.setId(id);
                    user1.setName(record.getName());
                    user1.setAge(record.getAge());
                    users.add(user1);
                    map.put("users", users);
                    return new Result<User>(Constants.SUCCESS, Constants.MSG_SUCCESS, user1);
                }
            }
        }
        return new Result<User>(Constants.SUCCESS, Constants.MSG_SUCCESS, null);
    }

    @ApiOperation(value = "根據ID删除使用者", notes = "根據ID删除使用者")
    @RequestMapping(value = "/deleteUser/{id}", method = RequestMethod.DELETE)
    public Result<Map<String, List<User>>> deleteUser(@Valid @PathVariable("id") int id) {
        Set<Map.Entry<String, List<User>>> entries = map.entrySet();
        Iterator<Map.Entry<String, List<User>>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, List<User>> next = iterator.next();
            List<User> users = next.getValue();
            for (User user : users) {
                if (user.getId().equals(id)) {
                    users.remove(user);
                    map.put("users", users);
                    return new Result<Map<String, List<User>>>(Constants.SUCCESS, Constants.MSG_SUCCESS, map);
                }
            }
        }
        return new Result<Map<String, List<User>>>(Constants.SUCCESS, Constants.MSG_SUCCESS, null);
    }

}      

2.5

通路Swagger,檢視Rest Api接口

通路位址:http://localhost:8080/HelloWorld-SpringMVC-SwaggerUI/swagger-ui.html

Setting Up Swagger 2 with a Spring REST API

以上就是SpringMVC內建Swagger的全部過程

最後附上我寫的源代碼下載下傳位址:​​https://gitee.com/micai/HelloWorld-SpringMVC-SwaggerUI​​

參考位址:

​​https://www.concretepage.com/spring-4/spring-rest-swagger-2-integration-with-annotation-xml-example#endpoint​​

​​http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api​​