SpringBoot系列之Springboot集成Swagger

1. Swagger的产生

 我们的RESTful API需要面对多个开发人员或多个开发团队:IOS开发、Android开发或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题:

 由于接口众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容等),高质量地创建这份文档本身就是件非常吃力的事,下游的抱怨声不绝于耳。

 随着时间推移,不断修改接口实现的时候都必须同步修改接口文档,而文档与代码又处于两个不同的媒介,除非有严格的管理机制,不然很容易导致不一致现象。

 Swagger的产生就是为了解决以上这些问题。

2. Swagger的介绍

 Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。Swagger 让部署管理和使用功能强大的API从未如此简单。

 接下来我们介绍spring boot怎么集成swagger。

3. 新建maven java project

 新建一个maven java project取名为:spring-boot-Swagger

4. 在pom.xml添加依赖

 主要是springfox-swagger2和springfox-swagger-ui,版本号根据决定

<!-- Swagger -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
</dependency>

5. 创建Swagger2配置类

 编写一个swagger配置类,com.config.SwaggerConfig:

package com.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.async.DeferredResult;
import com.google.common.base.Predicates;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Swagger配置类:
 * @author Angel --守护天使
 * @version v.0.1
 * @date 2016年9月7日
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    /**
     * SpringBoot默认已经将classpath:/META-INF/resources/和classpath:/META-INF/resources/webjars/映射
     * 所以该方法不需要重写,如果在SpringMVC中,可能需要重写定义(我没有尝试)
     * 重写该方法需要 extends WebMvcConfigurerAdapter
     *
     */
//    @Override
//    public void addResourceHandlers(ResourceHandlerRegistry registry) {
//        registry.addResourceHandler("swagger-ui.html")
//                .addResourceLocations("classpath:/META-INF/resources/");
//
//        registry.addResourceHandler("/webjars/**")
//                .addResourceLocations("classpath:/META-INF/resources/webjars/");
//    }
    /**
     * 可以定义多个组,比如本类中定义把test和demo区分开了
     * (访问页面就可以看到效果了)
     *
     */
    @SuppressWarnings("unchecked")
    @Bean
    public Docket testApi(){
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName("test")
                .genericModelSubstitutes(DeferredResult.class)
                .useDefaultResponseMessages(false)
                .forCodeGeneration(true)
                .pathMapping("/")// base,最终调用接口后会和paths拼接在一起
                .select()
                .paths(Predicates.or(PathSelectors.regex("/api/.*")))//过滤的接口
                .build()
                .apiInfo(testApiInfo());
        return docket;
    }
    @SuppressWarnings("unchecked")
    @Bean
    public Docket demoApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("demo")
                .genericModelSubstitutes(DeferredResult.class)
//              .genericModelSubstitutes(ResponseEntity.class)
                .useDefaultResponseMessages(false)
                .forCodeGeneration(false)
                .pathMapping("/")
                .select()
                .paths(Predicates.or(PathSelectors.regex("/demo/.*")))//过滤的接口
                .build()
                .apiInfo(demoApiInfo());
    }
    private ApiInfo testApiInfo() {
        ApiInfo apiInfo = new ApiInfo("Test相关接口",//大标题
                "Test相关接口,主要用于测试.",//小标题
                "1.0",//版本
                "https://blog.csdn.net/qq_34638225",
                "猿小雷",//作者
                "猿小雷的博客",//链接显示文字
                "https://blog.csdn.net/qq_34638225"//网站链接
        );
        return apiInfo;
    }
    private ApiInfo demoApiInfo() {
        ApiInfo apiInfo = new ApiInfo("Demo相关接口",//大标题
                "Demo相关接口,获取个数,获取列表,注意:",//小标题
                "1.0",//版本
                "https://blog.csdn.net/qq_34638225",
                "猿小雷",//作者
                "猿小雷的博客",//链接显示文字
                "https://blog.csdn.net/qq_34638225"//网站链接
        );
        return apiInfo;
    }
}

 上代码所示,通过@Configuration注解,让Spring来加载该类配置。再通过@EnableSwagger2注解来启用Swagger2。

 再通过createRestApi函数创建Docket的Bean之后,apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现

 经过这2步配置后,我们启动服务后,访问:http://localhost:8080/swagger-ui.html 就完成了集成。

 下面编写2个controller进行测试;

6.编写controller测试类

package com.controller;

import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.bean.Demo;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestBody;
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.ApiOperation;
import springfox.documentation.annotations.ApiIgnore;

/**
 * DemoController
 *
 */
@Controller
@RequestMapping(value = "/demo")
public class DemoController {

