Code ví dụ Swagger với springfox-swagger2, swagger ui

Code ví dụ Swagger với springfox-swagger2, swagger ui

(Xem lại: Swagger là gì)

Trong bài này mình sẽ sử dụng lại Code ví dụ Spring Boot RESTful Webservice với các api thêm, sửa, xóa user và tạo tài liệu để import vào swagger.

Tạo Spring Boot Project

Code ví dụ Swagger với springfox-swagger2, swagger ui

Thư viện sử dụng

Để sử dụng swagger ta thêm 2 thư viện sau:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger2</artifactId>
  <version>2.8.0</version>
</dependency>
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger-ui</artifactId>
  <version>2.8.0</version>
</dependency>

Thư viện springfox-swagger-ui giúp bạn nhúng sẵn phần mềm swagger-ui vào project, phần mềm swagger ui sẽ được start cùng project.

ví dụ swagger ui với spring

Cấu hình swagger

package stackjava.com.sbrestful.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
        		.apiInfo(getApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("stackjava.com.sbrestful.controller"))
                .paths(PathSelectors.any())
                .build();
    }
    
    private ApiInfo getApiInfo() {
        Contact contact = new Contact("stackjava.com", "https://stackjava.com", "cuong.9312@gmail.com");
        return new ApiInfoBuilder()
                .title("Spring Boot Swagger")
                .description("Demo Spring Boot Swagger")
                .version("1.0.0")
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .contact(contact)
                .build();
    }
}
  • Bean Docket sẽ xác định các class trong package nào được tạo document, thông tin là gì… (ví dụ ở đây mình tạo document cho các class trong package stackjava.com.sbrestful.controller)
  • Method getApiInfo() sẽ trả về thông tin hiển thị trên swagger:

ví dụ swagger getApiInfo

File entity

package stackjava.com.sbrestful.entities;

import io.swagger.annotations.ApiModelProperty;
public class User {
  
    @ApiModelProperty(notes = "Id auto increase upon create new")
  private int id;
  private String username;
  private String password;

  // getter - setter
}
  • Annotation @ApiModelProperty dùng để giải thích các field của model trên swagger:

Ví dụ trên swagger, class User sẽ hiển thị như sau:

giải thích các field của model trên swagger

File Controller

package stackjava.com.sbrestful.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import stackjava.com.sbrestful.entities.User;

@RestController
@RequestMapping("/rest")
@Api(tags = "Users Rest Controller")
public class UserRestController {

  public static HashMap<Integer, User> mapUser = new HashMap<Integer, User>();
  static {
    mapUser.put(1, new User(1, "kai", "123456"));
    mapUser.put(2, new User(2, "admin", "admin1234"));
    mapUser.put(3, new User(3, "sena", "123456"));
    mapUser.put(4, new User(4, "peter", "1234"));
  }

  @RequestMapping(value = "/users", method = RequestMethod.GET, produces= MediaType.APPLICATION_JSON_UTF8_VALUE)
  @ApiOperation(value = "Get all users", tags = "Users Rest Controller")
  @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"),
      @ApiResponse(code = 400, message = "Bad request"),
      @ApiResponse(code = 500, message = "Internal server error") })
  public ResponseEntity<List<User>> getAllUser() {
    List<User> listUser = new ArrayList<User>(mapUser.values());
    return new ResponseEntity<List<User>>(listUser, HttpStatus.OK);
  }

  @ApiOperation(value = "Get User By ID", tags = "Users")
  @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"),
      @ApiResponse(code = 400, message = "Bad request"),
      @ApiResponse(code = 500, message = "Internal server error") })
  @RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
  public ResponseEntity<Object> getUserById(@PathVariable int id) {
    User user = mapUser.get(id);
    if (user != null) {
      return new ResponseEntity<Object>(user, HttpStatus.OK);
    }
    return new ResponseEntity<Object>("Not Found User", HttpStatus.NO_CONTENT);
  }

  @ApiOperation(value = "Create new User")
  @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"),
      @ApiResponse(code = 400, message = "Bad request"),
      @ApiResponse(code = 500, message = "Internal server error") })
  @RequestMapping(value = "/users", method = RequestMethod.POST)
  public ResponseEntity<String> createUser(@RequestBody User user) {
    if (mapUser.containsKey(user.getId())) {
      return new ResponseEntity<String>("User Already Exist!", HttpStatus.CONFLICT);
    }
    mapUser.put(user.getId(), user);
    return new ResponseEntity<String>("Created!", HttpStatus.CREATED);
  }

  @ApiOperation(value = "Delete User")
  @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"),
      @ApiResponse(code = 400, message = "Bad request"),
      @ApiResponse(code = 500, message = "Internal server error") })
  @RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
  public ResponseEntity<String> deleteUserById(@PathVariable int id) {
    User user = mapUser.get(id);
    if (user == null) {
      return new ResponseEntity<String>("Not Found User", HttpStatus.OK);
    }

    mapUser.remove(id);
    return new ResponseEntity<String>("Deleted!", HttpStatus.OK);
  }

  @ApiOperation(value = "Update User")
  @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"),
      @ApiResponse(code = 400, message = "Bad request"),
      @ApiResponse(code = 500, message = "Internal server error") })
  @RequestMapping(value = "/users", method = RequestMethod.PUT)
  public ResponseEntity<String> updateUser(@RequestBody User user) {
    User oldUser = mapUser.get(user.getId());
    if (oldUser == null) {
      return new ResponseEntity<String>("Not Found User", HttpStatus.NO_CONTENT);
    }
    mapUser.put(user.getId(), user);
    return new ResponseEntity<String>("Updated!", HttpStatus.OK);
  }

}
  • Annotation @Api(tags = “Users Rest Controller”) dùng để nhóm tất cả các api (method) trong class thành một nhóm:

