Spring Boot integrated Swagger interface classification and sorting of each element

In the previous article, we completed the use of JSR-303 verification and used Swagger2 to obtain relevant interface documents. In this section, based on the original, we completed the specific configuration method in Swagger about controlling the order of each element.

Swagger interface grouping

First of all, we need to organize the interfaces in Swagger with the Controller layer as the first level gradient. In our actual development, there is a one-to-many relationship between Controller and other specific interfaces. We can group the interfaces that belong to the same module The interface is defined in a Controller. By default, our Swagger groups and manages interfaces based on Controller. In Swagger, the elements of this group are called Tags, but the relationship between Tag and interface here is not One-to-many relationship, which supports richer many-to-many relationships,

Default grouping

First, let’s take a look at how we deal with how Swagger organizes the relationship between Tags and interfaces based on Controllers by creating a simple example. We define two Controllers, which are respectively responsible for the teacher management and student management interfaces. In order to reuse the code, We added the code based on the previous article:
For the sake of simplicity and clarity, I put the following code in the Application class

@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {<!-- -->

    @GetMapping("/miaow")
    public String miaow() {<!-- -->
        return "miaow";
    }
}

@RestController
@RequestMapping(value = "/student")
static class StudentController {<!-- -->

    @ApiOperation("Get student list")
    @GetMapping("/list")
    public String bbb() {<!-- -->
        return "bbb";
    }

    @ApiOperation("Get the list of teachers who teach a certain student")
    @GetMapping("/his-teachers")
    public String ccc() {<!-- -->
        return "ccc";
    }

    @ApiOperation("Create a student")
    @PostMapping("/aaa")
    public String aaa() {<!-- -->
        return "aaa";
    }
}

At this time, we can access the organizational structure of Swagger through: localhost:8080/swagger-ui.html


In the picture above, we understand the control layer we defined, and the default structure generated by swagger is displayed.

application.properties file

