swagger-03-文档注释使用

在人生的道路上,不管是潇洒走一回,或者是千山独行,皆须是自己想走的路,虽然,有的人并不是很快就能找到自己的方向和道路,不过,只要坚持到底,我相信,就一定可以找到自己的路,只要找到路,就不必怕路途遥远了。

导读:本篇文章讲解 swagger-03-文档注释使用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1.7 文档注释使用

1.7.1 接口组定义
  • 接口有时候应该是分组的,而且大部分都是在一个controller中的,比如app管理相关的接口应该都在AppController中,那么不同的业务的时候,应该定义/划分不同的接口组。接口组可以使用@Api来划分。

注意,对于swagger,不要使用@RequestMapping

因为@RequestMapping支持任意请求方式,swagger会为这个接口生成7种请求方式的接口文档

@Api(tags = "app管理")  //可以当作是这个组的名字。
@RestController
@RequestMapping("app")
public class AppController {
    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    public String hello(){
        return "hello swagger!";
    }
}

可以理解成基于tags来分组

如果这个Controller下(接口组)下面没有接口,那么在swagger ui中是不会显示的,如果有的话就会这样显示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CS340edl-1660311086604)(../../typora-user-images/image-20220810151510792.png)]

1.7.2 接口定义
  • 使用了@Api来标注一个Controller之后,如果下面有接口,那么就会默认生成文档,但没有我们自定义的说明:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qAk9GVN3-1660311086607)(../../typora-user-images/image-20220810153325738.png)]

  • 我们可以使用@ApiOperation来描述接口,比如:
 //只要我们的接口中,返回值中存在实体类,他就会被扫描外wagger中
    @ApiOperation(value = "获取用户",notes = "获取用户接口")
    @GetMapping("/getUser")
    public User getUser(String name,String password){
        return new User(name,password);
    }

在这里插入图片描述

常用配置项:

  • value:可以当作是接口的简称
  • notes:接口的描述
  • tags:可以额外定义接口组,比如这个接口外层已经有@Api(tags = "用户管理"),将接口划分到了“用户管理”中,但你可以额外的使用tags,例如tags = "角色管理"让角色管理中也有这个接口文档。
1.7.3 定义接口请求参数
  • 上面使用了@ApiOperation来了描述接口,还缺少接口请求参数的说明.

对于GET方式,swagger不推荐使用body方式来传递数据所以虽然Spring MVC可以自动封装参数,也是不希望在GET方式时使用json、form-data等方式来传递,这时候最好使用路径参数或者url参数。(虽然POSTMAN等是支持的,swagger在线测试是不支持这个操作的),所以如果接口传递的数据是json或者form-data方式的,还是使用POST方式好。可翻看之前的博客SpringMVC-09-传递参数的几种方式

1.7.3.1 请求参数是实体类
  • 此时我们需要使用@ApiModel来标注实体类,然后在接口中定义入参为实体类即可:

  • @ApiModel:用来标类,@ApiModel内的注释 不要出现相同 否则会将相同的vo字段进行合并

    • 常用配置项:
      • value:实体类简称
      • description:实体类说明
  • @ApiModelProperty:用来描述类的字段的意义。

    • 常用配置项:
      • value:字段说明
      • example:设置请求示例(Example Value)的默认值,如果不配置,当字段为string的时候,此时请求示例中默认值为”“,对于int类型数据若没有默认值,则默认是””空字符串,会造成NumberFormatException,

1.给int类型的字段使用@ApiModelPorperty注解时添加example属性

2.去除原swagger中的swagger-models和swagger-annotations,自行引入高版本的annotations和models

<dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
            <exclusions>
                <exclusion>
                    <groupId>io.swagger</groupId>
                    <artifactId>swagger-annotations</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.swagger</groupId>
                    <artifactId>swagger-models</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.22</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.5.22</version>
        </dependency>

  • notes:参数类型为String,作用为该字段的注释说明
  • name:用新的字段名来替代旧的字段名。
  • position:参数类型为int,作用为允许显式地对模型中的属性排序。
  • allowableValues:限制值得范围,例如{1,2,3}代表只能取这三个值;[1,6]代表取1到6的值;(1,6)代表1到6的值,不包括1和6;还可以使用infinity或-infinity来无限值,比如[1, infinity]代表最小值为1,最大值无穷大。
  • required:标记字段是否必填,默认是false,
  • hidden:用来隐藏字段,默认是false,如果要隐藏需要使用true,因为字段默认都会显示,就算没有@ApiModelProperty
  • allowEmptyValue:参数类型为boolean,作用为是否允许传递空值,默认为false
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "用户实体类",description = "用户实体对象")  // 先使用@ApiModel来标注类
public class User {

