前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

swagger为项目的api规范文档,帮助我们进行开发的。在找不同游戏中有详细用到。

注解 属性 备注
@Api value 字符串 可用在class头上,class描述
description 字符串
@Api(value = "xxx", description = "xxx")
@ApiOperation value 字符串 可用在方法头上.参数的描述容器
notes 字符串 说明
httpMethod 字符串 请求方法
@ApiOperation(value = "xxx", notes = "xxx", method = "GET")
@ApiImplicitParams {} @ApiImplicitParam数组 可用在方法头上.参数的描述容器
@ApiImplicitParams({@ApiImplicitParam1,@ApiImplicitParam2,...})
@ApiImplicitParam name 字符串 与参数命名对应 可用在@ApiImplicitParams
value 字符串 参数中文描述
required 布尔值 true/false
paramType 字符串 参数请求方式:query/path
query:对应@RequestParam传递
path: 对应@PathVariable{}path传递
dataType 字符串 参数类型
dataTypeClass 参数对应的类
defaultValue 字符串 在api测试中默认值
@ApiImplicitParam(name = "newProduct", value = "商品信息对象", required = true, dataType = "Product", dataTypeClass = Product.class)
@ApiResponses {} @ApiResponse数组 可用在方法头上.参数的描述容器
@ApiResponses({@ApiResponse1,@ApiResponse2,...})
@ApiResponse code 整形 可用在@ApiResponses
message 字符串 错误描述
response 返回结果对应的类
@ApiResponse(code = 200, message = "Successful", response = CommonResponse.class)
@ApiModelProperty name 字符串 实体类参数名称
value 字符串 实体类参数值
notes 字符串 说明
example 字符串 返回值model中查看举例
@ApiModelProperty(name = "name", value = "name", notes = "名称",example = "张三")

1、项目构建

1.1、pom依赖

		<!--swagger 版本-->
		<swagger.version>2.7.0</swagger.version>
		
		<!--swagger-->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>${swagger.version}</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>${swagger.version}</version>
		</dependency>

全部pom文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.hlj.swagger</groupId>
	<artifactId>com-hlj-swagger</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>com-hlj-swagger</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<!--swagger 版本-->
		<swagger.version>2.7.0</swagger.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!--swagger-->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>${swagger.version}</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>${swagger.version}</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>


1.2、SpringBoot添加配置config支持swagger

1、添加扫描路径com下的所有的api文件 2、api文件的说明,也就是标题。自己随意设置喽


package com.hlj.swagger.config;

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

//import springfox.documentation.service.Contact;

@EnableSwagger2
@Configuration
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com"))//扫描com路径下的api文档
                .paths(PathSelectors.any())//路径判断
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Swagger 开发规范")//标题
                .description("Saggger 开发规范详文档细地址(HealerJean博客)--->>>>>>>:http://blog.healerjean.top/")//描述
                .termsOfServiceUrl("http://blog.healerjean.top/")//(不可见)条款地址
                .version("1.0.0")//版本号
                .contact(new Contact("试客","http://appshike.com","pengzhi.gao@duodian.com"))
                .build();
    }

}

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

    @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/");
        registry.addResourceHandler("/public/**").addResourceLocations("classpath:/public/");
        registry.addResourceHandler("/**").addResourceLocations("");
        super.addResourceHandlers(registry);
    }

}

1.3、启动tomcat进行观察

这里我的端口设置了8082

http://localhost:8082/swagger-ui.html#/

WX20180326-103236@2x

2、开始添加一个demo

2.1、返回的实体对象

2.1.1、@ApiModel(description = “我是User描述”) 


对实体的描述,其实也没什么用,可以直接不填。比如,找不同就没有填

2.1.2、@ApiModelProperty(value = “用户的姓名,比如’李四’” ,hidden = true)

关于 boolean的字段

1、实体类中尽量不要用 isTaobao,不要用is,如果有了则不会在接口文档中出现。

2、如果希望出现,则需要在下面ApiImplicitParam参数声明中进行添加,而使用name=”isTaobao“本身就会因为java的关系,传递参数进来无效 ,boolean类型的json格式化之后会变成taobao,

  @ApiImplicitParam(name = "isTaobao", value = "是否淘宝", required = true, paramType = "query", dataType = "string"),
private boolean isTaobao ;

3、正确写法应该是如下


  @ApiImplicitParam(name = "taobao", value = "是否淘宝", required = true, paramType = "query", dataType = "string"),