    private Logger logger = LoggerFactory.getLogger(DemoController.class);
    /**
     * 可以直接使用@ResponseBody响应JSON
     *
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getcount", method = RequestMethod.POST)
    @ApiOperation(value="测试-getCount", notes="getCount更多说明")
    public ModelMap getCount(HttpServletRequest request,
                             HttpServletResponse response) {
        logger.info(">>>>>>>> begin getCount >>>>>>>>");
        ModelMap map = new ModelMap();
        map.addAttribute("count", 158);
        // 后台获取的国际化信息
        map.addAttribute("xstest", "测试");
        return map;
    }
    /**
     * 可以直接使用@ResponseBody响应JSON
     *
     * @param request
     * @param response
     * @return
     */
    @ApiIgnore//使用该注解忽略这个API
    @ResponseBody
    @RequestMapping(value = "/jsonTest1", method = RequestMethod.POST)
    public ModelMap jsonTest(HttpServletRequest request,
                             HttpServletResponse response) {
        ModelMap map = new ModelMap();
        map.addAttribute("hello", "你好");
        map.addAttribute("veryGood", "很好");
        return map;
    }
    /**
     * 可以直接使用@ResponseBody响应JSON
     *
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/jsonTest3", method = RequestMethod.POST)
    public List<String> jsonTest3(HttpServletRequest request,
                                  HttpServletResponse response) {
        List<String> list = new ArrayList<String>();
        list.add("hello");
        list.add("你好");
        return list;
    }
    /**
     * JSON请求一个对象<br/>
     * (Ajax Post Data:{"name":"名称","content":"内容"})
     *
     * @param
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/jsonTest2", method = RequestMethod.POST)
    public ModelMap jsonTest2(@RequestBody Demo demo) {
        logger.info("demoName:" + demo.getName());
        logger.info("demoContent:" + demo.getContent());
        ModelMap map = new ModelMap();
        map.addAttribute("result", "ok");
        return map;
    }
    /**
     * 直接读取URL参数值<br/>
     * /demo/jsonTest6.do?name=Hello&content=World
     *
     * @param demoName
     * @param content
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/jsonTest6", method = RequestMethod.POST)
    public ModelMap jsonTest6(@RequestParam("name") String demoName, @RequestParam String content) {
        logger.info("demoName:" + demoName);
        ModelMap map = new ModelMap();
        map.addAttribute("name",demoName + "AAA");
        map.addAttribute("content",content + "BBB");
        map.addAttribute("date",new java.util.Date());
        return map;
    }
    /**
     * JSON请求一个对象,将RequestBody自动转换为JSONObject对象<br/>
     * (Ajax Post Data:{"name":"名称","content":"内容"})
     *
     * 使用JSONObject请添加依赖
     *  <dependency>
     *      <groupId>net.sf.json-lib</groupId>
     *      <artifactId>json-lib</artifactId>
     *      <version>2.4</version>
     *      <!--指定jdk版本 -->
     *      <classifier>jdk15</classifier>
     *  </dependency>
     *
     * @param
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/jsonTest5", method = RequestMethod.POST)
    public ModelMap jsonTest5(@RequestBody JSONObject jsonObject) {
        String name = jsonObject.getString("name");
        logger.info("demoName:" + name);
        ModelMap map = new ModelMap();
        map.addAttribute("demoName",name);
        return map;
    }
    /**
     * 输入和输出为JSON格式的数据的方式 HttpEntity<?> ResponseEntity<?>
     *
     * @param
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/jsonTest4", method = RequestMethod.POST)
    public ResponseEntity<String> jsonTest4(HttpEntity<Demo> demo,
                                            HttpServletRequest request, HttpSession session) {
        //获取Headers方法
        HttpHeaders headers = demo.getHeaders();
        // 获取内容
        String demoContent = demo.getBody().getContent();
        // 这里直接new一个对象(HttpHeaders headers = new HttpHeaders();)
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add("MyHeaderName", "SHANHY");
        ResponseEntity<String> responseResult = new ResponseEntity<String>(
                demoContent, responseHeaders, HttpStatus.OK);
        return responseResult;
    }
}
package com.controller;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.stereotype.Controller;
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;

/**
 * Created by Administrator on 2017/8/16.
 */
@Controller
@RequestMapping("/api/test")
public class TestController {

    @ResponseBody
    @RequestMapping(value = "/show",method = RequestMethod.POST)//这里指定RequestMethod,如果不指定Swagger会把所有RequestMethod都输出,在实际应用中,具体指定请求类型也使接口更为严谨。
    @ApiOperation(value="测试接口",notes = "测试接口详细描述")
    public String show(
            @ApiParam(required = true,name = "name",value = "姓名")
            @RequestParam(name="name") String stuName){
        return "success";
    }
}
package com.bean;

/**
 * Created by Administrator on 2017/8/16.
 */
public class Demo {

    private long id;
    private String name;
    private String content;

    public long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

 Swagger2默认将所有的Controller中的RequestMapping方法都会暴露,然而在实际开发中,我们并不一定需要把所有API都提现在文档中查看,这种情况下,使用注解@ApiIgnore来解决,如果应用在Controller范围上,则当前Controller中的所有方法都会被忽略,如果应用在方法上,则对应用的方法忽略暴露API。

 在访问http://localhost:8080/swagger-ui.html就可以看到如下效果:

这里写图片描述


关注公众号:猿小雷
获取更多文章,第一之间掌握技术。
有问题请在公众号内回复,小雷会一一回答。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_34638225/article/details/81268209