最近公司内部系统要做数据对接,故使用 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. SwaggerUI--SosoApi

    1.SwaggerUI是什么? Swagger UI是一款RESTFUL接口的文档在线自动生成+功能测试功能软件. Swagger-UI 的官方地址:http://swagger.io/ Github ...

  2. 《Spring Cloud与Docker微服务架构实战》配套代码

    不才写了本使用Spring Cloud玩转微服务架构的书,书名是<Spring Cloud与Docker微服务架构实战> - 周立,已于2017-01-12交稿.不少朋友想先看看源码,现将 ...

  3. 最强AngularJS资源合集

    AngularJS是Google开源的一款JavaScript MVC框架,弥补了HTML在构建应用方面的不足,其通过使用指令(directives)结构来扩展HTML词汇,使开发者可以使用HTML来 ...

  4. itchat库初探--微信好友全头像的拼接

        代码: import itchat import math import PIL.Image as Image import os itchat.auto_login() friends = ...

  5. 如何解决testng执行用例失败自动重跑问题

    注: 以下内容引自 http://blog.csdn.net/MenofGod/article/details/72846649 看过几个相关问题的帖子,内容类似,不过这篇解决问题的步骤和代码比较清晰 ...

  6. IZT复杂电磁环境记录回放和模拟系统

    结合实验室复杂电磁环境特性与模拟研究需求,实现对复杂多变的电磁环境录制.分析.重构和模拟,记录回放系统应具备如下几项能力: 1.电磁环境信号记录能力:能够实现对9KHz-18GHz频带范围内射频信号的 ...

  7. CentOS 7下单机部署RabbltMQ环境的操作记录

    一. RabbitMQ简单介绍 在日常工作环境中,你是否遇到过两个(多个)系统间需要通过定时任务来同步某些数据?你是否在为异构系统的不同进程间相互调用.通讯的问题而苦恼.挣扎?如果是,那么恭喜你,消息 ...

  8. ffmpeg 获得视频的时间长度, 仅仅学习一下

    public static void main(String[] args) { String result = processFLV("E:\\test\\京视传媒\\体育类\\xiao. ...

  9. centos7中输入ifconfig出现ens33,没有eth0

    vmware安装的centos7中没有出现eth0网卡,也没有ip,不能上网,输入ifconfig后如下图 解决办法 1.编辑网卡的配置文件 vi /etc/sysconfig/network-scr ...

  10. Java基础-递归调用

    意义: 递归算法是一种直接或间接地调用自身的算法.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 所以在工作中我们经常用递归 来进行一些算法操作 比如 ...