private boolean isTaobao ;
1、hidden = true,字段隐藏,不在前面展示

notes 对字段的描述 1、可以作为返回结果的描述和 2、关于User对象参数时候的内部参数的描述

2、name 实体类参数名字,(写上去没有用,亲试,不起作用)

3、example (并不是提供默认值)

   @ApiModelProperty(value = "用户的姓名,比如'李四'",example = "张三",dataType = "string",notes="notes")
    private String name;

WX20190131-154738@2x

package com.hlj.swagger.bean;

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

@ApiModel
public class User {

    @ApiModelProperty(value = "用户的姓名,比如'李四'")
    private String name;
    @ApiModelProperty(value = "id",required = true)
    private String id;
    @ApiModelProperty(value = "用户的年龄,比如:20")
    private Integer age;

    @ApiModelProperty(value = "用户的子类,测试用",required = true)
    private Base base;


	get set 省略



下面这个是嵌入类,一定要添加无参构造函数,否则不能初始化它

package com.hlj.swagger.bean;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(description = "User内部对象")
public class Base {
    @ApiModelProperty(value = "baseId,比如:20")
    private int baseId;

    public int getBaseId() {
        return baseId;
    }

    public void setBaseId(int baseId) {
        this.baseId = baseId;
    }
   //必须添加
    public Base() {
    }

    public Base(int baseId) {
        this.baseId = baseId;
    }
}



2.2、controler

2.2.1、@Api 标记一个Controller类做为swagger文档资源,以及该Controller的描述

@Api(value = “用户管理”,description = “用户管理”)

通过上面两个图片,所以以后我们只写description就可以,看起来方便

@Controller
@RequestMapping("duodian")
@Api(description = "优惠券商品控制器")
public class CouponItemGoodController {

WX20180612-101945@2x

@Controller
@RequestMapping("duodian")
@Api(tags = "推广位操作接口",description = "推广位控制器",value = "推广位value")
public class CouponAdzoneController {


WX20180612-102054@2x

2.2.2、 @ApiOperation每一个url资源的说明,可以随意定制返回的类型

@ApiOperation(value = “获取用户列表”,notes = “根据url的id来获取用户详细信息,返回List类型用户信息的JSON;")

2.2.3、@ApiImplicitParams 入参的描述

1、name 参数名称

2、value,参数说明

3、required 参数是否必填,当出现参数为对象时候,对象中的必填项可以在实体中 ApiModelProperty进行编辑

4、paramType 无关Get和Post方法 query:对应@RequestParam传递 path: 对应@PathVariable{}path传递 对象则不需要配置

5、defaultValue 默认值

6、

6、dataType (一般是一些基本数据类型,没有dataTypeClass ,可以使用它,也可以同时使用)

如果是实体类, dataType = “Product”, dataTypeClass = Product.class)

dataType = "java.lang.Integer"
dataType ="int"

dataTypeClass = Long.class
@ApiImplicitParams({
     @ApiImplicitParam(name = "id",
            					value = "用户Id", 
            					required = true, 
            					paramType = "query"
            					dataType = "string")
package com.hlj.swagger.controller;

import com.hlj.swagger.bean.Base;
import com.hlj.swagger.bean.User;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@Api(value = "用户管理",description = "用户管理")
@RestController
@RequestMapping("/user")
public class UserController {

Logger log = LoggerFactory.getLogger(UserController.class);

@ApiOperation(value = "获取用户列表", notes = "根据url的id来获取用户详细信息,返回List<User>类型用户信息的JSON;")
@ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "query",dataType = "string")

})
@GetMapping("one")
public List<User> getUserBagOne(String id) {
    List<User> users = new ArrayList<>();
    try {
        if (id.equals("1")) {
            users.add(new User("HealerJean", "1", 24, new Base(1)));
        } else {
            users.add(new User("huangliang", "2", 25, new Base(2)));
        }
        return users;
    } catch (Exception e) {
        return users;
    }

}
}

2.3、浏览器启动,开始测试

http://localhost:8081/swagger-ui.html#/

WX20180326-135830@2x

解释上面为返回值,下面为输入参数

WX20180326-141124@2x

可以看到下面中会出现这个url的描述,以及请求参数和返回的结果举例,点击Model会看到结果参数的说明

WX20180326-122416@2x


WX20180326-135736@2x

2.3.1 输入参数id为1 和2分别查看结果 try it out

WX20180326-140019@2x

3、修改2中获取结果的对象,设置为包装对象Response

3.1、包装对象

这里其实可以清晰的看到下面data其实就是我们正儿八经返回的结果

package com.hlj.swagger.common;


/**
 * @author fengchuanbo
 */
public class Response<T> {

