最近公司内部系统要做数据对接,故使用 jersey 来做 restful webservice 接口设计。由于 spring boot 已经集成 jersey,估计直接导入 spring-boot-starter-jersey 就好了。

在测试时候除了遇到中文乱码之外花费了比较长的时间,其余暂时没遇到大的问题。然而发布的时候发现了一个坑。

public class JerseyConfig extends ResourceConfig {

    public JerseyConfig(){
//registerClasses(findAllClasses());
packages("com.xx");
// 注册日志
register(LoggingFeature.class);
// 异常处理
register(ExceptionHandler.class);
// 跨域过滤器注册
register(CorsFilter.class); }
}

jersey 是使用 register(Class clazz) 或者 packages("packageName") 来注册或者扫描来加载所需的类到容器中的。然而在实际项目中,使用 register(Class clazz) 会写大量的注册类,依赖性太强,而且在maven多模块中更不好处理。

而使用 packages 来扫描,在开发测试的时候倒没发现什么问题,但是使用 spring boot 打成 jar 包运行时,会产生 FileNotFound 的错误,这是因为 使用 jersey 的 packages 扫描的机制是无法扫描到 jar 中的 class 文件的。

由于使用的是 spring boot,spring 的 component scan 是可以做到的。故参考 spring 扫描机制的源码,将 jar 中的 class 文件加载进来就好了。

代码如下:

import lombok.extern.slf4j.Slf4j;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.ClassUtils; import java.io.IOException;
import java.util.HashSet;
import java.util.Set; /**
* @author gongtao
* @version 2018-04-23 10:15
**/
@Configuration
@Slf4j
public class JerseyConfig extends ResourceConfig { public JerseyConfig(){
//扫描注册
registerClasses(findAllClasses());
// 注册日志
register(LoggingFeature.class);
// 异常处理
register(ExceptionHandler.class);
// 跨域过滤器注册
register(CorsFilter.class); } /**
* 由于spring boot 打包为jar包,jersey packages 无法扫描jar对应的文件夹的文件,故自定义包扫描
* @return
*/
private Set<Class<?>> findAllClasses(){
String scanPackages = "com.xxx.eoms.innerinterface.interfaces.resource.*";
ClassLoader loader = this.getClass().getClassLoader();
Resource[] resources = new Resource[0];
try {
resources = scan(loader, scanPackages);
} catch (IOException e) {
log.error("加载class异常",e);
}
return convert(loader, resources);
} /**
* 扫描 jar 包
* @param loader
* @param packageName
* @return
* @throws IOException
*/
private Resource[] scan(ClassLoader loader, String packageName) throws IOException {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(loader);
String pattern = "classpath*:" + ClassUtils.convertClassNameToResourcePath(packageName) + "/**/*.class";
return resolver.getResources(pattern);
} /**
* 加载 class
* @param loader
* @param resource
* @return
*/
private Class<?> loadClass(ClassLoader loader,Resource resource) {
try {
CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(loader);
MetadataReader reader = metadataReaderFactory.getMetadataReader(resource);
return ClassUtils.forName(reader.getClassMetadata().getClassName(), loader);
} catch (LinkageError | ClassNotFoundException e) {
if (log.isDebugEnabled()) {
log.debug("Ignoring candidate class resource " + resource + " due to " + e);
}
return null;
} catch (Throwable e) {
if (log.isWarnEnabled()) {
log.warn("Unexpected failure when loading class resource " + resource, e);
}
return null;
}
} /**
* resources 转换为 Set<Class>
* @param loader
* @param resources
* @return
*/
private Set<Class<?>> convert(ClassLoader loader,Resource[] resources){
Set<Class<?>> classSet = new HashSet<>(resources.length);
for (Resource resource : resources){
Class<?> clazz = loadClass(loader, resource);
if (clazz != null){
classSet.add(clazz);
}
}
return classSet;
}

jersey在 spring boot 添加 packages 扫描路径支持的更多相关文章

  1. Spring boot 默认静态资源路径与手动配置访问路径的方法

    这篇文章主要介绍了Spring boot 默认静态资源路径与手动配置访问路径的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下   在application.propertis中配置 ##端口号 ...

  2. Spring Boot 添加JSP支持【转】

    Spring Boot 添加JSP支持 大体步骤: (1)            创建Maven web project: (2)            在pom.xml文件添加依赖: (3)     ...