swagger.title=spring-boot-starter-swagger
swagger.description=Starter for swagger 2.x
swagger.version=1.9.0.RELEASE
swagger.license=Apache License, Version 2.0
swagger.licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.html
swagger.termsOfServiceUrl=https://github.com/dyc87112/spring-boot-starter-swagger
swagger.contact.name=miaow
swagger.contact.url=https://luoxiaohei520.github.io
[email protected]
swagger.base-package=com.didispace
swagger.base-path=/**

swagger.ui-config.tags-sorter=alpha
swagger.ui-config.operations-sorter=alpha

Add the relevant control layer interface to the startup class:

@EnableSwagger2Doc
@SpringBootApplication
public class Application {<!-- -->
    public static void main(String[] args) {<!-- -->
       SpringApplication.run(Application.class, args);
    }

    @Api(tags = {<!-- -->"1-Teacher Management","3-Teaching Management"})
    @RestController
    @RequestMapping(value = "/teacher")
    static class TeacherController {<!-- -->
        @ApiOperation(value = "miaow")
        @GetMapping("/miaow")
        public String miaow() {<!-- -->
            return "miaow";
        }
    }
    
    @Api(tags = {<!-- -->"2-Student Management"})
    @RestController
    @RequestMapping(value = "/student")
    static class StudentController {<!-- -->
        @ApiOperation(value = "Get student list", tags = "3-Teaching Management")
        @GetMapping("/list")
        public String bbb() {<!-- -->
            return "bbb";
        }
        @ApiOperation("Get the list of teachers who teach a certain student")
        @GetMapping("/his-teachers")
        public String ccc() {<!-- -->
            return "ccc";
        }
        @ApiOperation("Create a student")
        @PostMapping("/aaa")
        public String aaa() {<!-- -->
            return "aaa";
        }
    }
}

get result set

Customize the name of the default group

@Api(tags = "Teacher Management")
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {<!-- -->
    // ...
}

@Api(tags = "Student Management")
@RestController
@RequestMapping(value = "/student")
static class StudentController {<!-- -->
    // ...
}

We modify the tags in the Api to the expression text we want:

Merge Controller groups

Here, we use a one-to-one correspondence between Tag and Controller. Swagger also supports more flexible grouping! From the @Api annotation, if we look at the detailed code, we find that the tags attribute is actually an array type.


Therefore, we can summarize the relevant interfaces in the Controller by defining a Tag with the same name. For example, we can define a Tag as “Teaching Management” so that this group includes all interfaces for teacher management and student management. The case is as follows:

@Api(tags = {<!-- -->"Teacher Management", "Teaching Management"})
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {<!-- -->
    // ...
}

@Api(tags = {<!-- -->"Student Management", "Teaching Management"})
@RestController
@RequestMapping(value = "/student")
static class StudentController {<!-- -->
    // ...
}

Update fine-grained interface grouping

@Api can be used to merge the interfaces in the Controller into a Tag, but if we want to accurately merge a certain interface, what should we do?

@Api(tags = {<!-- -->"Teacher Management","Teaching Management"})
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {<!-- -->

    @ApiOperation(value = "maiow")
    @GetMapping("/miaow")
    public String miaow() {<!-- -->
        return "miaow";
    }

}

@Api(tags = {<!-- -->"Student Management"})
@RestController
@RequestMapping(value = "/student")
static class StudentController {<!-- -->

    @ApiOperation(value = "Get student list", tags = "Teaching Management")
    @GetMapping("/list")
    public String bbb() {<!-- -->
        return "bbb";
    }

    @ApiOperation("Get the list of teachers who teach a certain student")
    @GetMapping("/his-teachers")
    public String ccc() {<!-- -->
        return "ccc";
    }

    @ApiOperation("Create a student")
    @PostMapping("/aaa")
    public String aaa() {<!-- -->
        return "aaa";
    }

}

Get the rendering:

Order of content

After completing the grouping of interfaces, we can adjust the display order of interface content. Among them, we mainly involve three aspects: grouping sorting, interface sorting, and parameter sorting.

Group sorting

Regarding grouping sorting, that is, Tag sorting. The current version of Swagger support is not very good. Through the documentation, we can find the configuration method for Tag sorting.

The first one is suitable for native Swagger users, modify:

The second way: Swagger Starter users can modify the configuration:

swagger.ui-config.tags-sorter=alpha

Modify the source code of the above configuration:

public enum TagsSorter {<!-- -->
  ALPHA("alpha");

  private final String value;

  TagsSorter(String value) {<!-- -->
    this.value = value;
  }

  @JsonValue
  public String getValue() {<!-- -->
    return value;
  }

  public static TagsSorter of(String name) {<!-- -->
    for (TagsSorter tagsSorter : TagsSorter.values()) {<!-- -->
      if (tagsSorter.value.equals(name)) {<!-- -->
        return tagsSorter;
      }
    }
    return null;
  }
}

We can find that Swagger provides an option to sort by alphabetical order.

@Api(tags = {<!-- -->"1-Teacher Management","3-Teaching Management"})
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {<!-- -->

    // ...

}

@Api(tags = {<!-- -->"2-Student Management"})
@RestController
@RequestMapping(value = "/student")
static class StudentController {<!-- -->

    @ApiOperation(value = "Get student list", tags = "3-Teaching Management")
    @GetMapping("/list")
    public String bbb() {<!-- -->
        return "bbb";
    }
    // ...
}

Ordering of interfaces

After completing the group sorting problem (although it is not very elegant…), let’s take a look at how to implement sorting for each interface within the same group. Similarly, if you check the documentation in advance, you can see that Swagger also provides corresponding configurations. The following two configuration methods are introduced:
The first one is still suitable for native Swagger users and can be modified:

The second type: Swagger Starter users can modify the configuration method:

swagger.ui-config.operations-sorter=alpha

Unlike Tag’s sorting configuration, this configuration has no options. It provides two configuration items: alpha and method, which represent alphabetical sorting and sorting by method definition order respectively. When we do not configure it, the configuration defaults to alpha.

Parameter sorting

After completing the sorting of interfaces, the more fine-grained sorting is the sorting of request parameters. By default, our Swagger will display the parameter content of the Model in alphabetical order. Our displayed User is like this before Swagger. :

Now, we hope to display the member variables in the order defined in the Model, so we need to set the position through the position parameter of the @ApiModelProperty annotation.

The corresponding User object is as follows:

w is not added

@ApiModel(description = "User Entity")
public class User {<!-- -->

    @ApiModelProperty(value = "User ID", position = 1)
    private Long id;

    @NotNull
    @Size(min = 2, max = 5)
    @ApiModelProperty(value = "User Name", position = 2)
    private String name;

    @NotNull
    @Max(100)
    @Min(10)
    @ApiModelProperty(value = "User age", position = 3)
    private Integer age;

    @NotNull
    @Email
    @ApiModelProperty(value = "User Email", position = 4)
    private String email;


    public Long getId() {<!-- -->
        return id;
    }

    public void setId(Long id) {<!-- -->
        this.id = id;
    }

    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;
    }

    public String getEmail() {<!-- -->
        return email;
    }

    public void setEmail(String email) {<!-- -->
        this.email = email;
    }

    public User(Long id, String name, Integer age, String email) {<!-- -->
        this.id = id;
        this.name = name;
        this.age = age;
        this.email = email;
    }

    public User() {<!-- -->
    }
}

Swagger display after adding Position: