用Swagger生成SpringBoot接口文档

目录

一,原始项目说明

二,引入Swagger

三,Swagger首页

四,Swagger注解使用

1,@Api

2,@ApiOperation

3,@ApiImplicitParam和@ApiImplicitParams

4,@ApiResponse和@ApiResponses

5,@ApiModel和@ApiModelProperty

6,@ResponseHeader


一,原始项目说明

首先,我找了一个Springboot+SpringCloud的项目,里面没什么东西,是个最简单的服务,比如这样:

启动类:

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class ConsumerRibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerRibbonApplication.class, args);
    }

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

一个Controller:

@RestController
public class HiController {

    @Autowired
    RibbonService ribbonService;

    @RequestMapping(value = "/hi")
    public String hi(@RequestParam String name) {
        return ribbonService.hiService(name);
    }
}

一个Service:

@Service
public class RibbonService {

    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiServiceError")
    public String hiService(String name) {
        return restTemplate.getForObject("http://provider-a/hi?name=" + name, String.class);
    }

    public String hiServiceError(String name) {
        return "hi," + name + ",断路机制启动,hiServiceError";
    }
}

application.properties文件里写的是:

server.port: 8764

spring.application.name: consumer-ribbon

eureka.client.service-url.defaultZone: http://localhost:8761/eureka/

以上代码,和Swagger有关的也只有端口配置8764了。

 

二,引入Swagger

如果要在项目中加入Swagger,首先要在pom文件中加入:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

然后我们需要一个Swagger的配置类:

package consumer.ribbon;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableSwagger2
@ComponentScan(basePackages = {"consumer.ribbon"})
@Configuration
public class SwaggerConfig extends WebMvcConfigurationSupport {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("这里填title")//标题
                .description("这里填description")//描述
                .termsOfServiceUrl("http://www.google.com.hk")//(不可见)条款地址,公司内部使用的话不需要配
                .contact(new Contact("这里填作者姓名", "这里填作者url", "这里填作者email"))//作者信息
                .version("这里填version")//版本号
                .build();
    }

//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new LoginInterceptor())
//                .addPathPatterns("/**")
//                .excludePathPatterns("/user/login")
//                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
//    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

//        registry.addResourceHandler("/templates/**")
//                .addResourceLocations("classpath:/META-INF/resources/templates/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

注:

1,注解别写少了,另外@ComponentScan注解中的basePackages参数别写错了,这是需要扫描Swagger注解的文件路径。

2,createRestApi()方法里的内容基本照抄,不用改。

3,addResourceHandlers()方法是为了避免Swagger首页进不去而添加的路径关联,这个方法不写的话进首页会404。

其中:

registry.addResourceHandler("swagger-ui.html")

是为了访问首页。

registry.addResourceHandler("/webjars/**")

是首页用到的一些静态资源。

中间注释的一段貌似不写也没什么影响。

4,被注释的addInterceptors()方法网上很多文章说需要加,否则首页404,不过我试了一下好像也可以不写。方法中用到的LoginInterceptor类实际上是自定义的一个Interceptor,没什么内容:

package consumer.ribbon;

import org.springframework.web.servlet.HandlerInterceptor;

public class LoginInterceptor  implements HandlerInterceptor {
}

 

三,Swagger首页

做完这些后,启动SpringBoot服务,在地址栏输入:

http://127.0.0.1:8764/swagger-ui.html

可以进入Swagger首页:

可以看到,首页中已经展示了两个Controller。

其中BasicErrorController不是自己定义的,点开之后里面展示的是/error接口的配置,看起来像是请求错误地址后的跳转接口:

另外首页还展示了hi-controller,这个controller没有使用任何Swagger专用的注解,但是Swagger依然扫描到了他,可能是用@RestController和@RequestMapping两种注解扫描的。另外/hi接口没有配置请求方式,所以Swagger列出了所有格式的/hi接口:

打开某个接口会有参数的说明,返回值说明等:

另外,点击右上角的Try it out按钮,还可以实际调用一下该接口,输入参数值,点击Execut按钮调用,就像PostMan一样:

 

四,Swagger注解使用

 

1,@Api

@Api注解用在Controller上,说明该类的作用。

注意:使用该注解必须与Controller注解一起使用,比如@RestController或@Controller。

 

部分参数:

value:网上说是url路径值,但是我填了貌似没啥用,没见在哪能展示。

tags:应该理解为Controller的名字,可以选择填Controller类名,或者Controller的Url路径。网上说此参数会覆盖value,但是即使没有此参数value也显示不出来。

