Building Dynamic RESTful API with Swagger 2 in Spring MVC

Keywords: Java Spring Mobile Maven github

When multi-terminal (WEB/mobile) needs common business logic, RESTful-style services are generally constructed for multi-terminal use.

To reduce the cost of frequent communication with the corresponding terminal development team, we will initially create a RESTful API document to record all interface details.

However, as the project progresses, the problems exposed by doing so become more and more serious.

a. There are many interfaces and complicated details (different HTTP request types, HTTP header information, HTTP request content.) It is very difficult to create this document with high quality.

b. Continuous modification of interface implementations requires simultaneous modification of interface documents. Documents and codes are in two different media. Unless there is a strict management mechanism, inconsistencies can easily result.

Based on this, the project team introduced Swagger earlier, and after several projects precipitation, it did have a good effect.

Swagger is a normative and complete framework for generating, describing, invoking and visualizing RESTful-style Web services.

The methods, parameters and models of the service are tightly integrated into the server-side code, which integrates the maintenance document and the adjustment code, and keeps the API synchronized all the time.

This paper mainly describes the integration process of Swagger and Spring MVC and some problems encountered, which can be used only when a brick is thrown to attract jade, and specific project analysis.

  

1. Maven dependencies and minimal configuration

      <!--restfull APi swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>

Spring-Context Swagger configuration:

    <! - swagger2 configuration class - >
    <bean id="config" class="com.rambo.spm.core.config.SwaggerConfig"/>

    <! - swagger2 static resources are handed over to spring management mapping (springfox-swagger-ui.jar is a static resource bundle) --> uuuuuuuuuuu
    <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/"/>
    <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>

Spring MVC handles static resources and adds some useful value-added functions.

A. <mvc: resources/> allows static resources to be placed anywhere, such as under WEB-INF directory, classpath, etc., completely breaking the restriction that static resources can only be placed under the root path of the Web container.

B. <mvc: resources/> optimizes static resources according to the well-known browser optimization principles such as Page Speed and YSlow.

SwaggerConfig configuration class:

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
    }
    private ApiInfo apiInfo() {
        ApiInfoBuilder apiInfoBuilder = new ApiInfoBuilder();
        apiInfoBuilder.title("SPM Doc");
        apiInfoBuilder.description("SPM Api File");
        apiInfoBuilder.contact(new Contact("orson", "https://www.cnblogs.com/", ""));
        apiInfoBuilder.version("2.0");
        return apiInfoBuilder.build();
    }
}

For which request method API s are generated? Swagger provides the following methods for restricting the scope of the RequestHandlerSelectors object:

2. Service Annotation Configuration Practice

After the above operations, Swagger has actually been integrated. In the process of project development, only the corresponding annotations need to be added to the corresponding RESTful service.

@Api: Annotate on a class to illustrate the role of that class. You can tag a Controller class as a swagger document resource in the following way:

@Api(description = "user management")

Annotation @ApiOperation: Notes on methods, explains the role of methods, the definition of each url resource, and how to use it:

@ApiOperation(value = "Get a list of all users")

The @ApiParam and @ApiImplicitParam are annotated to the parameter to explain the function of the parameter and how to use it:

@ApiParam(value = "user ID") String userId

All of these are the simplest configurations, and building clear API documents is enough, and of course there is a lot more. Rich notes Just know.

@RestController
@Api(description = "user management")
public class UserRestController extends BaseController {
    @Autowired
    private SysUserService sysUserService;

    @GetMapping("r/user/get")
    @ApiOperation(value = "Get specific user details")
    public Object getUser(ModelMap modelMap, @ApiParam(value = "user ID") String userId) {

    }

    @PostMapping("r/user/add")
    @ApiOperation(value = "Add user")
    public Object addUser(ModelMap modelMap, @ModelAttribute @Valid SysUser user, BindingResult result) {

    }
}

Some problems encountered in the follow-up use of the project:

a. Some methods include HttpServletRequest, HttpServletResponse, HttpSession, ModelMap and so on. These parameters are meaningless when generating API documents. How is Swagger configured correctly?

Initially, these parameters are annotated with @ApiParam(hidden = true). When there are many methods, these types of parameters are written once, which is very redundant to use.

Docket objects are found to have ignoredParameterTypes method in API. It is convenient to uniformly define overlooked parameter types in configuration classes.

public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .ignoredParameterTypes(ModelMap.class, HttpServletRequest.class,HttpServletResponse.class, BindingResult.class)
                .select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
    }

b. How to annotate when the parameters of the request are encapsulated objects? How to annotate attributes in an object? How to shield every attribute in an object?

When the parameters of the request are objects, the corresponding objects are annotated with Spring@ModelAttribute annotation, and the attributes in the objects are @ApiModelProperty, masking the attributes of @ApiModelProperty(hidden = true)

    @ApiModelProperty(hidden = true)
    private String uuid;

    @ApiModelProperty("Full name")
    private String name;

    @ApiModelProperty("Password")
    private String passwd;

Swagger has a wealth of tools and can do a lot of things. What this article describes is just to let you quickly understand it, use it, check more information when you need it, and read more blogs.

Posted by Coruba67 on Wed, 09 Jan 2019 11:54:10 -0800