swagger2 離線文件 文件中心搭建 json swagger 自動生成api文件
最近找了一個自動生成api文件的工具swagger,相對swaggerEdit就不說了。個人比較懶,還是自動生成來的便捷,尤其是老專案,新專案在初期可能會維護,但是到了後期就很難保證了。所以,那些需要一些特殊配置說明的文件工具就不提了。
這篇文章主要是在swagger2 swagger UI的基礎上結合nginx解決跨域來實現統一的api文件中心,至於如何搭建swagger2請自行百度。
使用swagger2生成離線文件比較麻煩,尤其是非springcloud專案(具體實現方式,請自行百度)。本文另闢蹊徑,通過修改swagger部分js指令碼檔案、提供統一的資源載入路徑、使用nginx反向代理解決swagger測試跨域問題,來搭建一個統一的api文件中心繫統。
首先說一下swagger的jar包:
其他自行百度,主要說一下swagger的請求流程:
swaggerUI的靜態檔案:
springfox-swagger-ui-2.6.1.jar 解壓縮開啟後在META-INF\resources下面就可以看到我們訪問的html頁以及靜態檔案。
swagger2的幾個資源服務controller:
swagger-resources//configuration/security
swagger-resources/configuration/ui:控制頁面展示效果
swagger-resources/:比較重要,這個也是我們要覆蓋重寫的主要協議
所在jar包:springfox-swagger-common-2.6.1.jar
controller類路徑: springfox.documentation.swagger.web.ApiResourceController
最重要的程式碼路徑,生成api文件的服務:
jar包:springfox-swagger2-2.6.1.jar
controller類路徑:springfox.documentation.swagger2.web.Swagger2Controller
我們要搭建中心api文件,或者離線文件,那就需要更改js檔案,把資源路徑修改為統一的服務路徑或者靜態json(訪問/v2/api-docs可以獲取介面描述json)檔案。
貼程式碼:重寫swagger-resources服務和提供統一的api-docs文件(swagger-resources提供的location就是生成介面描述頁面資料的來源訪問路徑):
@RequestMapping("my")
@RestController
public class SwaggerController {
private static Logger logger = LoggerFactory.getLogger(SwaggerController.class);
private static Map<String,SwaggerResource> resourceMap = new HashMap<String,SwaggerResource>();
public static void getDocJson(){
String filename = "apidoc.json";
Type type =new TypeToken<Map<String,SwaggerResource>>(){}.getType();
resourceMap = new Gson().fromJson(
new InputStreamReader(SwaggerController.class.getClassLoader().getResourceAsStream(filename),Charset.forName("UTF-8")),type);
}
static{
getDocJson();
}
@RequestMapping("/swagger-resources")
public ResponseEntity<List<SwaggerResource>> swaggerResources() {
getDocJson();
List<SwaggerResource> swaggerResources = new ArrayList<SwaggerResource>();
if(resourceMap!=null&&resourceMap.size()>0){
for (String key : resourceMap.keySet()) {
SwaggerResource resource = resourceMap.get(key);
swaggerResources.add(resource);
if(StringUtils.isBlank(resource.getLocation())){
resource.setLocation("/my/apidoc/"+key);
}
}
}
/*SwaggerResource resource = new SwaggerResource();
resource.setName("default");
resource.setLocation("/v2/api-docs");
resource.setSwaggerVersion("2.0");
swaggerResources.add(resource);
resource = new SwaggerResource();
resource.setName("本地檔案");
resource.setLocation("/apidoc/Goods_0.0.1.json");
resource.setSwaggerVersion("0.0.1");
swaggerResources.add(resource);
resource = new SwaggerResource();
resource.setName("遠端測試");
resource.setLocation("http://127.0.0.1/Goods_0.0.1.json");
resource.setSwaggerVersion("0.0.1");
swaggerResources.add(resource);*/
return new ResponseEntity<List<SwaggerResource>>(swaggerResources, HttpStatus.OK);
}
@RequestMapping("/apidoc/{id}")
public String findJsonDocs1(@PathVariable("id")String id) {
SwaggerResource resource = resourceMap.get(id);
String swagger = "";
if(StringUtils.isNotBlank(resource.getPath())){
RestTemplate template = new RestTemplate();
ResponseEntity<String> body = template.exchange(resource.getPath(), HttpMethod.GET, null, String.class);
try {
return new String(body.getBody().getBytes("iso8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
logger.error("遠端獲取資料轉碼異常(findJsonDocs1):", e);
}
}else if(StringUtils.isNotBlank(resource.getFileName())){
try {
InputStreamReader in = new InputStreamReader(SwaggerController.class.getClassLoader().getResourceAsStream(resource.getFileName()),Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(in);
String tmp = null;
StringBuilder sb = new StringBuilder();
while((tmp = reader.readLine()) != null){
sb.append(tmp);
}
swagger = sb.toString();
} catch (IOException e) {
logger.error("讀取檔案異常(findJsonDocs1):", e);
}
return swagger;
}
return JSONObject.toJSONString( new Swagger());
}
}
提供的配置檔案:apidoc.json
{
"1":{"name":"default","location":"/v2/api-docs","swaggerVersion":"2.0","host":"http://localhost:8080/","path":"","fileName":""},
"2":{"name":"本地檔案","location":"","swaggerVersion":"2.0","host":"http://localhost:8080","path":"","fileName":"Goods_0.0.1.json"},
"3":{"name":"遠端檔案","location":"","swaggerVersion":"2.0","host":"http://127.0.0.1","path":"http://127.0.0.1/Goods_0.0.1.json","fileName":""}
}
其中,path表示遠端http協議路徑,fileName表示本地資原始檔路徑。
對應的Bean實體類:
public class SwaggerResource extends springfox.documentation.swagger.web.SwaggerResource{
/**
* 域名埠
*/
private String host;
/**
* 遠端資源路徑
*/
private String path;
/**
* 本地資源
*/
private String fileName;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
貼一下改寫的js檔案:springfox.js:
function initializeBaseUrl() {
var relativeLocation = springfox.baseUrl();
$('#input_baseUrl').hide();
$.getJSON(relativeLocation + "/my/swagger-resources", function(data) {
var $urlDropdown = $('#select_baseUrl');
$urlDropdown.empty();
$.each(data, function(i, resource) {
var option = $('<option></option>')
.attr("value", maybePrefix(resource.location, relativeLocation))
.text(resource.name + " (" + resource.location + ")");
$urlDropdown.append(option);
});
$urlDropdown.change();
});
}
這是springfox.js的最後一個函式(initializeBaseUrl),如果是搭建中心的api文件系統,更改/swagger-resources路徑為我們自定義的服務路徑/my/swagger-resources即可。
如果是搭建離線的文件,講這部分程式碼改寫成訪問靜態資原始檔就可以了。
/swagger-resources資料格式:
[{"name":"default","location":"/v2/api-docs","swaggerVersion":"2.0"}]
效果圖: