Documentación de la API REST de Java con Swagger2

En este artículo, nos sumergiremos en el marco Swagger. Usaremos Swagger2 para diseñar, construir y documentar una API RESTful de Spring Boot y una interfaz de usuario de Swagger para ob...

Introducción

En este artículo, nos sumergiremos en el Marco de arrogancia. Usaremos Swagger2 para diseñar, construir y documentar una Bota de primavera RESTful API y [Interfaz de usuario de Swagger](https:/ /swagger.io/tools/swagger-ui/) para observar nuestros puntos finales y probarlos.

¿Qué es Swagger? {#lo que es swagger}

Swagger es la herramienta más utilizada para crear API compatibles con la [Especificación de API abierta] (https://en.wikipedia.org/wiki/OpenAPI_Specification) (OAS).

Swagger en sí mismo es un conjunto de herramientas de código abierto creadas en torno a la OEA que pueden ayudarlo a diseñar, construir, documentar y generar los documentos de la API REST para los servicios web RESTful.

Las herramientas Swagger más destacadas son:

Swagger2 es una extensión de Swagger hacia nuevas tecnologías y protocolos más allá de HTTP.

Construyendo una aplicación

La integración de Swagger2 en una aplicación Spring Boot es bastante rápida y fácil con la ayuda de algunas herramientas que ya usamos día tras día.

La forma más sencilla de comenzar con un proyecto básico de Spring Boot, como siempre, es usar <a rel=“nofollow” target="_blank" href=" https://start.spring.io/">Spring Initializr.

Seleccione su versión preferida de Spring Boot y genere como un proyecto Maven y ¡ya está todo listo!

Para habilitar Swagger2 en sí mismo, deberá agregar un par de dependencias a su archivo pom.xml:

1
2
3
4
5
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${version}</version>
</dependency>

Con nuestro proyecto completamente configurado y nuestras dependencias bajo control, podemos continuar y crear un punto final REST simple que expondremos en la documentación más adelante:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@RestController
@RequestMapping("/v1/hello")
public class HelloResource {

    @GetMapping
    public String hello() {
        return "Hello World";
    }

    @PostMapping("/post")
    public String helloPost(@RequestBody String hello) {
        return hello;
    }

    @PutMapping("/put")
    public String helloPut(@RequestBody String hello) {
        return hello;
    }
}

Después de esto, sigamos adelante y creemos un punto final REST más: UserResource:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@RestController
@RequestMapping("/v1/user")
public class UserResource {

@GetMapping
public List<User> getUsers() {
    return Arrays.asList(
        new User("John", 3000),
        new User("Kevin", 2000)
    );
}

@GetMapping("/{userName}")
public User getUser(@PathVariable("userName") String userName) {
    return new User(userName, 2000);
}

Ambas clases se basan en el modelo Usuario:

1
2
3
4
5
6
7
private class User {

    private String userName;
    private Integer salary;

    // constructor, getters and setters
}

Habilitación de Swagger2 {#habilitación de Swagger2}

Ahora es el momento de habilitar Swagger2 en nuestra aplicación definiendo una clase de configuración para ella.

La clase de configuración debe anotarse con @Configuration, la anotación estándar de Spring, y las anotaciones @EnableSwagger2 para habilitar el marco para su aplicación Spring Boot.

El orden de estas anotaciones no es importante:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@EnableSwagger2
@Configuration
public class Swagger2Config {

    @Bean
    public Docket productApi() {
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.demo.resource"))
            .paths(regex("/v1.*"))
            .build();
    }
}

Definiremos un Bean llamado Docket en la clase de configuración para este propósito.

Docket es un constructor que pretende ser la interfaz principal en el marco swagger-springmvc. Proporciona valores predeterminados sensibles y métodos convenientes para la configuración.

Después de definir el bean Docket, llamar a su método select() devuelve una instancia de ApiSelectorBuilder, que proporciona control sobre los puntos finales expuestos por Swagger.

También podemos definir un paquete base para nuestras clases de API REST si lo deseamos, usando RequestHandlerSelectors.basePackage(). Escaneará el paquete base y creará API para todas las clases dentro de él.

Por otro lado, podemos usar RequestHandlerSelectors.any() para generar documentación para todos los paquetes.

En nuestro caso, es el paquete com.demo.resource, donde definimos las clases HelloResource y UserResource.

El método paths() define aún más para qué rutas en nuestras API queremos crear documentación. Todos nuestros puntos finales tienen "/v1", por lo que en nuestro caso incluye todos los puntos finales. Sin embargo, esto puede no ser siempre el caso.

Si desea incluir todos los puntos finales, puede hacerlo fácilmente usando PathSelectors.any().

Interfaz de usuario de Swagger

Usemos Swagger UI para observar todos nuestros puntos finales REST que creó Swagger.

Para utilizar la interfaz de usuario de Swagger, debemos agregar una dependencia a nuestro archivo pom.xml:

1
2
3
4
5
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${version}</version>
</dependency>

Ahora, navegue hasta localhost:8080/swagger-ui.html. Esta es la URL donde podemos observar todos los puntos finales de descanso que creó Swagger:

{.img-responsive}

Como puede ver, nuestros dos extremos están aquí: hello-resource y user-resource, con sus respectivos métodos dentro. Los nombres de los métodos se definen a la derecha, como puede ver.

Podemos usar esta interfaz de usuario para probar nuestros puntos finales:

  • Haga clic en HelloResource y expanda GET/v1/hello
  • Haga clic en el botón de llamada de descanso Pruébelo

{.img-responsive}

Seremos recibidos con el cuerpo de respuesta "Hello World" y el código de respuesta 200, lo que significa que está funcionando según lo previsto.

Lo mismo que para GET/v1/user de la clase UserResource:

{.img-responsive}

Seremos recibidos con la información relevante para el usuario que creamos antes.

Personalización de Swagger2 {#personalización de Swagger2}

A veces, las empresas y los equipos necesitan personalizar el comportamiento de Swagger2, agregando mensajes y operaciones personalizados para adaptar el uso del marco a sus propias necesidades.

Para hacer esto, necesitamos anular la metainformación del marco con ApiInfo.

El constructor de ApiInfo espera:

  • Título de la cadena
  • Descripción de la cadena
  • Versión de cadena
  • String termsOfServiceUrl
  • nuevo contacto (nombre de contacto, "", "")
  • Licencia de cadena
  • String URL de licencia

Si no desea definir ninguno de estos, puede ingresar null y ese campo no se mostrará en la interfaz de usuario:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@EnableSwagger2
@Configuration
public class SwaggerConfig {

    @Bean
    public Docket productApi() {
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.demo.resource"))
            .paths(regex("/v1.*"))
            .build()
            .apiInfo(metaInfo());
    }

    private ApiInfo metaInfo() {

        ApiInfo apiInfo = new ApiInfo(
            "Spring Boot Swagger2 Example API",
            null,
            "1.0",
            "Terms of Service",
            new Contact("Your Name or Team", null,
                null),
            "Apache License Version 2.0",
            "https://www.apache.org/licenses/"
        );

        return apiInfo;
    }
}

{.img-responsive}

Podemos anular los nombres de los métodos con anotaciones.

La anotación @ApiOperation nos permite anular el punto final y su tipo de respuesta. Swagger2 también permite anular los mensajes de respuesta predeterminados de los métodos ‘HTTP’.

Puede usar la anotación @ApiResponse para documentar otras respuestas, además del HTTP 200 OK habitual:

1
2
3
4
5
6
@ApiOperation(value = "Returns Hello World", description = "shows hello world")
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "The request has succeeded or (your message)"),
        @ApiResponse(code = 401, message = "The request requires user authentication or (your message)"),
        @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden or (your message)"),
        @ApiResponse(code = 404, message = "The server has not found anything matching the Request-URI or (your message)")

Echemos un vistazo a la interfaz de usuario:

{.img-responsive}

Al expandir hello-resource podemos ver que el lado derecho de la documentación se actualizó. Además, los mensajes de respuesta se actualizaron con el código que proporcionamos y el tipo de retorno de la anotación @Api en el nivel de clase.

Propiedades del modelo

Swagger2 nos proporciona un conjunto de anotaciones para manipular modelos con mucho control:

  • @ApiModel - Nos permite manipular los metadatos de un modelo
  • @ApiModelProperty: nos permite controlar las definiciones y operaciones específicas de Swagger (valores permitidos, notas, filtrado)

Tendremos que actualizar nuestro controlador UserResource con la anotación @Api en el nivel de clase.

En Swagger2, esta anotación se usa para aplicar definiciones a todas las operaciones definidas bajo ella, a diferencia de su uso en versiones anteriores, donde declaraba recursos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@RestController
@RequestMapping("/v1/user")
@Api(value = "User Resource REST Endpoint", description = "Shows the user info")
public class UserResource {

    @GetMapping
    public List<User> getUsers() {

        return Arrays.asList(
            new User("John", 2000),
            new User("Kevin", 1000)
        );
    }

    @GetMapping("/{userName}")
    public User getUser(@PathVariable("userName") String userName) {
        return new User(userName, 1000);
    }

Después de actualizar la API, actualicemos también el modelo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@ApiModel
private class User {

    @ApiModelProperty(notes = "name of the user")
    private String userName;

    @ApiModelProperty(notes = "salary of the user")
    private Integer salary;

    @ApiModelProperty(allowableValues = "active, inactive, banned")
    private String status;

    // constructor, getters and setters
}

Hay una amplia gama de cosas que puede definir usando @ApiModelProperty. Para obtener más información y una lista de métodos, visite [la documentación oficial](http://docs.swagger.io/swagger-core/v1.5.X/apidocs/index.html?io/swagger/annotations/ApiModelProperty. html).

{.img-responsive}

Expandiendo GET/v1/user y luego haciendo clic en la propiedad Modelo, podemos notar las descripciones en cada campo.

"Valor de ejemplo" muestra solo los valores predeterminados.

Conclusión

Cada día, las empresas y las personas comienzan a utilizar Swagger como su herramienta preferida para exponer las API REST a terceros.

Al utilizar las herramientas de Swagger, puede generar código basado en la documentación de una API, así como también crear documentación atractiva e interactiva. Esto ahorra tiempo y esfuerzo y ofrece un estándar con el que trabajar.