Swagger2使用起來很簡單,加一個@EnableSwagger2註解,並引入以下依賴就ok了html
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency>
配置好以後,啓動項目,瀏覽器輸入 http://localhost:8080/swagger-ui.html 應該就能看到api頁面了。java
But…git
Unable to infer base url. This is common when using dynamic servlet registration or when the API is behind an API Gateway. The base url is the root of where all the swagger resources are served. For e.g. if the api is available at http://example.org/api/v2/api-docs then the base url is http://example.org/api/. Please enter the location manually:github
問題緣由:項目中使用了Spring Security,swagger2相關的資源沒作免登陸配置web
解決辦法:增長以下配置,把Swagger2相關的請求都容許spring
@Component public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { // allow Swagger URL to be accessed without authentication web.ignoring().antMatchers( "/swagger-ui.html", "/v2/api-docs", // swagger api json "/swagger-resources/configuration/ui", // 用來獲取支持的動做 "/swagger-resources", // 用來獲取api-docs的URI "/swagger-resources/configuration/security", // 安全選項 "/swagger-resources/**" ); } }
解決認證問題以後,打開swagger-ui,頁面是出來了,不過頁面提示json
fetching resource list: http://localhost:8080undefined;api
api 選擇下拉框裏面也是undefined,瀏覽器f12有js報錯瀏覽器
Uncaught DOMException: Failed to execute 'open' on 'XMLHttpRequest': Invalid URL
at h.end (http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:13:5344)
at u.execute (http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:7:29443)
at n.exports.c.execute (http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:7:27351)
at t.exports.g.build (http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:7:17807)
at t.exports.g.initialize (http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:7:16198)
at new t.exports (http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:7:14664)
at C.n.load (http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:13:11513)
at C.n.updateSwaggerUi (http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:13:11182)
at C.n.(http://localhost:8080/webjars/springfox-swagger-ui/swagger-ui.min.js:13:10872) 安全
at u (http://localhost:8080/webjars/springfox-swagger-ui/lib/backbone-min.js:1:2091)
頁面能出來了,至少說明免認證的配置是生效了。
由於swagger的js已經被壓縮過,很難從這段js報錯發現問題。本想從網上找下源碼,無功而返。
不甘心,從網上下載了自定義的ui,稍做整理後,上傳到個人github上了
這個自定義的有2個版本,只改了UI,沒有改java代碼邏輯,
訪問地址分別是
- swagger/index.html
- swagger-v2/docs.html
將這2個地址加入過濾,而後方式試了下,結果發現
swagger/index.html 能夠正常訪問
swagger-v2/docs.html 也有js報錯
有錯爆出來,又有源碼,就好辦了。查看了下js報錯的位置,是調用了 /v2/api-docs 後處理返回json數據報錯了。
直接在瀏覽器裏面訪問了下 /v2/api-docs ,發現回來的數據直接是{「error_no」:「0」,「error_info」:「」}
這裏應該不對了,返回的怎麼會是這個呢?
debug跟蹤一下,springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation方法處理完以後,返回的是
return new ResponseEntity<Json>(jsonSerializer.toJson(swagger), HttpStatus.OK); // 其中JSON對象代碼以下 package springfox.documentation.spring.web.json; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonValue; public class Json { private final String value; public Json(String value) { this.value = value; } @JsonValue @JsonRawValue public String value() { return value; } }
並且這裏的json數據仍是正常的,繼續往下執行,發現進入到了項目自定義的ResponseBodyAdvice中。在這個加強器中,對返回的數據都統一加了error_no和error_info。
繼續debug發現,這個方法裏面把body轉成了map,而在轉換的時候,獲得的是空的map!!??
那爲何明明有數據的body對象,轉map就成空的了呢?
// object轉map方法核心代碼摘錄以下 BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor property : propertyDescriptors) { String key = property.getName(); if (StringUtils.equalsIgnoreCase(key, "class")) { continue; } Method getter = property.getReadMethod(); Object value = getter != null ? getter.invoke(obj) : null; }
原來,beanInfo.getPropertyDescriptors()獲取屬性描述的時候,只能拿到 getXXX,setXXX方法。而上面的Json對象的value字段恰好沒有getValue方法。