description:描述信息。

position:在Swagger上的排序位置,有多个@Api的时候可以配。

hidden:为true时隐藏该文档,但是我设置了没啥用。

 

写个代码:

@Api(tags = "SwaggerController", description = "Swagger测试Controller", position = 0)
@RestController
@RequestMapping(value = "/swagger", method = RequestMethod.POST)
public class SwaggerController {
    @RequestMapping(value = "/hi")
    public String hi(@RequestParam String name) {
        return "name=" + name;
    }
}

Swagger里显示的是这样的:

 

2,@ApiOperation

@ApiOperation注解用在Controller中的方法上,用于说明方法的作用。

 

部分参数:

tags:方法名。可以选择写方法名或url路径。

notes:描述信息。

 

写个代码:

@ApiOperation(value = "getUser", notes = "获取用户接口", response = java.lang.String.class)
@RequestMapping(value = "/hi")
public String getUser(@RequestParam String name) {
    return "name=" + name;
}

Swagger里显示的是这样的:

 

3,@ApiImplicitParam和@ApiImplicitParams

@ApiImplicitParam注解用在单参数方法上,或者多参数方法的 @ApiImplicitParams注解中。

 

部分参数:

paramType:参数类型,可选项有:

  1. path:以地址的形式提交数据。此类型的参数必须由@PathVariable注解来获取。
  2. query:直接跟参数完成自动映射赋值。此类型的参数必须由@RequestParam注解来获取。
  3. body:以流的形式提交,仅支持POST。
  4. header:参数在request headers里提交。此类型的参数必须由@RequestHeader注解来获取。
  5. form:以form表单的形式提交,仅支持POST

dataType:参数数据类型:可选值有Integer和String。

name:参数名,最好写成和Java方法中实际的参数名一致。

value:参数描述。

required:参数是否必填,可选值有true和false。

defaultValue:默认值,这个默认值是使用Swagger发起调用时用的,和SpringMVC提供的参数默认值不是一个概念。

 

Swagger和Spring对参数的控制方式完全不同

Swagger对参数的控制是文档层面的,并不能真正控制接口本身,而Spring可以真正控制接口的定义,二者各管一边互不干扰。

以required为例,在Swagger中是这么用的:

@ApiImplicitParam(name = "userName", value = "用户名", required = true)

该配置代表Swagger认为userName参数必填,这一点将体现在Swagger生成的文档上,另外,如果在Swagger首页上使用Try it out发起调用,这个配置也会生效,如果不填userName的话请求就发不出去。然而,以上这些和接口的实际要求并没有什么关系,从配置上来说二者完全可以对不上。

相比之下,Spring提供restful接口时是这样使用required的:

@RequestParam(required = true) String userName

该配置代表Spring认为接口的userName参数是必填项,那么这个参数就真的是必填的,如果没填那么请求将被返回400的错误。

同理,Swagger和Spring对默认值的使用也有同样的情况,Swagger的默认值就是能在文档上看看。

 

@ApiImplicitParam中的name,最好写成和Java方法中实际的参数名一致,否则在Swagger上会分别展示,比如:

@ApiOperation(value = "getUser", notes = "获取用户接口", response = java.lang.String.class)
@ApiImplicitParam(name = "name", value = "用户名value", required = true, defaultValue = "abcde", paramType = "form", dataType = "String")
@RequestMapping(value = "/getUser", method = RequestMethod.POST)
public String getUser(@RequestParam String userName) {
    return "userName=" + userName;
}

在Swagger上的效果是:

图8

上面的name参数就是我们用@ApiImplicitParam注解定义的,下面的userName是在Java方法中定义的参数,而且和@RequestParam注解无关。使用Try it out来发起调用的时候,我们自定义的name和方法的真实参数userName都可以使用输入值,但是只有真实参数才是有效的:

 

@ApiImplicitParam注解的另一个用法,是用在@ApiImplicitParams注解中,比如:

@ApiOperation(value = "getUser2", notes = "获取用户接口", response = java.lang.String.class)
@ApiImplicitParams({
        @ApiImplicitParam(name = "userName", value = "用户名", required = true, defaultValue = "abcde", paramType = "query", dataType = "String"),
        @ApiImplicitParam(name = "age", value = "用户年龄", required = false, defaultValue = "12", paramType = "query", dataType = "Integer")
})
@RequestMapping(value = "/getUser2", method = RequestMethod.POST)
public String getUser2(@RequestParam String userName,
                      Integer age) {
    return "userName=" + userName + " age=" + age;
}

