javascript
学习Spring Boot:(六) 集成Swagger2
前言
Swagger是用來描述和文檔化RESTful API的一個項目。Swagger Spec是一套規范,定義了該如何去描述一個RESTful API。類似的項目還有RAML、API Blueprint。 根據Swagger Spec來描述RESTful API的文件稱之為Swagger specification file,它使用JSON來表述,也支持作為JSON支持的YAML。
Swagger specification file可以用來給swagger-ui生成一個Web的可交互的文檔頁面,以可以用swagger2markup生成靜態文檔,也可用使用swagger-codegen生成客戶端代碼。總之有了有個描述API的JSON文檔之后,可以做各種擴展。
Swagger specification file可以手動編寫,swagger-editor為了手動編寫的工具提供了預覽的功能。但是實際寫起來也是非常麻煩的,同時還得保持代碼和文檔的兩邊同步。于是針對各種語言的各種框架都有一些開源的實現來輔助自動生成這個`Swagger specification file。
swagger-core是一個Java的實現,現在支持JAX-RS。swagger-annotation定義了一套注解給用戶用來描述API。
spring-fox也是一個Java的實現,它支持Spring MVC, 它也支持swagger-annotation定義的部分注解。
使用
添加依賴
在pom文件添加:
<swagger.version>2.7.0</swagger.version><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>配置docket
@Configuration @EnableSwagger2 public class SwaggerConfig {/*** SpringBoot默認已經將classpath:/META-INF/resources/和classpath:/META-INF/resources/webjars/映射* 所以該方法不需要重寫,如果在SpringMVC中,可能需要重寫定義(我沒有嘗試)* 重寫該方法需要 extends WebMvcConfigurerAdapter*/ // @Override // public void addResourceHandlers(ResourceHandlerRegistry registry) { // registry.addResourceHandler("swagger-ui.html") // .addResourceLocations("classpath:/META-INF/resources/"); // // registry.addResourceHandler("/webjars/**") // .addResourceLocations("classpath:/META-INF/resources/webjars/"); // }@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.wuwii")).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("Spring Boot中使用Swagger2構建RESTful APIs").description("rest api 文檔構建利器").termsOfServiceUrl("https://blog.wuwii.com/").contact("KronChan").version("1.0").build();} }builder說明
根據網上一位前輩的文章:
@Beanpublic Docket petApi() {return new Docket(DocumentationType.SWAGGER_2).select() //1.apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build().pathMapping("/") //2.directModelSubstitute(LocalDate.class, //3String.class).genericModelSubstitutes(ResponseEntity.class) //4.alternateTypeRules( //5newRule(typeResolver.resolve(DeferredResult.class,typeResolver.resolve(ResponseEntity.class, WildcardType.class)),typeResolver.resolve(WildcardType.class))).useDefaultResponseMessages(false) //6.globalResponseMessage(RequestMethod.GET, //7newArrayList(new ResponseMessageBuilder().code(500).message("500 message").responseModel(new ModelRef("Error")).build())).securitySchemes(newArrayList(apiKey())) //8.securityContexts(newArrayList(securityContext())) //9;}方法說明:
接口上添加文檔
@RestController @Api(description = "這是一個控制器的描述 ") public class PetController {/*** logger*/private static final Logger LOGGER = LoggerFactory.getLogger(PetController.class);private String no;private String kind;private String name;@ApiOperation(value="測試接口", notes="測試接口描述")@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "Long", paramType = "path"),@ApiImplicitParam(name = "pet", value = "寵物", required = true, dataType = "PetController")})@ApiResponses({@ApiResponse(code = 200, message = "請求完成"),@ApiResponse(code = 400, message = "請求參數錯誤")})@RequestMapping(path = "/index/{id}", method = RequestMethod.PUT)public PetController index1(@PathVariable("id") String id, @RequestBody PetController pet) {return pet;}//…… get / set常用的注解說明
查看API文檔
啟動Spring Boot程序,訪問:http://host:port/swagger-ui.html
。就能看到RESTful API的頁面。打開我們的測試接口的API ,可以查看這個接口的描述,以及參數等信息:
點擊上圖中右側的Model Schema(黃色區域:它指明了這個requestBody的數據結構),此時pet中就有了pet對象的模板,修改上測試數據,點擊下方Try it out!按鈕,即可完成了一次請求調用!
調用完后,我們可以查看接口的返回信息:
參考文章
- Spring Boot中使用Swagger2構建強大的RESTful API文檔檔
- spring-boot-swagger2 使用手冊
- 使用springfox生成springmvc項目的swagger的文檔
例外補充點
驗證碼
我使用的是 com.github.axet.kaptcha 的驗證碼
雖然按照別人的方法使用 HttpServletResponse 輸出流,這種是暴露 Servlet 的接口。但是發現了一個問題了,在 swagger 的獲取驗證碼接上測試的時候不能得到驗證碼圖片,但是在 img 標簽中是沒問題,發現 swagger 還是把我的返回結果作為 json 處理。所以我還是想到使用下載中二進制流的方法,將 BufferedImage 轉換成二進制流數組,總算是解決。
上最后解決的辦法:
/*** 獲取驗證碼*/@GetMapping(value = "/captcha.jpg", produces = MediaType.IMAGE_JPEG_VALUE)public ResponseEntity<byte[]> captcha()throws IOException {//生成文字驗證碼String text = producer.createText();//生成圖片驗證碼BufferedImage image = producer.createImage(text);ByteArrayOutputStream out = new ByteArrayOutputStream();ImageIO.write(image, "jpg", out);// 文字驗證碼保存到 shiro sessionShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text);HttpHeaders headers = new HttpHeaders();headers.setCacheControl("no-store, no-cache");return ResponseEntity.status(HttpStatus.OK).headers(headers).body(out.toByteArray());我是采用 ImageIO 工具類的將 BufferedImage 轉換成 輸出流,從輸出流中獲取二進制流數組。
ImageIO.write(BufferedImage image,String format,OutputStream out)再補充一個 將二進制流數組 byte[] 轉換成 BufferedImage
// 將二進制流數組轉換成輸入流 ByteArrayInputStream in = new ByteArrayInputStream(byte[] byets); // 讀取輸入流 BufferedImage image = ImageIO.read(InputStream in);在 swagger 上是這樣的了:
配置不同環境中是否啟動
在不同環境種配置是否啟用規則:
swagger:enable: true # or false在 swagger 配置類中加入
/*** 啟用*/@Value("${swagger.enable}")private boolean enable;…… set / get配置 Docket 中
@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())// 加入 enable.enable(enable).select().apis(RequestHandlerSelectors.basePackage("com.wuwii")).paths(PathSelectors.any()).build();}SpringMVC 中配置 Swagger2
Swagger 的配置文件:
@Configuration @EnableSwagger2 @EnableWebMvc @ComponentScan("com.devframe.controller") public class SwaggerConfig extends WebMvcConfigurerAdapter {/*** 靜態文件過濾* @param registry*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.devframe")).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("RESTful APIs").description("rest api 文檔構建利器").termsOfServiceUrl("https://blog.wuwii.com/").version("1.0").build();}}額外需要在 web.xml 配置:
<!-- Springmvc前端控制器掃描路徑增加“/v2/api-docs”,用于掃描Swagger的 /v2/api-docs,否則 /v2/api-docs無法生效。--><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/v2/api-docs</url-pattern></servlet-mapping>單元測試中會出現的錯誤
發現加入 Swagger 后,以前的單元測試再運行的時候,會拋出一個異常,參考 How to run integration tests with spring and springfox?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper' defined in URL [jar:file:/C:/Users/test/.m2/repository/io/springfox/springfox-spring-web/2.0.0-SNAPSHOT/springfox-spring-web-2.0.0- SNAPSHOT.jar!/springfox/documentation/spring/web/plugins/DocumentationPluginsBootstrapper.class]: Unsatisfied dependency expressed through constructor argument with index 1 of type [java.util.List]: : No qualifying bean of type [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] found for dependency [collection of org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] found for dependency [collection of org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}1解決,單元測試上加入 @EnableWebMvc
總結
以上是生活随笔為你收集整理的学习Spring Boot:(六) 集成Swagger2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Golang基础知识入门详解
- 下一篇: 谈Servlet与JSP