  3. spring boot: @EnableScheduling开启计划任务支持,@Scheduled计划任务声明

    spring boot: @EnableScheduling开启计划任务支持, @Scheduled计划任务声明 package ch2.scheduler2; //日期转换方式 import jav ...

  4. spring boot 添加拦截器

    构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Appli ...

  5. Spring Boot 添加jersey-mvc-freemarker依赖后内置tomcat启动不了解决方案

    我在我的Spring Boot 项目的pom.xml中添加了jersey-mvc-freemarker依赖后,内置tomcat启动不了. 报错信息如下: org.springframework.con ...

  6. spring boot 添加拦截器的简单实例(springBoot 2.x版本,添加拦截器,静态资源不可访问解决方法)

    spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor 一.HandlerInterceptor HandlerInterceptor是s ...

  7. spring boot 添加整合ssl使得http变成https方法

    1. https出现的背景:(1)都知道http传输协议是裸漏的,明文传输的,极易被黑客拦截,因此,(2)人们想出的使用加密,也就是 对称加密 例如aes,不过这个由于因为对称加密需要每个客户端和服务 ...

  8. spring boot mybatis没有扫描jar中的Mapper接口

    只需要在spring boot启动类上加上注解,并指定jar包中接口文件包路径即可 如下: @ComponentScan(basePackages = "com.xx") @Map ...

  9. 为项目配置了Bean,结果Spring Boot并没有扫描到

    问题如图,而这个问题遇见的场景是因为自己在一个基础项目里面配置cros,按照网上的说法都配置了一边,结果发现前后端的通讯仍然报跨域问题.后来怀疑是否bean并没有被注入进去,导致没有生效,于是在代码中 ...

随机推荐

  1. JVM堆内存监测的一种方式,性能调优依旧任重道远

    上月,由极客邦.InfoQ和听云联合主办2016 APMCon中国应用性能管理大会圆满落下帷幕.会上,Java冠军Martijn Verburg进行了一场Java and the Machine的分享 ...

  2. SVN汉化教程2017.10.6

    https://jingyan.baidu.com/album/b87fe19e95f5925219356853.html?picindex=4

  3. jQuery学习之旅 Item2 选择器【二】

    这里接着上一个Item1 把jQuery的选择器讲完.主要有:属性过滤器和子元素过滤器 点击"名称"会跳转到此方法的jQuery官方说明文档. 5. 属性过滤器 Attribute ...

  4. 第一个vue示例-高仿微信

    这时我学习vue写的第一个demo,因为以前学过angular,所以这次看vue的时候是先写demo,在写的过程中遇到不会的在看书的方式学习的,因为是针对性学习,所以可以快速的对vue有个大概的认识, ...

  5. github 用git bash上传项目 最后提示 Everything up-to-date 但没传上去

    今天为了把本地的项目远程到githup远程仓库,把好久不用的githup命令重新用了起来,不用怀疑,很正常的出错了. 为了长点记性,总结错误与解决办法如下: 1.我犯得第一个简单错误,是忘了git c ...

  6. Java开源生鲜电商平台-监控模块的设计与架构(源码可下载)

    Java开源生鲜电商平台-监控模块的设计与架构(源码可下载) 说明:Java开源生鲜电商平台-监控模块的设计与架构,我们谈到监控,一般设计到两个方面的内容: 1. 服务器本身的监控.(比如:linux ...

  7. inner join 与 left join 之间的区别

    关于inner join 与 left join 之间的区别,以前以为自己搞懂了,今天从前端取参数的时候发现不是预想中的结果,才知道问题出在inner join 上了. 需求是从数据库查数据,在前端以 ...

  8. Java多线程简介

    Java多线程简介 Java中内置了对多线程的支持,让多线程的开发方便很多,但同时也带来了另外的复杂,线程间的交互以及很多的不确定性让多线程又显得很复杂.在此只是针对Java中多线程的基础做些说明,有 ...

  9. 【最小生成树】UVA1494Qin Shi Huang's National Road System秦始皇修路

    Description During the Warring States Period of ancient China(476 BC to 221 BC), there were seven ki ...

  10. BZOJ_3191_[JLOI2013]卡牌游戏_概率DP

    BZOJ_3191_[JLOI2013]卡牌游戏_概率DP Description   N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随 ...