    /**
     * 返回code
     */
    private String code;
    /**
     * 返回描述
     */
    private String desc;
    /**
     * 返回数据
     */
    private T data;

    public Response(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public Response(Code code) {
        this.code = code.getCode();
        this.desc = code.getDesc();
    }

    public Response(Code code, T data) {
        this.code = code.getCode();
        this.desc = code.getDesc();
        this.data = data;
    }

    /**
     * 成功响应
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Response<T> success(T t){
        return new Response<>(Code.OK, t);
    }

    /**
     * 成功响应,date为空
     * @return
     */
    public static Response success(){
        return new Response(Code.OK);
    }

    /**
     * 参数错误
     * @return
     */
    public static Response illegalArgument(){
        return new Response(Code.illegalArgument);
    }


    /**
     * 自定义返回
     * @param code
     * @param desc
     * @return
     */
    public static <T> Response of(String code,String desc, T t){
        return new Response(code,desc,t);
    }


    /**
     * 自定义返回
     * @param code
     * @param desc
     * @return
     */
    public static Response of(String code,String desc){
        return new Response(code,desc);
    }


    /**
     * 自定义返回
     * @param code
     * @param t
     * @return
     */
    public static <T> Response of(Code code, T t){
        return new Response(code,t);
    }

    /**
     * 自定义返回
     * @param code
     * @return
     */
    public static Response of(Code code){
        return new Response(code);
    }


    /**
     * 系统错误
     * @return
     */
    public static Response error() {
        return new Response(Code.ERROR);
    }

	get set 省略

}


3.2、修改controller中的方法

1、修改 ApiOperation(实施说明) 中添加返回数据格式就可以,如下

@ApiOperation(value = "获取用户列表",
						notes = "根据url的id来获取用户详细信息,返回List<User>类型用户信息的JSON;",
						response = User.class,responseContainer = "List",//包含list集合,如果不是list集合可以不写其他只写response类即可,即使是被包装的即可
						//application/json 返回结果的类型
						produces = MediaType.APPLICATION_JSON_VALUE,
						//multipart/form-data,传入的的数据格式Post
						consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
						
	

						
get 请求
consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE

post 请求 
consumes = MediaType.MULTIPART_FORM_DATA_VALUE		
							
						@ApiOperation(value = "获取分类列表", notes = "0[OK];", response = TQuestionVO.class, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@GetMapping("getCategoryList")
public Wrapper<?> getCategoryList(String name,Short classify, PageQuery pageQuery){
      return WrapMapper.ok(page);
}

@ApiOperation(value = "添加分类",notes = "0[OK];",response = Wrapper.class,produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@PostMapping("addCategory")
public Wrapper<?> addCategory(@RequestBody TVideoCategory category) throws IOException {
    return zqCategoryService.addCategory(category);
}



@ApiOperation(value = "获取用户列表",notes = "根据url的id来获取用户详细信息,返回List<User>类型用户信息的JSON;",response = User.class,responseContainer = "List",produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "query",dataType = "string")

})
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "Successful — 请求已完成"),
        @ApiResponse(code = 400, message = "请求中有语法问题,或不能满足请求"),
        @ApiResponse(code = 401, message = "未授权客户机访问数据"),
        @ApiResponse(code = 404, message = "服务器找不到给定的资源;文档不存在"),
        @ApiResponse(code = 500, message = "服务器不能完成请求")}
)
@GetMapping("two")
public Response<?> getUserBagTwo(String id){
    List<User> users = new ArrayList<>();
    try {
        if(id.equals("1")) {
            users.add(new User("HealerJean", "1", 24, new Base(1)));
        }else {
            users.add(new User("huangliang", "2", 25, new Base(2)));
        }
        return Response.success(users);
    }catch (Exception e){
        return Response.error();
    }

}

2、运行项目(这个时候我将第一个demo路径修改成了one,本次为two)

WX20180326-123635@2x

这个时候,就看到其实是List(User)中的内容了。而不是Response对象中的内容

WX20180326-123709@2x

4、添加系统提供的http返回状态码描述

1、ApiResponses

@ApiResponses(value = {
        @ApiResponse(code = 200, message = "Successful — 请求已完成"),
        @ApiResponse(code = 400, message = "请求中有语法问题,或不能满足请求"),
        @ApiResponse(code = 401, message = "未授权客户机访问数据"),
        @ApiResponse(code = 404, message = "服务器找不到给定的资源;文档不存在"),
        @ApiResponse(code = 500, message = "服务器不能完成请求")}
)


@ApiOperation(value = "获取用户列表",notes = "根据url的id来获取用户详细信息,返回List<User>类型用户信息的JSON;",response = User.class,responseContainer = "List",produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "string")

})
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "Successful — 请求已完成"),
        @ApiResponse(code = 400, message = "请求中有语法问题,或不能满足请求"),
        @ApiResponse(code = 401, message = "未授权客户机访问数据"),
        @ApiResponse(code = 404, message = "服务器找不到给定的资源;文档不存在"),
        @ApiResponse(code = 500, message = "服务器不能完成请求")}
)
@GetMapping("two")
public Response<?> getUserBagTwo(String id){
    List<User> users = new ArrayList<>();
    try {
        if(id.equals("1")) {
            users.add(new User("HealerJean", "1", 24, new Base(1)));
        }else {
            users.add(new User("huangliang", "2", 25, new Base(2)));
        }
        return Response.success(users);
    }catch (Exception e){
        return Response.error();
    }

}

