SpringMVC+Swagger UI生成可檢視的API文件(詳細圖解)
Swagger UI
關於Swagger UI官方解釋是這樣的:The Swagger UI is an open source project to visually render documentation for a Swagger defined API directly from the API’s Swagger specifcation 官網地址
下面是官方的效果圖:
我將上圖分成了兩部分
- 文件地址:從改地址請求資料,獲取JSON格式資料,交給第二步顯示
- API文件顯示:將JSON資料轉化成可檢視的效果
Swagger可以將某種固定格式的JSON資料生成可以檢視的線上API文件,支援線上測試,可以清楚的觀察到IO資料
SpringMVC + Swagger
目的:在原有的SpringMVC系統中新增Swagger,通過在介面上添加註解實現,介面文件的同步效果。
下圖為我實現之後的效果:
專案搭建
我的工具:Eclipse開發工具(安裝Spring外掛,當然也可以不要,就是麻煩點),Maven,Tomcat,Internet訪問,Chrome瀏覽器
1.建立Simple Spring Web Maven工程
右鍵New->Spring Project,選擇對應型別,finish, 如下圖:
我的工程的結構,注意那兩個配置檔案,名稱不重要,可以隨便改,注意要對應好web.xml中的名稱就行。
想了想還是把三個配置檔案貼出來吧。
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id ="WebApp_ID" version="2.5">
<display-name>SwaggerDemo</display-name>
<!--
- Location of the XML file that defines the root application context.
- Applied by ContextLoaderListener.
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
- Servlet that dispatches request to registered handlers (Controller implementations).
-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
application-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Uncomment and add your base-package here:
<context:component-scan
base-package="org.springframework.samples.service"/> -->
</beans>
mvc-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Uncomment and your base-package here:
<context:component-scan
base-package="org.springframework.samples.web"/> -->
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
這樣配置到後面配置Swagger會出現無法自動注入的問題,後面再說,以上為工具自動生成的程式碼。
2.新增Swagger-Spring MVC包、JSON和jackson
pom.xml檔案中
properties標籤裡面新增jackson版本號
<version.jackson>2.4.4</version.jackson>
dependencies標籤中新增
<!-- Swagger -->
<dependency>
<groupId>com.mangofactory</groupId>
<artifactId>swagger-springmvc</artifactId>
<version>0.9.5</version>
</dependency>
<!-- JSON -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- JACKSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${version.jackson}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${version.jackson}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${version.jackson}</version>
</dependency>
3.下面是重點,Swagger所有API文件都在這裡儲存,新增Swagger配置類
建立一個配置類MySwaggerConfig,新增私有成員SpringSwaggerConfig,set方法使用@Autowired註解自動注入,使用@Bean註解新增SwaggerSpringMvcPlugin,並使用自定義的ApiInfo,SwaggerConfig類需要新增@Configuration以及@EnableSwagger
package com.edu.xk;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import com.mangofactory.swagger.configuration.SpringSwaggerConfig;
import com.mangofactory.swagger.models.dto.ApiInfo;
import com.mangofactory.swagger.plugin.EnableSwagger;
import com.mangofactory.swagger.plugin.SwaggerSpringMvcPlugin;
@Configuration
@EnableSwagger
@EnableWebMvc
public class MySwaggerConfig {
private SpringSwaggerConfig springSwaggerConfig;
/**
* Required to autowire SpringSwaggerConfig
*/
@Autowired
public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
this.springSwaggerConfig = springSwaggerConfig;
}
/**
* Every SwaggerSpringMvcPlugin bean is picked up by the swagger-mvc
* framework - allowing for multiple swagger groups i.e. same code base
* multiple swagger resource listings.
*/
@Bean
public SwaggerSpringMvcPlugin customImplementation() {
// 暫時不用過濾
/*return new SwaggerSpringMvcPlugin(this.springSwaggerConfig).apiInfo(apiInfo()).includePatterns(".*pet.*");*/
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig).apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo(
"My Apps API Title",
"My Apps API Description",
"My Apps API terms of service",
"My Apps API Contact Email",
"My Apps API Licence Type",
"My Apps API License URL"
);
return apiInfo;
}
}
官方原話:
The @EnableSwagger annotation, in this example, enables swagger-springmvc out of the box. The generated swagger json Resource Listing is available at /api-docs
4.新增Controller:WebServiceForCSS,Swagger文件在此處新增
package com.edu.xk.webservice;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.edu.xk.model.User;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import net.sf.json.JSONObject;
/**
* @moudle: WebServiceForCSS
* @version:v1.0
* @Description: TODO
* @author: xukai
* @date: 2016年12月1日 下午5:37:30
*
*/
@Controller
public class WebServiceForCSS {
@ResponseBody
@RequestMapping(value = "getUserById", method = RequestMethod.GET, produces = {"application/json; charset=utf-8","application/xml"})
@ApiOperation(value = "通過ID查詢USER資訊", httpMethod = "GET", notes = "暫無")
public String getUserById(
@ApiParam(required = true, name = "id", value = "ID")
@RequestParam(value = "id") String id,HttpServletRequest request) {
User user = new User();
user.setId(id);
user.setName("測試人員");
user.setAge(25);
JSONObject object = JSONObject.fromObject(user);
return object.toString();
}
}
5.配置檔案修改
context載入的時候需要配置的檔案,此處配置檔案為application-config.xml
<mvc:annotation-driven /> <!-- mvc-config.xml中的可以去掉 -->
<context:component-scan base-package="com.edu"/>
<bean class="com.edu.xk.configer.SwaggerConfig"/>
6.下載Swagger UI元件
去官網下載Zip包,或者在github上下載也可以,需要將dist資料夾下的所有檔案的複製到webapp目錄下。
7.修改Project Properties
將jdk1.5換成最新的本地的jdk,對應的Java complier也改為對應的,還有maven包依賴也需要新增,不然啟動的時候會找不到ContextLoader.class。
8.新增攔截器,不然無法訪問.html字尾檔案,在web.xml中新增
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.ico</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.xls</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.doc</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>
<!-- 字型相關 開始 -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.eot</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.svg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.ttf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.woff</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.woff2</url-pattern>
</servlet-mapping>
<!-- 字型相關 結束 -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
執行專案,可以看到效果圖:
可以看到,現在效果還是和官網上一樣的。改為自己的API文件可以通過修改index.html中的url = "http://petstore.swagger.io/v2/swagger.json";
或者直接修改訪問的位址列為:http://localhost:8080/SwaggerDemo/api-docs
原理分析
SpringMVC+Swagger其實就是在系統載入的時候,Swagger配置類去掃描所有添加註釋的介面,並且儲存起來通過下面地址進行訪問,返回JSON資料,在前端介面顯示出來
這裡我在網上看到一個漢化的版本(原效果),下載了他工程,將他生成demo.json放入的我的工程中的webapp目錄下,下面是效果圖
遇到的問題
- 問題1:下載maven的jar包中途失敗,工程會出錯maven missing
解決方法:選中Project->右鍵maven->update project->選中Force update 如果此時依然有
missing的jar,按照 buildpath 提示的 jar包missing 路徑,去 maven
本地倉庫中對應位置(jar包後面有路徑),刪掉 該 jar 包的 xxx.lastUpdated 檔案,之後,再重新執行
專案右鍵maven->update project - 問題2:缺失jackson包會導致出現異常java.lang.NoClassDefFoundError:
com/fasterxml/jackson/databind/ObjectMapper) - 問題3:java.lang.ClassNotFoundException:
org.springframework.web.util.Log4jConfigListen,因為工程沒有引入maven中的jar包,解決辦法:選中工程右鍵->Properties->Deployment Assembly->add->Java Build Path Entries->Maven Dependencies->OK 問題4:org.springframework.beans.factory.BeanCreationException,出現這個異常是因為SpringSwaggerConfig的私有成員RequestMappingHandlerMapping造成的,將
<mvc:annotation-driven />
放入到web.xml的context-param標籤對應的配置檔案application-config.xml中,完美解決,官網解釋該標籤作用為: Required so swagger-springmvc can access spring’s RequestMappingHandlerMapping 。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: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Swagger Editor
反正順路,順便的Editor也寫完,Editor個人感覺就是一個文件編輯器,感覺SosoApi還是好些。試著在Swagger官網下載了一個Swagger Editor跑著玩了玩.下載swagger-editor.zip,解壓到Tomcat的webapps資料夾中,來看一下效果圖
Swagger UI結合Swagger Editor更好用,但是線上編輯那個太卡了,備份一個本地的,以備不時只需。