code ví dụ annotation @api swagger

  • Annotation @ApiOperation dùng để chỉ rõ method nào sẽ được tạo document:
    • value: mô tả chức năng của method
    • tags: khai báo nhóm cho
    • annotation @ApiResponses dùng để chỉ rõ code và message trả về

Ví dụ mô tả của method getAllUser trên swagger sẽ như sau:

mô tả của method trên swagger mô tả của method trên swagger

Trong trường hợp bạn muốn giải thích các paramater trong request thì ta có thể dùng annotation @ApiImplicitParams

Ví dụ trong method getAllUser mình muốn truyền thêm thông tin page và size để phân trang kết quả trả về thì mình sẽ dùng thêm annotation sau trước method getAllUser

@ApiImplicitParams(
        value = {
                @ApiImplicitParam(name = "page", value = "page number start from 0", dataType = "integer",
                        examples = @Example(@ExampleProperty("1")), paramType = "query"),
                @ApiImplicitParam(name = "size", value = "maximum number of item in page", dataType = "integer",
                        examples = @Example(@ExampleProperty("40")), paramType = "query"),
        }
)

ví dụ annotation @ApiImplicitParams swagger

Config Cors

Trong trường hợp phần mềm swagger và project của bạn không cùng địa chỉ, ta cần enable cors để cho phép swagger có thể gửi ajax tới project spring boot.

Ví dụ trong trường hợp mình chạy phần mềm swagger ui riêng rồi start project spring boot riêng, nếu không enable cors thì sẽ gặp lỗi sau:

lỗi cors với swagger và cách khắc phục

package stackjava.com.sbrestful.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {
  
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**");
  }
  
  @Bean
  public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    // Allow anyone and anything access. Probably ok for Swagger spec
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/v2/api-docs", config);
    return new CorsFilter(source);
  }
}

Demo:

Sau khi cấu hình xong swagger và start project, mặc định thông tin swagger sẽ được tạo ra ở url: http://localhost:8080/v2/api-docs

thông tin swagger sẽ được tạo ra

Bây giờ bạn chỉ cần nhập http://localhost:8080/v2/api-docs vào ô input explorer của swagger là nó sẽ tạo document api cho bạn:

Code ví dụ Swagger với springfox-swagger2, swagger ui

Hoặc bạn có thể chạy swagger trên project với url localhost:8080/swagger-ui.html

ví dụ swagger ui với spring

Ví dụ thực hiện kiểm tra, chạy thử api get all users trên swagger:

demo test api trên swagger

Ví dụ thực hiện lấy thông tin của user có id = 1

demo spring boot swagger

Với những trường hợp put, post các bạn thêm data giống vào body, nhìn chung swagger hoạt động giống hệt như một rest client (ví dụ như postman)

Code ví dụ Swagger với springfox-swagger2, swagger ui stackjava.com

Okay, Done!

Download code ví dụ trên tại đây.

References:

swagger.io/docs/specification/about

stackjava.com