在springboot中整合jersey和springfox-swagger2
前言
提要
-
Springboot 集成swagger 通过springfox-swagger2实现SpringMVC的RESTful文档接口服务;
-
Springboot 集成 Jersey 通过swagger-jersey2-jaxrs 实现Jersey的文档接口服务;
环境
详细配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
< 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 >
|
1
2
|
server.servlet-path = /
spring.jersey.application-path = /api
|
1
2
3
4
5
6
7
8
9
10
|
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);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
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 );
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
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",
// "[email protected]"))
.version( "2.0" ).build();
}
private ApiInfo restInfo() {
return new ApiInfoBuilder().title( "berheley service rest api " ) // 大标题
.description( "spring boot webservice 平台 API" ) // 小标题
.version( "2.0" ).build();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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" ;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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!!!" ;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
<!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 >
|