在基于Spring-Boot的Jersey中集成Swagger

最近一时兴起,想将最近几年工作中用到的微服务栈,提干,优化一下作为Seed项目记录一下,省着忘了。
my-microservice-seed

本来想引入Swagger来作为Api描述与设计,以前在一个基于Spring REST开发的一个小后台项目中简单的初探过,配置起来很方便。
只要引入io.springfox的两个依赖,在提供一个配置类,配置类中在指定下下RestControlle所有在的包既可通过swagger-ui.html看到生成的描述。like this

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
/**
* @author liuxinsi
* @mail akalxs@gmail.com
*/
@Configuration
@EnableSwagger2
public class Swagger {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.lxs.mms.rs.resource"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("MMS")
.description("my microservice seed")
.version("1.0.0")
.contact(new Contact("liuxinsi", "https://liuxinsi.github.io", "akalxs@gmail.com"))
.build();
}
}

但这次试用的是Jersey,配置后没办法产生文档,根据日志看感觉配置的resource下都没扫到东西。最后在io.springfox与Swagger的github wiki上查了一下.

原来springfox提供的Swagger实现仅能作用于基于Spring MVC的REST实现,Jersey不行。。
想要用Swagger对Jersey生成的接口产生描述文档则需要:

  • 用Swagger-api提供的Swagger-core对Jersey的resource产生Swagger2的描述文件(类似WADL/WSDL)即swagger.json。
  • 在github上下载swagger-ui.
  • 用直接运行html或docker或nginx等运行swagger-ui。
  • 调整跨域策略或让swagger-ui与Jersey在同一域下。
  • 访问生成的swagger.json
  • all shit done.

乍一看颇为麻烦,但其实除了要手动处理下swagger-ui以外其他也还好,都是Swagger需要的步骤无非是自己做还是springfox帮你做好了。

完整代码

1
2
3
4
5
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>

引入swagger依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Swagger配置。
*
* @author liuxinsi
* @mail akalxs@gmail.com
*/
@Component
@Log4j2
public class Swagger {
@PostConstruct
public void initSwagger() {
log.debug("init Swagger ");
BeanConfig config = new BeanConfig();
config.setTitle("MMS");
config.setDescription("my microservice seed");
config.setVersion("1.0.0");
config.setContact("liuxinsi");
config.setSchemes(new String[]{"http", "https"});
config.setBasePath(JerseyConfig.APPLICATION_PATH);
config.setResourcePackage(JerseyConfig.RESOURCE_PACKAGE_NAME);
config.setPrettyPrint(true);
config.setScan(true);
}
}

配置整个服务的相关信息以及Resource所在包

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
package com.lxs.mms.rs.resource;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.springframework.stereotype.Component;
import javax.ws.rs.ApplicationPath;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* jersey 相关配置。
*
* @author liuxinsi
* @mail akalxs@gmail.com
*/
@Component
@ApplicationPath(JerseyConfig.APPLICATION_PATH)
public class JerseyConfig extends ResourceConfig {
public static final String APPLICATION_PATH = "services";
public static final String RESOURCE_PACKAGE_NAME = "com.lxs.mms.rs.resource";
/**
* 覆盖jersey logging 自带的jul logger
*/
private static final Logger REQ_RESP_LOGGER = Logger.getLogger("payload-logger");
public JerseyConfig() {
// 移除根日志处理器
SLF4JBridgeHandler.removeHandlersForRootLogger();
// 绑定新的处理器
SLF4JBridgeHandler.install();
// 请求 响应日志
REQ_RESP_LOGGER.setLevel(Level.FINE);
LoggingFeature lf = new LoggingFeature(REQ_RESP_LOGGER);
register(lf);
// 配置Swagger
this.register(ApiListingResource.class);
this.register(SwaggerSerializers.class);
packages(RESOURCE_PACKAGE_NAME);
}
}

注册两个feature,一个用于生成api信息,一个用于编解码产生swagger.json。

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
package com.lxs.mms.rs.resource.user;
import com.lxs.mms.rs.resource.ResourceSupport;
import com.lxs.mms.rs.resource.bean.user.UserInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Component;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author liuxinsi
* @mail akalxs@gmail.com
*/
@Component
@Path("/user/v1")
@Api(value = "用户相关服务", produces = "application/json")
public class UserResource extends ResourceSupport {
@ApiOperation(value = "加载所有用户", notes = "要分页")
@GET
@Path("/loadUsers")
public List<UserInfo> loadUsers() {
List<UserInfo> userInfos = new ArrayList<>(10);
for (int i = 0; i < 100; i++) {
UserInfo u = new UserInfo();
u.setId(i + "");
u.setName("u" + i);
u.setPwd("");
u.setRegisteDate(new Date());
userInfos.add(u);
}
return userInfos;
}
}

Resource类,注意@Api注解。

这时可以先启动spring-boot,访问http://127.0.0.1:8888/services/swagger.json,如生成了swagger2的信息则配置都成功。
部署swagger-ui,我是将下载到的静态资源直接部署在spring-boot的resource/static中,让swagger-ui的请求与swagger在一个域下。
最后重新启动spring-boot访问swagger-ui界面。


all shit done。