当前位置: 首页 > news >正文

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() {// 。。。 其他的 。。。}
}

完结!!!

相关文章:

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

环境 java17 springboot 3.x 如题&#xff0c;简单来说&#xff0c;jersey官方希望用户通过 register 的方式&#xff0c;将所有的资源类注册到jersey中&#xff0c;但是&#xff0c;一般开发中&#xff0c;可能定义了N个Resource类&#xff0c;一个一个的加入&#xff0c;太…...

基于springboot和vue的旅游资源网站的设计与实现

环境以及简介 基于vue, springboot旅游资源网站的设计与实现&#xff0c;Java项目&#xff0c;SpringBoot项目&#xff0c;含开发文档&#xff0c;源码&#xff0c;数据库以及ppt 环境配置&#xff1a; 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xf…...

Python编程异步爬虫——协程的基本原理

Python编程之异步爬虫 协程的基本原理 要实现异步机制的爬虫&#xff0c;自然和协程脱不了关系。 案例引入 先看一个案例网站&#xff0c;地址为https://www.httpbin.org/delay/5&#xff0c;访问这个链接需要先等5秒钟才能得到结果&#xff0c;这是因为服务器强制等待5秒时…...

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

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

Debezium日常分享系列之:Debezium2.5稳定版本之Monitoring

Debezium日常分享系列之&#xff1a;Debezium2.5稳定版本之Monitoring 一、Snapshot metrics二、Streaming metrics三、Schema history metrics Debezium系列之&#xff1a;安装jmx导出器监控debezium指标 除了 Zookeeper、Kafka 和 Kafka Connect 提供的对 JMX 指标的内置支持…...

GuLi商城-商品服务-API-三级分类-网关统一配置跨域

参考文档&#xff1a; https://tangzhi.blog.csdn.net/article/details/126754515 https://github.com/OYCodeSite/gulimall-learning/blob/master/docs/%E8%B0%B7%E7%B2%92%E5%95%86%E5%9F%8E%E2%80%94%E5%88%86%E5%B8%83%E5%BC%8F%E5%9F%BA%E7%A1%80.md 谷粒商城-day04-完…...

【ai技术】(4):在树莓派上,使用qwen0.5b大模型+chatgptweb,搭建本地大模型聊天环境,速度飞快,非常不错!

1&#xff0c;视频地址 https://www.bilibili.com/video/BV1VK421i7CZ/ 【ai技术】&#xff08;4&#xff09;&#xff1a;在树莓派4上&#xff0c;使用ollama部署qwen0.5b大模型chatgptweb前端界面&#xff0c;搭建本地大模型聊天工具&#xff0c;速度飞快 2&#xff0c;下载…...

深入理解PHP+Redis实现分布式锁的相关问题

概念 PHP使用分布式锁&#xff0c;受语言本身的限制&#xff0c;有一些局限性。 通俗理解单机锁问题&#xff1a;自家的锁锁自家的门&#xff0c;只能保证自家的事&#xff0c;管不了别人家不锁门引发的问题&#xff0c;于是有了分布式锁。分布式锁概念&#xff1a;是针对多个…...

perl:获取同花顺数据--业绩预告

perldoc LWP::UserAgent 如果没有安装&#xff0c;则安装模块&#xff0c;运行 cpanm LWP::UserAgent 。 编写 get_yjyg_10jqka.pl 如下 #!/usr/bin/perl # perl 获取同花顺数据--业绩预告 use LWP::UserAgent; use Encode qw(decode encode); use POSIX; use Data::Dump…...

如何对比引用传参和值传参两者的效率

以值作为参数或者返回值类型&#xff0c;在传参和返回期间&#xff0c;函数不会直接传递实参或者将变量本身直接返回&#xff0c;而是传递实参或者返回变量的一份临时的拷贝&#xff0c;因此用值作为参数或者返回值类型&#xff0c;效率是非常低下的&#xff0c;尤其是当参数或…...

探索软件工程:构建可靠、高效的数字世界

软件工程是一门涵盖了设计、开发、测试、维护和管理软件的学科&#xff0c;它在如今数字化时代的发展中扮演着至关重要的角色。随着科技的不断进步和社会的不断变迁&#xff0c;软件工程的意义也愈发凸显。本文将探索软件工程的重要性、原则和实践&#xff0c;以及其对当今社会…...

超越肉眼:深入计算机视觉的奇妙之旅

揭秘计算机视觉的奥秘&#xff1a;从基础到前沿的探索之旅 引言&#xff1a;一、计算机视觉的基础1. 图像处理基础2. 特征提取与描述3. 基本模式识别 二、机器学习在计算机视觉中的应用1. 深度学习革命2. 迁移学习与多任务学习3. 强化学习与主动学习4. 无监督学习和自监督学习 …...

mac 安装 nvm 【真解决问题】

前提 没有node环境已有git 下载 我用的gitee极速下载 git clone https://gitee.com/mirrors/nvm.git ~/.nvm && cd ~/.nvm && git checkout git describe --abbrev0 --tags配置 1. 配置变量 在用户的目录下新增文件 .zshrc export NVM_DIR"$HOME/…...

【Godot 3.5控件】用TextureProgress制作血条

说明 本文写自2022年11月13日-14日&#xff0c;内容基于Godot3.5。后续可能会进行向4.2版本的转化。 概述 之前基于ProgressBar创建过血条组件。它主要是基于修改StyleBoxFlat&#xff0c;好处是它几乎可以算是矢量的&#xff0c;体积小&#xff0c;所有东西都是样式信息&am…...

第十届蓝桥杯大赛个人赛省赛(软件类)真题- CC++ 研究生组

第十届蓝桥杯大赛个人赛省赛&#xff08;软件类&#xff09;真题- C&C 研究生组-立方和 第十届蓝桥杯大赛个人赛省赛&#xff08;软件类&#xff09;真题- C&C 研究生组-字串数字 第十届蓝桥杯大赛个人赛省赛&#xff08;软件类&#xff09;真题- C&C 研究生组-质数…...

Linux:Gitlab:16.9.2 创建用户及项目仓库基础操作(2)

我在上一章介绍了基本的搭建以及邮箱配置 Linux&#xff1a;Gitlab:16.9.2 (rpm包) 部署及基础操作&#xff08;1&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136821311?spm1001.2014.3001.5501 本章介绍一下用户的创建&#xff0c;组内设置用户&…...

【数据挖掘】实验5:数据预处理(1)

实验5&#xff1a;数据预处理&#xff08;1&#xff09; 一&#xff1a;实验目的与要求 1&#xff1a;熟悉和掌握数据预处理&#xff0c;学习数据清洗、数据集成、数据变换、数据规约、R语言中主要数据预处理函数。 二&#xff1a;实验内容 【缺失值分析】 第一步&#xff1…...

383.赎金信

给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 思路&#xff1a;将magazine 中字…...

Python 3 教程(8)

heisenbug601 601***902@qq.com 参考地址 311 tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出同学的名字: 代码如下: >>> classmates = (Michael, Bob, Tracy) 现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法…...

Mysql数据库深入理解

目录 一、什么是数据库 二、Mysql基本架构图 1.Mysql客户端/服务器架构 2.客户端与服务器的连接过程 3.服务器处理客户端请求 4.一条查询SQL执行顺序 4.1连接器 4.2查询缓存 4.3解析器 4.4执行器 4.4.1预处理阶段 4.4.2优化阶段 4.4.3执行阶段 5.一条记录如何存…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...