在springboot中整合jersey和springfox-swagger2
前言
为了实现RESTful Webservice和接口说明,基于springboot平台,使用jersey作为JAX-RS的实现,采用swagger文档在线生成工具。
提要
在实现了springboot集成jersey的swagger文档功能,同时满足SpringMVC 整合swagger提供RESTful文档功能。
Springboot 集成swagger 通过springfox-swagger2实现SpringMVC的RESTful文档接口服务;
Springboot 集成 Jersey 通过swagger-jersey2-jaxrs 实现Jersey的文档接口服务;
环境
Springboot 1.5.1.RELEASE
springfox-swagger 2 2.6.1
swagger 1.5.12
详细配置
1、Pom文件
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<swagger.version>1.5.12</swagger.version>
<springfox-swagger2.version>2.6.1</springfox-swagger2.version>
<spring.boot.version>1.5.1.RELEASE</spring.boot.version>
</properties>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 支持自动确定版本路径: 写法由:link rel=‘stylesheet‘ href=‘/webjars/bootstrap/3.1.0/css/bootstrap.min.css‘
变为: link rel=‘stylesheet‘ href=‘/webjars/bootstrap/css/bootstrap.min.css‘ -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.32</version>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- springboot 集成 jersey 、swagger 实现 JAX-RS Restful 開始 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- swagger 静态资源 -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>2.2.10</version>
</dependency>
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>spring-bridge</artifactId>
<version>2.5.0-b34</version>
</dependency>
<!-- springboot 集成 jersey 、swagger 实现 JAX-RS Restful 結束 -->
<!-- springboot 集成 swagger 实现SpringMVC Restful 開始 -->
<!-- 解决 springfox-swagger 依赖swagger版本过低问题 -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-swagger2.version}</version>
</dependency>
<!-- springboot 集成 swagger 实现SpringMVC Restful 結束 -->
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<configuration>
<mainClass>sample.rs.service.SampleRestApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>2、springboot配置文件 application.properties
server.servlet-path = / spring.jersey.application-path = /api
3、springboot启动class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SampleRestApplication {
public static void main(String[] args) {
SpringApplication.run(SampleRestApplication.class, args);
}
}4、Jersey配置类,整合swagger
import javax.annotation.PostConstruct;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.wadl.internal.WadlResource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import sample.jersey.demo1.HelloResource;
import sample.jersey.demo1.JerseyTest;
import sample.jersey.demo2.Endpoint;
import sample.jersey.demo2.ReverseEndpoint;
import sample.jersey.demo3.HelloService;
@Component
public class JerseyConfig extends ResourceConfig {
@Value("${spring.jersey.application-path}")
private String apiPath;
public JerseyConfig() {
register(Endpoint.class);
register(ReverseEndpoint.class);
this.registerEndpoints();
}
@PostConstruct
public void init() {
// Register components where DI is needed
this.configureSwagger();
}
private void registerEndpoints() {
this.register(HelloResource.class);
this.register(JerseyTest.class);
this.register(HelloService.class);
// Access through /<Jersey‘s servlet path>/application.wadl
this.register(WadlResource.class);
}
private void configureSwagger() {
// Available at localhost:port/swagger.json
this.register(ApiListingResource.class);
this.register(SwaggerSerializers.class);
BeanConfig config = new BeanConfig();
config.setConfigId("springboot-jersey-swagger-docker-example");
config.setTitle("Spring Boot + Jersey + Swagger + Docker Example");
config.setVersion("v1");
config.setContact("wzh");
config.setSchemes(new String[] { "http", "https" });
config.setBasePath(this.apiPath);
config.setResourcePackage("sample.jersey");
config.setPrettyPrint(true);
config.setScan(true);
}
}5、Swagger配置类,支持spirngMVC RESTful文档功能
import static com.google.common.base.Predicates.or;
import static springfox.documentation.builders.PathSelectors.regex;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.base.Predicate;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* api doc -- springfox swagger configuration
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Value("${spring.jersey.application-path}")
private String apiPath;
@Bean
public SecurityScheme apiKey() {
return new ApiKey("access_token", "accessToken", "header");
}
@Bean
public Docket apiConfig() {
return new Docket(DocumentationType.SWAGGER_2).groupName("controller")
// 调用apiInfo方法,创建一个ApiInfo实例,里面是展示在文档页面信息内容
.apiInfo(apiInfo()).select()
// 控制暴露出去的路径下的实例
// 如果某个接口不想暴露,可以使用以下注解
// @ApiIgnore 这样,该接口就不会暴露在 swagger2 的页面下
.apis(RequestHandlerSelectors.basePackage("sample.jersey.controller")).paths(PathSelectors.any())
.build().useDefaultResponseMessages(false).securitySchemes(Arrays.asList(apiKey()));
}
@Bean
public Docket restConfig() {
return new Docket(DocumentationType.SWAGGER_2).groupName("jax-rs").apiInfo(restInfo()).forCodeGeneration(true)
.pathMapping("/").select().paths(paths())// 过滤的接口
.build().useDefaultResponseMessages(false);
}
// 请求url匹配,支持and or,可以过滤筛选
private Predicate<String> paths() {
return or(regex("/test/.*"), regex("/rest/.*")); //
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("berheley service controller api ")// 大标题
.description("spring boot webservice 平台 API")// 小标题
// .termsOfServiceUrl("http://ww.swagger.com/")
// .contact(new Contact("swagger", "www.swagger.com",
// "swagger@foxmail.com"))
.version("2.0").build();
}
private ApiInfo restInfo() {
return new ApiInfoBuilder().title("berheley service rest api ")// 大标题
.description("spring boot webservice 平台 API")// 小标题
.version("2.0").build();
}
}6、SprintMVC风格的web 服务示例
package sample.jersey.controller;
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 io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@Controller
@RequestMapping("/test")
public class TestController {
@ResponseBody
@RequestMapping(value = "/show", method = RequestMethod.POST) // 这里指定RequestMethod,如果不指定Swagger会把所有RequestMethod都输出,在实际应用中,具体指定请求类型也使接口更为严谨。
@ApiOperation(value = "测试接口", notes = "测试接口详细描述")
public String show(@ApiParam(required = true, name = "name", value = "姓名") @RequestParam(name = "name") String stuName) {
return "success";
}
}7、JAX-RS 实现的服务示例
package sample.jersey.demo3;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.springframework.stereotype.Service;
@Path("/rest")
@Component
public class HelloService {
@GET
@Path("/sayHello/{a}")
@Produces(MediaType.TEXT_PLAIN)
public String sayHello(@PathParam("a") String a) {
return "Hello " + a + ", Welcome to CXF RS Spring Boot World!!!";
}
}8、将swagger-ui包中的index.html复制到static目录下,修改资源文件路径
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<title>Swagger UI</title>
<link rel="icon" type="image/png" href="webjars/swagger-ui/images/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="webjars/swagger-ui/images/favicon-16x16.png" sizes="16x16" />
<link href=‘/webjars/swagger-ui/css/typography.css‘ media=‘screen‘ rel=‘stylesheet‘ type=‘text/css‘/>
<link href=‘/webjars/swagger-ui/css/reset.css‘ media=‘screen‘ rel=‘stylesheet‘ type=‘text/css‘/>
<link href=‘/webjars/swagger-ui/css/screen.css‘ media=‘screen‘ rel=‘stylesheet‘ type=‘text/css‘/>
<link href=‘/webjars/swagger-ui/css/reset.css‘ media=‘print‘ rel=‘stylesheet‘ type=‘text/css‘/>
<link href=‘/webjars/swagger-ui/css/print.css‘ media=‘print‘ rel=‘stylesheet‘ type=‘text/css‘/>
<script src=‘/webjars/swagger-ui/lib/object-assign-pollyfill.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/jquery-1.8.0.min.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/jquery.slideto.min.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/jquery.wiggle.min.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/jquery.ba-bbq.min.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/handlebars-4.0.5.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/lodash.min.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/backbone-min.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/swagger-ui.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/highlight.9.1.0.pack.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/highlight.9.1.0.pack_extended.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/jsoneditor.min.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/marked.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lib/swagger-oauth.js‘ type=‘text/javascript‘></script>
<!-- Some basic translations -->
<script src=‘/webjars/swagger-ui/lang/translator.js‘ type=‘text/javascript‘></script>
<script src=‘/webjars/swagger-ui/lang/zh-cn.js‘ type=‘text/javascript‘></script>
<script type="text/javascript">
$(function () {
var url = window.location.search.match(/url=([^&]+)/);
if (url && url.length > 1) {
url = decodeURIComponent(url[1]);
} else {
url = "/api/swagger.json";
}
hljs.configure({
highlightSizeThreshold: 5000
});
// Pre load translate...
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
window.swaggerUi = new SwaggerUi({
url: url,
dom_id: "swagger-ui-container",
supportedSubmitMethods: [‘get‘, ‘post‘, ‘put‘, ‘delete‘, ‘patch‘],
onComplete: function(swaggerApi, swaggerUi){
if(typeof initOAuth == "function") {
/* initOAuth({
clientId: "your-client-id",
clientSecret: "your-client-secret-if-required",
realm: "your-realms",
appName: "your-app-name",
scopeSeparator: " ",
additionalQueryStringParams: {}
}); */
}
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
},
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none",
jsonEditor: false,
defaultModelRendering: ‘schema‘,
showRequestHeaders: false,
showOperationIds: false
});
window.swaggerUi.load();
function log() {
if (‘console‘ in window) {
console.log.apply(console, arguments);
}
}
});
</script>
</head>
<body class="swagger-section">
<div id=‘header‘>
<div class="swagger-ui-wrap">
<a id="logo" href="http://swagger.io"><img class="logo__img" alt="swagger" height="30" width="30" src="/webjars/swagger-ui/images/logo_small.png" /><span class="logo__title">swagger</span></a>
<form id=‘api_selector‘>
<div class=‘input‘><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div>
<div id=‘auth_container‘></div>
<div class=‘input‘><a id="explore" class="header__btn" href="#" data-sw-translate>Explore</a></div>
</form>
</div>
</div>
<div id="message-bar" class="swagger-ui-wrap" data-sw-translate> </div>
<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
</body>
</html>9、结果展示
http://localhost:8080/ 为Jersey 的文档路径
http://localhost:8080/swagger-ui.html 为SpringMVC的controller文档路径
文章来自:http://skyfly.blog.51cto.com/12626797/1901744

