天天看点

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​​