    // 使用ApiModelProperty来标注字段属性。
    @ApiModelProperty(value = "name",required = true,example = "toy")
    private String name;
    @ApiModelProperty(value = "name",required = true,example = "123456")
    private String password;
    
    //swagger在入参赋值时需要的getter,setter来置值
}
  • 定义成入参:
@ApiOperation(value = "获取用户",notes = "获取用户通过传递实体json")
@PostMapping("/getUser")
public User getUserPost(@RequestBody User user){
    return user;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • try it out 结果
    在这里插入图片描述
1.7.2.2 请求参数是非实体类
  • 对于非实体类参数,可以使用@ApiImplicitParams@ApiImplicitParam来声明请求参数。
    @ApiImplicitParams用在方法头上,@ApiImplicitParam定义在@ApiImplicitParams里面,一个@ApiImplicitParam对应一个参数。

    @ApiImplicitParam常用配置项:

  • name:用来定义参数的名字,也就是字段的名字,可以与接口的入参名对应。如果不对应,也会生成,所以可以用来定义额外参数!

  • value:用来描述参数

  • required:用来标注参数是否必填

  • paramType有path,query,body,form,header等方式,但对于对于非实体类参数的时候,常用的只有path,query,header;body和form是不常用的。body不适用于多个零散参数的情况,只适用于json对象等情况。【如果你的接口是form-data,x-www-form-urlencoded的时候可能不能使用swagger页面API调试,但可以在后面讲到基于BootstrapUI的swagger增强中调试,基于BootstrapUI的swagger支持指定form-datax-www-form-urlencoded

  • 也可以仅仅使用@ApiParam作用在方法上参数不用声明,@ApiParam使用配置和@ApiImplicitParam一样对于3.0.0比2.X有点是可以适配所有类型的参数请求方式,2.x需要测试时手动选择

//只要我们的接口中,返回值中存在实体类,他就会被扫描外wagger中
    @ApiOperation(value = "获取用户",notes = "获取用户接口")
    @GetMapping("/getUser")
    public User getUser(@ApiParam(name = "name",value = "账户",required = true) String name,@ApiParam(name = "password",value = "密码",required = true)String password){
        return new User(name,password);
    }

query方式入参

//query方式入参
@ApiOperation(value = "获取用户1",notes = "获取用户接口1-query方式入参")
@GetMapping("/getUser1")
@ApiImplicitParams({
        @ApiImplicitParam(name = "name",value = "账户",required = true,paramType = "query"),
        @ApiImplicitParam(name = "password",value = "密码",required = true,paramType = "query")
})
public User getUser1(String name,String password){
    return new User(name,password);
}

在这里插入图片描述

在这里插入图片描述

path方式入参

//path方式入参
@ApiOperation(value = "获取用户2",notes = "获取用户接口2-path方式入参")
@GetMapping("/getUser/{name}/{password}")
@ApiImplicitParams({
        @ApiImplicitParam(name = "name",value = "账户",required = true,paramType = "path"),
        @ApiImplicitParam(name = "password",value = "密码",required = true,paramType = "path")
})
public User getUser2(@PathVariable("name") String name,@PathVariable("password")String password){
    return new User(name,password);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FFiaweHT-1660311086611)(../../typora-user-images/image-20220810183314191.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qeouf7Ic-1660311086612)(../../typora-user-images/image-20220810183440703.png)]

header方式入参

//header方式入参
@ApiOperation(value = "获取用户3",notes = "获取用户接口3-header方式入参")
@GetMapping("/getUser3")
@ApiImplicitParams({
        @ApiImplicitParam(name = "name",value = "账户",required = true,paramType = "header"),
        @ApiImplicitParam(name = "password",value = "密码",required = true,paramType = "header")
})
public User getUser3(@RequestHeader String name,@RequestHeader String password){
    return new User(name,password);
}

在这里插入图片描述

在这里插入图片描述

单件上传入参

文件上传时要用@ApiImplicitParams @ApiImplicitParam @ApiParam作用在方法上作为入参@RequestPart用在参数上,用于将“multipart/form-data”请求的一部分与方法参数相关联的注释

//单件上传入参
    @ApiOperation(value = "文件上传1",notes = "文件上传-单文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uploadFile", paramType="form", value = "上传文件", dataType="uploadFile", required = true)
    })
    @PostMapping(value = "/upload1", headers = "content-type=multipart/form-data")
    public String upload(@RequestPart("uploadFile") MultipartFile uploadFile, HttpSession session, HttpServletRequest req){
        String originalFilename = uploadFile.getOriginalFilename();
        //若文件名为空则返回到上传页
        if (!StringUtils.hasText(originalFilename)) {
            return "originalFilename is error";
        }

        //上传路径保存设置
        //String uploadPath = session.getServletContext().getRealPath("/uploadFile/");

        System.out.println("fileSavePath====="+fileSavePath);
        File file1 = new File(fileSavePath);
        if (!file1.exists()) {
            file1.mkdirs();
        }
        try {
            uploadFile.transferTo(new File(file1,originalFilename));
        } catch (IOException e) {
            e.printStackTrace();
            return "uploadFile is error!";
        }
        return req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/workspace_idea01/uploadFile/"+originalFilename;
    }

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