在Swagger上的效果是:

依然需要注意参数名和java方法实际的参数名要一致。

 

4,@ApiResponse和@ApiResponses

@ApiResponse注解用在方法上,并且用在@ApiResponses注解中,是对返回信息的说明。

@ApiResponse注解直接用在方法上时貌似不会起作用。

 

部分参数:

code:http响应状态码

message:描述信息

response:响应类,默认void

注:关于response参数,可能本身设计的初衷是为了维护某些错误的http请求时的响应类,不过实际上此参数也可以用来描述正常http请求(code=200)的响应类。另外,响应类的参数可以设置为public,或者设置为private并且写好get/set方法。

比如:

@ApiOperation(value = "getUser3", notes = "获取用户接口", response = java.lang.String.class)
@ApiResponses({
    @ApiResponse(code = 200, message = "请求正常", response = ErrorResponse.class),
    @ApiResponse(code = 400, message = "参数错误", response = ErrorResponse.class)
})
@RequestMapping(value = "/getUser3", method = RequestMethod.POST)
public String getUser3(@RequestParam String userName,
                       Integer age) {
    return "userName=" + userName + " age=" + age;
}

其中ErrorResponse类是这样的:

public class ErrorResponse {
    private int code;
    private String message;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

在Swagger里效果是这样的:

 

5,@ApiModel和@ApiModelProperty

@ApiModel用于响应类上,是返回响应类的说明。

@ApiModelProperty用于响应类的属性上,是对响应类属性的描述。

 

@ApiModel注解的部分参数:

value:名称

description:描述

parent:父类class,为了可以描述从父类继承来的属性。

 

@ApiModelProperty注解的部分参数:

value:参数名

 

举个例子:

@ApiOperation(value = "getUser4", notes = "获取用户接口", response = consumer.swagger.UserResponse.class)
@RequestMapping(value = "/getUser4", method = RequestMethod.POST)
public UserResponse getUser4(@RequestParam String userName,
                             Integer age) {
    UserResponse userResponse = new UserResponse();
    userResponse.setId(123);
    userResponse.setAge(age);
    userResponse.setName(userName);
    return userResponse;
}

其中的响应类UserResponse是这样的:

package consumer.swagger;

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

@ApiModel(value = "UserResponse",description = "用户信息",parent = consumer.swagger.UserResponseParent.class)
public class UserResponse extends UserResponseParent{

    @ApiModelProperty(value = "用户id")
    private int id;

    @ApiModelProperty(value = "用户名")
    private String name;

    @ApiModelProperty(value = "年龄")
    private int age;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

有父类UserResponseParent,此类定义如下:

package consumer.swagger;

import io.swagger.annotations.ApiModelProperty;

public class UserResponseParent {

    @ApiModelProperty(value = "父级姓名")
    private String parentName;

    public String getParentName() {
        return parentName;
    }

    public void setParentName(String parentName) {
        this.parentName = parentName;
    }
}

父类可以不用@ApiModel注解,只需要在属性上添加@ApiModelProperty注解。

于是在Swagger上是这样的效果:

注意,在code=200的那一栏里,此时默认选中的是Example Value这一项,所以显示了UserResponse类的一个例子,如果我们选择Model这一项,就会显示UserResponse类的说明:

可见,父类的属性也被列出来了,如果父类属性添加了@ApiModelProperty注解,注解就会生效,否则就只有属性名。

 

6,@ResponseHeader

@ResponseHeader注解用于设置响应头,可以用在@ApiResponse注解中。

 

部分参数:

name:响应头名称

description:描述

response:响应类,默认Void。

比如:

@ApiOperation(value = "getUser5", notes = "获取用户接口", response = java.lang.String.class)
@ApiResponses({
        @ApiResponse(code = 400, message = "参数错误", response = ErrorResponse.class,responseHeaders = {
                @ResponseHeader(name = "Location", description = "The URL to retrieve created resource", response = String.class)
        })
})
@RequestMapping(value = "/getUser5", method = RequestMethod.POST)
public String getUser5(@RequestParam String userName,
                       Integer age) {
    return "userName=" + userName + " age=" + age;
}

在Swagger中的效果是这样的:

 

其实Swagger的功能还是蛮强大的,不只是生成文档这么简单,上面提到的注解和参数也只是冰山一角,待后面慢慢学习。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值