一次掌握Swagger

Swagger介绍

Swagger是一个可以在线生成并且实时更新的API接口文档框架,可以直接集成在项目中

先上图:)

导入依赖

<!--swagger-->
<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>

SpringMVC集成

springmvc.xml

SpringMVC的的配置文件中添加以下内容

<!-- 引入swagger相关 -->
    <!-- 将SwaggerConfig配置类注入 -->
    <bean class="com.djn.controller.Swagger2Config"/>
    <!-- 引用Swagger 默认配置 -->
    <bean class="springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration" id="swagger2Config"/>
		<!--会去改目录下找相关资源 该目录在导入的依赖jar包中-->
    <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" />
    <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>

SwaggerConfig

  • @Configuration:声明是一个配置类
  • @EnableSwagger2:开启Swagger2
  • @EnableWebMVC:开启默认的mvc配置
    • 该注解一定要添加,不然启动会出现No qualifying bean of type 'java.util.List<org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
  • .groupName("张三"):用于分组,该功能用于协同开发
  • .select():扫描接口的方式
  • .apis():扫描包
    • RequestHandlerSelectors.basePackage("com.djn.controller"):只扫描com.djn.controller该包
    • RequestHandlerSelectors.any():扫描全部(默认)
    • RequestHandlerSelectors.none():不扫描
  • .paths:过滤
    • PathSelectors.ant("/user"):只扫描包下的/user/*请求
    • PathSelectors.any()
    • PathSelectors.none()
  • .enable:是否可以访问swagger,传入boolean值,默认为true
@Configuration 
@EnableSwagger2 
@PropertySource("classpath:mall.properties") 
public class Swagger2Config {

    @Value("${swagger.enable}")
    public Boolean flag;
  
  	//注入Bean,Docket是Swagger接口,提供默认配置和便捷配置
    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("丁江楠")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.djn.controller"))
                .build()
                .enable(flag)
                .apiInfo(apiInfo());
    }
  	
  	//swagger.html页面展示的信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("SwaggerDemo项目接口文档")
                .description("SwaggerDemo项目接口测试")
                .version("1.0.0")
                .termsOfServiceUrl("")
                .license("")
                .licenseUrl("")
                .build();
    }
}

Controller类

  • @RestController:@ResponseBody+@Controller,表示将方法的返回值转为特定的格式写入到response的body区域,从而返回给客户端
    • 如果没有@ResponseBody,默认会将方法的返回值封装为ModelView对象,从而跳转到视图
    • 如果返回值是String,就直接将字符串返回给客户端,如果返回值是对象,会将对象转为json串返回给客户端
  • @ApiOperation:对方法的注释说明
  • @GetMapping:用于映射get请求,这里不要使用@RequestMapping,不然会一个方法生成很多个item
  • @ApiParam("用户ID"):对请求参数的注释说明
  • @RequestBody:用于接受客户端传递的json字符串(请求体中的数据)
@RestController
public class HelloController {

    @ApiOperation("Hello方法")
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

    //只要返回实体类就会添加到Swagger中
    @ApiOperation("获取用户信息")
    @GetMapping("/getUser")
    public User getUser(@ApiParam("用户ID") Integer userId) {
        return new User();
    }

    @ApiOperation("获取用户信息")
    @PostMapping("/getUser2")
    public User getUser(@ApiParam("用户ID") @RequestBody User user) {
        int i= 1/0;
        return new User(user.getName(),user.getAge(),user.getPassword());
    }  
}

Model类

  • @ApiModel:实体类的注释说明
  • ApiModelProperty:实体类属性的说明
  • 属性必须要有getter方法或者声明为public,否则不会显示
@ApiModel("用户实体类")
public class User {
    @ApiModelProperty("姓名")
    private String name;
    @ApiModelProperty("年龄")
    private Integer age;
    @ApiModelProperty("密码")
    private String password;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }

SpringBoot集成

与SpringMVC相似,不过不需要配置文件和@EnableWebMvc注解

业务场景

在开发环境开启Swagger,在线上环境关闭Swagger

因为Swagger启动是需要加载资源也就是占内存的,同时会将我们的接口暴露给别人,这肯定是死翘翘的~

  • 通过配置文件中的值来控制:在配置文件中配置swagger.enable,然后在SwaggerConfig获取值,从而将值传入到.enbale
@Configuration 
@EnableSwagger2 
@PropertySource("classpath:xxx.properties")  //加载配置文件
public class Swagger2Config {

  	//获取开关值 boolean类型
    @Value("${swagger.enable}")
    public Boolean flag;
  
  	//注入Bean,Docket是Swagger接口,提供默认配置和便捷配置
    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("丁江楠")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.djn.controller"))
                .build()
                .enable(flag) //赋值
                .apiInfo(apiInfo());
    }
  	
  	//swagger.html页面展示的信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("SwaggerDemo项目接口文档")
                .description("SwaggerDemo项目接口测试")
                .version("1.0.0")
                .termsOfServiceUrl("")
                .license("")
                .licenseUrl("")
                .build();
    }
}
  • 通过环境来配置:使用@Profile注解:在类上添加@Profile("dev"):只有dev环境Swagger才生效
@Profile("dev") //只有dev环境才生效
@Configuration 
@EnbaleWebMvc
@EnableSwagger2 
public class Swagger2Config {
  
  	//注入Bean,Docket是Swagger接口,提供默认配置和便捷配置
    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("丁江楠")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.djn.controller"))
                .build()
                .enable(true)
                .apiInfo(apiInfo());
    }
  	
  	//swagger.html页面展示的信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("SwaggerDemo项目接口文档")
                .description("SwaggerDemo项目接口测试")
                .version("1.0.0")
                .termsOfServiceUrl("")
                .license("")
                .licenseUrl("")
                .build();
    }
}

忽略参数Class类型

今天写项目时发现的一个问题,先看一下不忽略有什么效果:

代码:

@ApiOperation("登录")
@PostMapping("/login")
public ServerResponse<User> login(@RequestParam("username") String username,
                                  @RequestParam("password") String password,
                                  HttpSession session) {
    Subject subject = SecurityUtils.getSubject();
    if (!subject.isAuthenticated()) {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(true);
        subject.login(token);
    }
    return ServerResponse.createBySuccess((User));
}

效果图:

可以看出,Swagger帮我们把HttpSession的参数也显示出来了,而HttpSession我们并不需要传参处理,如何解决?

两种方式:

第一种方式

在方法的参数前,添加@ApiIgnore注解

@ApiOperation("登录")
@PostMapping("/login")
public ServerResponse<User> login(@RequestParam("username") String username,
                                  @RequestParam("password") String password,
                                  @ApiIgnore HttpSession session) {
    Subject subject = SecurityUtils.getSubject();
    if (!subject.isAuthenticated()) {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(true);
        subject.login(token);
    }
    return ServerResponse.createBySuccess((User));
}

虽然问题解决了,但是这不是最好的办法,假如我们有很多个接口都有HttpSession呢,岂不是每个方法都要加一个注解,又或者其他的对象,比如HttpServletRequestHttpServletResponse都需要添加注解,所以看一下第二种方式

第二种方式

在创建Docket对象时,指定忽略相关的Class

使用ignoredParameterTypes方法传入我们要忽略的Class类型,可以传入多个

    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("dingjn")
                //扫描接口的方式
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.djn.controller"))
                .build()
                //忽略Class,swagger参数中不显示
                .ignoredParameterTypes(HttpSession.class)
                .enable(true) //是否启动swagger
                .apiInfo(apiInfo());
    }

springFox默认为我们忽略了以下类型

private void initIgnorableTypes() {
    ignored = newHashSet();
    ignored.add(ServletRequest.class);
    ignored.add(Class.class);
    ignored.add(Void.class);
    ignored.add(Void.TYPE);
    ignored.add(HttpServletRequest.class);
    ignored.add(HttpServletResponse.class);
    ignored.add(HttpHeaders.class);
    ignored.add(BindingResult.class);
    ignored.add(ServletContext.class);
    ignored.add(UriComponentsBuilder.class);
    ignored.add(ApiIgnore.class); //Used to ignore parameters
}

最终效果图:

忽略字段

又发现了一个问题,所以再来更新一下~,因为有的时候我们传递的是一个对象,而对象里的字段有的是不想让前端传过来的,比如时间,所以需要做一个忽略

这个还是很简单的,不要慌,只需要在字段@ApiModelProperty(hidden = true)注解就OK了

@Data
@NoArgsConstructor
@ApiModel("用户信息")
public class User implements Serializable {

    private Integer userId;

    @ApiModelProperty("用户名名")
    private String username;

    @ApiModelProperty("密码")
    private String password;
		
  	//该字段不显示在Swagger页面
    @ApiModelProperty(hidden = true)
    private Date createTime;

    @ApiModelProperty(hidden = true)
    private Date updateTime;
}

图我就不上了,自己试一下吧
结束~

posted @ 2020-04-22 00:39  范特西-  阅读(344)  评论(0)    收藏  举报