Springboot集成jersey打包jar找不到class处理

环境 java17 + springboot 3.x

如题,简单来说,jersey官方希望用户通过 register 的方式,将所有的资源类注册到jersey中,但是,一般开发中,可能定义了N个Resource类,一个一个的加入,太麻烦,也可能遗漏,解决方案就是,写个方法,扫描到resource包下的所有资源类,然后 register 到jersey中

特别注意,是 registerClasses 方法,不是 register 方法

以下两种方法

  1. 使用java自带的扫描
    1.1 核心代码
import lombok.extern.slf4j.Slf4j;
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;@Slf4j
public class ClassUtil {/*** 由于spring boot 打包为jar包,jersey packages 无法扫描jar对应的文件夹的文件,故自定义包扫描** @return class[]*/public static Set<Class<?>> findAllClasses(String... scanPackages) {Set<Class<?>> classes = new HashSet<>();for (String scanPackage : scanPackages) {ClassLoader loader = ClassUtil.class.getClassLoader();Resource[] resources = new Resource[0];try {resources = scan(loader, scanPackage);} catch (IOException e) {log.error("加载class异常", e);}classes.addAll(convert(loader, resources));}return classes;}/*** 扫描 jar 包** @param loader      ClassLoader* @param packageName packageName*/private static 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   ClassLoader* @param resource resource*/private static 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    ClassLoader* @param resources Resource*/private static 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;}}
1.2 使用
@Configuration
public class JerseyConfig extends ResourceConfig {public JerseyConfig() {// 注册包扫描 这个方法在开发使用没问题,但是打包jar后,找不到 class 文件
//        packages("com.xxx.xxx.api");// 定义扫描包含接口资源包registerClasses(ClassUtil.findAllClasses("com.xxx.xxx.api"));}
}
  1. 使用JerseyScan
    2.1 核心代码
    注意中间的 scanner.addIncludeFilter(new AnnotationTypeFilter(Path.class)); 这一行代码!!!
public class JerseyServiceAutoScanner {private JerseyServiceAutoScanner() {}public static Class[] getPublishJerseyServiceClasses(ApplicationContext context, String... scanPackages) {// 传入applicationContext对象,在整个spring容器中捞我们需要的controller// 传入的第二个参数是可变参数,字符串,用于传入需要扫描的包路径List<Class> jerseyServiceClasses = new ArrayList<>();if (scanPackages == null || scanPackages.length == 0) {return jerseyServiceClasses.toArray(new Class[jerseyServiceClasses.size()]);}ClassPathScanningCandidateComponentProvider scanner = new JerseyScanningComponentProvider(false);// 我只需要扫描使用了@Path注解的controller,如果还有其他的组合条件,可以在这里增加scanner.addIncludeFilter(new AnnotationTypeFilter(Path.class));for (var scanPackage : scanPackages) {jerseyServiceClasses.addAll(scanner.findCandidateComponents(scanPackage).stream().map(beanDefinition -> ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), applicationContext.getClassLoader())).collect(Collectors.toSet()));}// 返回符合条件的spring容器中的全部的类对象return jerseyServiceClasses.toArray(new Class[jerseyServiceClasses.size()]);}private static class JerseyScanningComponentProvider extends ClassPathScanningCandidateComponentProvider {public JerseyScanningComponentProvider(boolean useDefaultFilters) {super(useDefaultFilters);}@Overrideprotected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {AnnotationMetadata metadata = beanDefinition.getMetadata();// 注意这里的值,最好debug一下,我使用的时候,只有第一个metadata.isIndependent()是truereturn (metadata.isIndependent() && metadata.isAbstract() && !beanDefinition.getMetadata().isAnnotation());}}
}
2.2 引用
@Configuration
public class JerseyConfig extends ResourceConfig implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}@PostConstructpublic void init() {registerClasses(JerseyServiceAutoScanner.getPublishJerseyServiceClasses(applicationContext, "com.xxx.xxx.api"));}public JerseyConfig() {// 。。。 其他的 。。。}
}

完结!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/766118.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python--for循环

for循环&#xff1a; python中的for循环是用来迭代容器中的每一个元素的&#xff0c;而不是c,java中理解那个循环&#xff1b; for 零时变量 in 容器&#xff1a; print&#xff08;零时变量&#xff09; #每一个迭代出的元素 range 全局函数&#xff1a; …

嵌入式面试积累

C语言 1、volatile关键字的作用 volatile意为”易变的“&#xff0c;是一种类型修饰符。提示编译器这个编译器定义的变量可以随时改变&#xff0c;编译器将不会轻易优化该变量&#xff0c;它主要用于多线程编程中&#xff0c;用来保证共享变量的内存可见性。 volatile修饰的…

P6技巧:修改P6 Professional标题/标签名称/字体

前言 P6 Professional作为P6的客户端工具其本身具有一定的改造属性&#xff0c;通过修改其安装程序文件&#xff0c;可以实现对部分功能菜单/标签文字名称的修改/重定义 如以下标识的信息&#xff0c;都可对齐改名 方法 以下介绍的方法只可对本机有效&#xff0c;这里已修改…

开学考核复现

不要尝试爆破哟!(misc) 下载图片&#xff0c;解析图片 拿到密码&#xff0c;解压压缩包&#xff0c;生成图片 扫描二维码 留个后门(misc) D盾扫描 打开文件寻找 师姐的旅游照片(misc) 随波逐流&#xff0c;然后base64解码 修改后缀为zip&#xff0c;解压 修改高度 Fuck! (C…

服务器硬防和软防是什么?

关于服务器防御相关的知识很多新手都不是很了解&#xff0c;服务器防御分为服务器硬防和软防&#xff0c;接下来小编就带领大家一起来了解一下什么是服务器硬防和软防。 一、服务器硬防 服务器硬防主要指的是硬件防火墙&#xff0c;能够在硬件设备中嵌入防火墙的防御程序&…

Matlab之已知2点绘制长度可定义的射线

目的&#xff1a;在笛卡尔坐标系中&#xff0c;已知两个点的位置&#xff0c;绘制过这两点的射线。同时射线的长度可以自定义。 一、函数的参数说明 输入参数&#xff1a; PointA&#xff1a;射线的起点&#xff1b; PointB&#xff1a;射线过的零一点&#xff1b; Length&…

Redis入门到实战-第四弹Strings 篇

Redis实战热身Strings 篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#xff09;&#xff0c;用作数据库、缓存、消息代理…

【Android】【Bluetooth Stack】蓝牙音乐协议分析之A2DP和AVRCP连接流程(超详细)

1. 精讲蓝牙协议栈(Bluetooth Stack):SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论 2. 欢迎大家关注和订阅,【蓝牙协议栈】和【Android Bluetooth Stack】专栏会持续更新中.....敬请期待! 1. 协议架构 上面描述的就是整体的协议架构,我们针…

基于springboot+vue的物资仓储物流管理系统(源码+论文)

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

Linux线程补充1

十、多线程中线程间的"独立" ​ 1.线程在代码段通过执行不同的函数&#xff0c;实现代码段的独立&#xff1b; ​ 2.新线程通过在共享区划分不同的管理属性和不同的栈空间&#xff0c;实现栈的独立&#xff0c;而主线程使用的是栈空间&#xff1b; ​ 3.线程通过获…

2 Spring之IOC详解

文章目录 4&#xff0c;IOC相关内容4.1 bean基础配置4.1.1 bean基础配置(id与class)4.1.2 bean的name属性步骤1&#xff1a;配置别名步骤2:根据名称容器中获取bean对象步骤3:运行程序 4.1.3 bean作用范围scope配置4.1.3.1 验证IOC容器中对象是否为单例验证思路具体实现 4.1.3.2…

计算平均分 javascript

养成好习惯&#xff1a;先写注释再写代码 基础版&#xff1a;直接写逻辑&#xff08;平均分总和/个数&#xff09; // 求平均分 var scores [60, 55, 80, 33, 75, 100]; // 求和,相除 var sum 0; var avg;for (var i 0; i < 6; i) {sum scores[i]; }avg sum / 6; con…

美团一路稳扎稳打,稳健型选手是如何炼成的?

2023年至今&#xff0c;宏观环境出现多元变化。这种变化带来了一种独特的机遇——当下&#xff0c;可能是观察一家公司或一种行业抗周期能力的最好时期。因为在面对不可预知的未来时&#xff0c;它们的抉择&#xff0c;一方面会反映业务基本盘的可靠性&#xff0c;另一方面则能…

节后必看!复工复产九项安全提示!

本文转载自“中华人民共和国应急管理部”公众号&#xff0c;原文链接&#xff1a;节后必看&#xff01;复工复产九项安全提示&#xff01; 春节假期结束&#xff0c;不少工厂企业开始复工复产&#xff0c;安全防范不可疏忽大意&#xff0c;复工复产时期主要危险因素 01假期综合…

【保姆级讲解如何在Ubuntu中设置中文输入法】

在Ubuntu中设置中文输入法 Ubuntu 中设置中文输入法的过程如下&#xff0c;这里以 Ubuntu 20.04 LTS 为例&#xff0c;步骤在其他版本中可能略有差异&#xff0c;请根据实际情况进行调整&#xff1a; 安装中文输入法框架&#xff1a; Ubuntu 默认使用 IBus 输入法框架&#xf…

C++ 月落乌啼算钱(斐波那契数列)

文章目录 一、题目描述月落乌啼算钱&#xff08;斐波那契数列&#xff09;题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 二、参考代码 一、题目描述 月落乌啼算钱&#xff08;斐波那契数列&#xff09; 题目背景 &#xff08;本道题目木有隐藏歌曲……

谈谈对前端性能监控的理解和实践

一、谈谈对前端性能监控的理解和实践 前端性能监控是确保网页或应用高效、稳定运行的关键环节&#xff0c;它涉及对前端页面加载速度、资源消耗、错误率等指标的实时监控和预警。通过前端性能监控&#xff0c;开发者和运维团队能够及时发现并解决性能瓶颈&#xff0c;从而提升…

基于SSM+Jsp+Mysql的记账管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

使用maxwell实时同步mysql数据到kafka

一、软件环境&#xff1a; 操作系统&#xff1a;CentOS release 6.5 (Final) java版本: jdk1.8 zookeeper版本: zookeeper-3.4.11 kafka 版本: kafka_2.11-1.1.0.tgz maxwell版本&#xff1a;maxwell-1.16.0.tar.gz 注意 &#xff1a; 关闭所有机器的防火墙&#xff0c;同时注意…

基于springboot+vue的旅游推荐系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…