就我自己的理解来说,Swagger应用于前后端分离项目中,前端和后端之间的联系就是Controller层的接口,Swagger中有一个swagger-ui.html,后端配置好之后Controller层的接口都会显示在swagger-ui.html上,前端就可以直接访问这个swagger-ui.html来调用接口,最重要的是这个网页是实时显示的。可以有效的降低前后端打架几率。
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
dependency>
创建一个Swagger配置类,加上@Configuration注解,放到Spring容器中,然后添加@EnableSwagger2,指示应用开启Swagger的支持,@EnableSwagger2注解的源码里的解释如下
/**
* Indicates that Swagger support should be enabled.
* 指示应启用Swagger支持。
*
* This should be applied to a Spring java config and should have an accompanying '@Configuration' annotation.
* 这应该应用于Spring java config,并带有“ @Configuration”注释
*
* Loads all required beans defined in @see SpringSwaggerConfig
* 加载@see SpringSwaggerConfig中定义的所有必需bean,这里@see所必需的的bean是下面一句写的Docket,
* 意思就是说,添加这个注解的类必须要将Docket加载到bean中,因为这是他所必须的
*
* @see springfox.documentation.spring.web.plugins.Docket
*/
package springfox.documentation.swagger2.annotations;
import org.springframework.context.annotation.Import;
import springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Indicates that Swagger support should be enabled.
*
* This should be applied to a Spring java config and should have an accompanying '@Configuration' annotation.
*
* Loads all required beans defined in @see SpringSwaggerConfig
*
* @see springfox.documentation.spring.web.plugins.Docket
*/
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({Swagger2DocumentationConfiguration.class}) //这里是最关键的,引入了Swagger的配置类
public @interface EnableSwagger2 {
}
Swagger配置类:大体都是固定的代码,直接复制稍微修改就行。
package shiro.demo.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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @Auther Shen
* @Date 2020-07-06
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
/* RequestHandlerSelectors:配置要扫描的接口的方式
.basePackage():指定要扫描的包,一般就配置自己Controller所在的包
.any():扫描全部
.none():不扫描
.withClassAnnotation():扫描类上的注解,参数是一个注解的反射对象
.withMethodAnnotation():扫描方法上的注解
*/
.apis(RequestHandlerSelectors.basePackage("shiro.demo.controller"))
/* paths(): 配置过滤的请求
.any():不过滤,所有请求都放行,结果就是在swagger-ui.html上显示扫描包
的所有的RequestMapping
.none():过滤全部,所有请求都不放行,结果就是在swagger-ui.html上什么都不显示
.ant():括号里填请求地址,就是过滤其他,只剩下ant()括号里的请求显示在网页上
*/
.paths(PathSelectors.any())
.build();
}
/**
* String title; 标题
* String description; 描述
* String termsOfServiceUrl; 服务条款网址
* Contact contact; 负责这个 api 的人的联系方式
* String license; 这个 api 的许可证信息
* String licenseUrl; 这个 api 的许可证地址
* String version; Api版本
*
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("我的Api文档")
.description("这是一个测试文档")
.termsOfServiceUrl("https://gitee.com/") //随便填的,不填也行,不配置这一项也行
.contact(new Contact("老申", "", "***********@qq.com"))
.license("许可证信息")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
.version("1.0x")
.build();
}
}
随便写一个Controller,然后访问swagger-ui.html
package shiro.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Auther Shen
* @Date 2020-07-06
*/
@RestController
public class SwaggerTestController {
@GetMapping("/test")
public String swaggerTest(){
return "swagger";
}
}
开发时需要Swagger,但是上线时,我们不想让它生效,因为如果上线后还生效的话,用户就会知道你的服务端的所有的接口,可能会受到攻击。所以现在出来一个问题,怎么能简单的实现这样的功能:开发环境启用Swagger,上线后关闭Swagger。
直接上代码
package shiro.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
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;
/**
* @Auther Shen
* @Date 2020-07-06
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket(Environment environment) {
//设置要显示Swagger的环境
Profiles profiles = Profiles.of("dev");
//通过environment.acceptsProfiles判断是否处在自己设定的环境中
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(flag)//enable是否启动Swagger,如果为false,则Swagger-ui不能在浏览器中访问
.select()
.apis(RequestHandlerSelectors.basePackage("shiro.demo.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("我的Api文档")
.description("这是一个测试文档")
.termsOfServiceUrl("https://gitee.com/")
.contact(new Contact("Shen", "", "***********@qq.com"))
.license("许可证信息")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
.version("1.0x")
.build();
}
}
在application.yml中配置环境,如下图所示
然后在开发环境就会生效,上线时可以改为 spring.profiles.active=prod。
分组问题:多个组就创建多个Docket,每个Docket的groupName设置为不同就行了,各自组扫描各自的包
package shiro.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
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;
/**
* @Auther Shen
* @Date 2020-07-06
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket(Environment environment) {
//设置要显示Swagger的环境
Profiles profiles = Profiles.of("dev");
//通过environment.acceptsProfiles判断是否处在自己设定的环境中
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(flag)//enable是否启动Swagger,如果为false,则Swagger-ui不能在浏览器中访问
.groupName("Shen")
.select()
.apis(RequestHandlerSelectors.basePackage("shiro.demo.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("我的Api文档")
.description("这是一个测试文档")
.termsOfServiceUrl("https://gitee.com/")
.contact(new Contact("Shen", "", "***********@qq.com"))
.license("许可证信息")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
.version("1.0x")
.build();
}
}
在Controller中只要存在这种,返回值为实体类对象的就会直接添加到Swagger中
@GetMapping("/user")
public User getUser(){
return new User();
}
然后还可以在User类上加注释,让生成的文档更易懂,下面是效果
@ApiModel:作用于类,接口,枚举上
@ApiModelProperty:作用于实体类属性上
@GetMapping("/user")
@ApiOperation("User访问控制接口")
public User getUser(){
return new User();
}
@GetMapping("/test")
@ApiOperation("test测试注解")
public String test(@ApiParam("用户名") String username){
return username;
}
在与shiro或者SpringSecurity整合的时候需要配置过滤器放行,不然会出现弹窗问题,如下图所示
这里提供了shiro需要放行的路径,放到shiro中的过滤器中即可
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/v2/**", "anon");
filterMap.put("/swagger-resources/**", "anon");
用户实体类
package shiro.demo.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 用户实体类
* @Auther Shen
* @Date 2020-07-06
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("用户实体类")
public class User implements Serializable {
@ApiModelProperty("用户的编号")
private int id;
@ApiModelProperty("用户名")
private String username;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("用户具备的权限")
private String perms;
}
Swagger配置类
package shiro.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
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;
/**
* @Auther Shen
* @Date 2020-07-06
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket(Environment environment) {
//设置要显示Swagger的环境
Profiles profiles = Profiles.of("dev", "test");
//通过environment.acceptsProfiles判断是否处在自己设定的环境中
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(flag)//enable是否启动Swagger,如果为false,则Swagger-ui不能在浏览器中访问
.groupName("Shen")
.select()
/* RequestHandlerSelectors:配置要扫描的接口的方式
.basePackage():指定要扫描的包
.any():扫描全部
.none():不扫描
.withClassAnnotation():扫描类上的注解,参数是一个注解的反射对象
.withMethodAnnotation():扫描方法上的注解
*/
.apis(RequestHandlerSelectors.basePackage("shiro.demo.controller"))
/* paths(): 配置过滤的请求
.any():不过滤,所有请求都放行,结果就是在swagger-ui.html上显示扫描包的所有的RequestMapping
.none():过滤全部,所有请求都不放行,结果就是在swagger-ui.html上什么都不显示
.ant():括号里填请求地址,就是过滤其他,只剩下ant()括号里的请求显示在网页上
*/
.paths(PathSelectors.any())
.build();
}
/**
* String title; 标题
* String description; 描述
* String termsOfServiceUrl; 服务条款网址
* Contact contact; 负责这个 api 的人的联系方式
* String license; 这个 api 的许可证信息
* String licenseUrl; 这个 api 的许可证地址
* String version; Api版本
*
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("我的Api文档")
.description("这是一个测试文档")
.termsOfServiceUrl("https://gitee.com/")
.contact(new Contact("Shen", "", "***********@qq.com"))
.license("许可证信息")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
.version("1.0x")
.build();
}
}
Controller
package shiro.demo.controller;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import shiro.demo.pojo.User;
/**
* @Auther Shen
* @Date 2020-07-07
*/
@Controller
public class SwaggerTestController {
@GetMapping("/user")
@ApiOperation("User访问控制接口")
public User getUser(){
return new User();
}
@GetMapping("/test")
@ApiOperation("test测试注解")
public String test(@ApiParam("用户名") String username){
return username;
}
}