之前 WX20180326-132132@2x

之后

WX20180326-132053@2x

5、根据id-/{id}获取User

1、paramType = “path” 表示在请求头上直接写入参数

1、controller

    @ApiOperation(value = "根据id获取用户详细信息", notes = "根据url的id来获取用户详细信息")
    //描述容器
    @ApiImplicitParam(name = "id", value = "用户ID", required = true,  paramType = "path",dataType = "long",dataTypeClass = Long.class)
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public User getUser(String id) {
        return new User("HealerJean", id, 24, new Base(1));
    }


WX20180326-141020@2x

6、Post方法传入User对象参数

6.1、user 不需要配置 paramType ,配置下面这个,默认是body,

@ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User"),


@ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
@ApiImplicitParams({
        @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User"),
        @ApiImplicitParam(name = "flag", value = "是否开启标志位", paramType = "query", dataType = "boolean"),
        @ApiImplicitParam(name = "version", value = "版本号", required = true, paramType = "query", dataType = "string")

})
@RequestMapping(value = "", method = RequestMethod.POST)
public User postUser(User user, @RequestParam(defaultValue = "false") boolean flag, String version) {
    log.info(flag+"");
    log.info(version);
    return user;
}




6.1.1、开始测试

1、user 对象也不需要输入值,只输入{}即可,前台不会接受,因为前台没有写@requestbody,而是普通的form表单接收的 2、测试成功

错误分析:如果当调用得到base.baseId输入后台报错的时候,说明base中没有空构造函数导致不能初始化。

WX20180326-144606@2x

WX20180326-144637@2x

6.2、不显示Json只显示实体的属性

6.2.1、不显示Json只显示实体的属性,只方法中加上传入参数的对象即可

WX20180426-190305@2x

@RequestPart(value = "videoFile",required = false)MultipartFile videoFile,
@ApiOperation(value = "添加视频",notes = "0[OK];",response = Wrapper.class,produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiResponse(code = 200,message = "code=0,desc=OK")
@PostMapping("add")
public Wrapper<?> add(@RequestPart(value = "videoFile",required = false)MultipartFile videoFile, @RequestPart(value="imgFile",required = false)MultipartFile imgFile,TVideo video) throws IOException {
    return zqVideoService.add(videoFile,imgFile, video);
}


@ApiOperation(value = "上传Excel",notes = "上传Excel",
        consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
        produces = MediaType.APPLICATION_JSON_VALUE,
        response = ResponseBean.class)
@PostMapping("uploadExcel")
@ResponseBody
public ResponseBean uploadBusinessPic(MultipartFile file){

6.3、补充不显示实体的属性,只显示json

6.3.1、方法中只使用注解@RequestBody,

WX20180426-190229@2x

@ApiOperation(value = "添加TAG",notes = "0[OK];",response = Wrapper.class,produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiResponse(code = 200,message = "code=0,desc=OK")
@PostMapping("addCategoryTag")
public Wrapper<?> addCategoryTag(@RequestBody TVideoCategoryTag tag) throws IOException {
    return zqCategoryService.addCategoryTag(tag);
}

3、有时候为了不让某些开发者看到,可以使用

@ApiIgnore 注解

代码下载

ContactAuthor