多件上传入参

多个文件上传时,swagger只能测试单文件上传,需要用postman或Apifox等工具测试

@ApiOperation(value = "文件上传2",notes = "文件上传-多文件")
@PostMapping(value = "/upload2",consumes = "multipart/*", headers = "content-type=multipart/form-data")
public ArrayList upload2(@ApiParam(name = "uploadFile",value = "上传文件",required = true,allowMultiple = true) MultipartFile[] uploadFile, HttpSession session, HttpServletRequest req){
    String originalFilename ="";
    //若文件名为空则返回到上传页
    if (!StringUtils.hasText(originalFilename)) {
        System.out.println("originalFilename is error");
    }
    ArrayList<String> filePathList=new ArrayList();

    System.out.println("fileSavePath====="+fileSavePath);
    File file1 = new File(fileSavePath);
    if (!file1.exists()) {
        file1.mkdirs();
    }
    for (MultipartFile file: uploadFile) {
        originalFilename = file.getOriginalFilename();
        if (!StringUtils.hasText(originalFilename)) {
            System.out.println("originalFilename is error");
        }
        try {
            file.transferTo(new File(file1,originalFilename));
            filePathList.add(req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/workspace_idea01/uploadFile/"+originalFilename);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("uploadFile is error!");
        }
    }

    return filePathList;
}

通过reuestbody传递数据等方式

//通过reuestbody传递数据等方式
@ApiOperation(value = "测试requestBody", notes = "测试requestBody")
@ApiImplicitParams({
        @ApiImplicitParam(paramType="query", name="userId", value="用户id", dataTypeClass = Integer.class, required = true),
        @ApiImplicitParam(paramType="body", name = "body",dataType = "string", example = "", required = false)
})
@PostMapping(value="/command",produces = {"application/json;charset=UTF-8"})
    public String getHttpInfo(@RequestBody User user, Integer userId) throws IOException {
        //InputStream in = request.getInputStream();
        // TODO. LOGIC
        return user.toString();
    }
  • 也可以从request流中取值
public String getHttpInfo(HttpServletRequest request, Integer userId) throws IOException {
InputStream in = request.getInputStream();
}

在这里插入图片描述

在这里插入图片描述

既有文件,又有参数

@ApiOperation(value = "文件上传3",notes = "文件上传-携带参数")
@ApiImplicitParams({
        @ApiImplicitParam(name = "uploadFile", paramType="form", value = "上传文件", dataType="uploadFile", required = true),
        @ApiImplicitParam(name = "id", paramType="query", value = "参数id", dataTypeClass= Integer.class, required = true)
})
@PostMapping(value = "/upload3", headers = "content-type=multipart/form-data")
public String upload3(@RequestPart("uploadFile") MultipartFile uploadFile,Integer id, HttpServletRequest req){
    String originalFilename = uploadFile.getOriginalFilename();
    //若文件名为空则返回到上传页
    if (!StringUtils.hasText(originalFilename)) {
        return "originalFilename is error";
    }

    //上传路径保存设置
    //String uploadPath = session.getServletContext().getRealPath("/uploadFile/");

    System.out.println("fileSavePath====="+fileSavePath);
    File file1 = new File(fileSavePath);
    if (!file1.exists()) {
        file1.mkdirs();
    }
    try {
        uploadFile.transferTo(new File(file1,originalFilename));
    } catch (IOException e) {
        e.printStackTrace();
        return "uploadFile is error!";
    }
    return req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/workspace_idea01/uploadFile/"+originalFilename+"&id="+id;
}

在这里插入图片描述

在这里插入图片描述

1.7.4 定义接口响应
  • 定义接口响应,即查看接口文档的人能够知道接口返回的数据的意义。
1.7.4.1 响应是实体类
  • 只要在接口请求参数上使用@ApiModel来标注类,如果接口返回了这个类,那么这个类上的说明也会作为响应的说明:
@ApiOperation(value = "返回实体对象",notes = "返回实体对象描述user")
@PostMapping("/getUser4")
public User getUser4(@RequestBody User user){
    return user;
}

在这里插入图片描述

在这里插入图片描述

1.7.4.2 响应非实体类
  • swagger无法对非实体类的响应进行详细说明,只能标注响应码等信息。是通过@ApiResponses@ApiResponse来实现的。
@ApiOperation(value = "返回非实体",notes = "返回非实体描述Stirng")
@PostMapping("/getUser5")
@ApiResponses({
        @ApiResponse(code = 200,message = "请求-响应成功"),
        @ApiResponse(code = 404,message = "页面异常"),
})
public String getUser5(@RequestBody User user){
    return user.toString();
}

在这里插入图片描述

在这里插入图片描述

1.8 Swagger UI增强

  • 作为Swagger UI的衍生,可以使用第三方提供了一些Swagger UI增强,如swagger-bootstrap-ui
1.8.1 使用
  • 补充导入swagger-bootstrap-ui,前面的swagger-ui不变
 <!--1.9.6会出NoClassDefFoundError: com/google/common/base/Function环境问题-->
 <dependency>
     <groupId>com.github.xiaoymin</groupId>
     <artifactId>swagger-bootstrap-ui</artifactId>
     <version>1.8.7</version>
 </dependency>
  • 在swagger配置类中增加注解@EnableSwaggerBootstrapUI:
@Configuration // 标明是配置类
//@EnableSwagger2  //开启swagger2功能 供3.0以下使用,swagger老版本
@EnableOpenApi
//@Profile({"dev","test"})
@ConditionalOnProperty(name = "swagger.enable",havingValue = "true")
@EnableSwaggerBootstrapUI
public class SwaggerConfig {
...
}
  • 访问API:http://localhost:8080/doc.html,可预览到基于bootstarp的Swagger UI界面。

在这里插入图片描述

在这里插入图片描述

  • 基于BootstrapUI的swagger支持指定form-datax-www-form-urlencoded

  • 支持复制单个API文档和导出全部API文档:

在这里插入图片描述

  • 整合Spring Security注意

在Spring Boot整合Spring Security和Swagger的时候,需要配置拦截的路径和放行的路径,注意是放行以下几个路径。

.antMatchers("/swagger**/**").permitAll()
.antMatchers("/webjars/**").permitAll()
.antMatchers("/v2/**").permitAll()
.antMatchers("/doc.html").permitAll() // 如果你用了bootstarp的Swagger UI界面,加一个这个。
1.8.2 对于token的处理
  • 在swagger中只支持了简单的调试,但对于一些接口,我们测试的时候可能需要把token信息写到header中

  • 办法如下:

    • 在Swagger BootstrapUI,可以在“文档管理”中增加全局参数,这包括了添加header参数。
    • 在swagger配置类中增加全局参数配置
    @Bean
        public Docket docket(Environment environment){
            RequestParameterBuilder builder = new RequestParameterBuilder();
            RequestParameter requestParameter = builder.name("token").description("令牌").in(ParameterType.HEADER).required(false).build();
    
            List<RequestParameter> globalRequestParameters = new ArrayList<>();
            globalRequestParameters.add(requestParameter);
            //设置要显示的Swagger环境
            Profiles profiles = Profiles.of("dev", "test");
            //通过environment.acceptsProfiles配置文件中设置的环境来判断是否在设定的环境中
            boolean flag = environment.acceptsProfiles(profiles);
            return new Docket(DocumentationType.OAS_30)// DocumentationType.OAS_30 固定的,代表swagger3.0
                    .groupName("分组1") // 如果配置多个文档的时候,那么需要配置groupName来分组标识
                    .apiInfo(apiInfo())
                    .enable(flag)
                    .select() // select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档
                    .apis(RequestHandlerSelectors.basePackage("com.example.controller"))// 用于指定扫描哪个包下的接口
                    //paths 指定扫描路径  PathSelectors.ant("/app/**")在controller包下,请求路径是/app/**可以扫描到
                    .paths(PathSelectors.any())// 选择所有的API,如果你想只为部分API生成文档,可以配置这里
                    .build().globalRequestParameters(globalRequestParameters);   //建造者模式
        }
    

在这里插入图片描述

  • 使用@ApiImplicitParams来额外标注一个请求头参数,例如:
@ApiOperation(value = "获取用户5",notes = "获取用户接口5-带token的接口")
@GetMapping("/getUser5")
@ApiImplicitParams({
        @ApiImplicitParam(name = "name",value = "账户",required = true,paramType = "query"),
        @ApiImplicitParam(name = "password",value = "密码",required = true,paramType = "query"),
        @ApiImplicitParam(name = "token",value = "令牌",required = true,paramType = "header"),

})
public User getUser5(String name,String password){
    return new User(name,password);
}

在这里插入图片描述

  • 整合了权限管理,可以给swagger加上权限管理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123871.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!