欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot集成jersey打包jar找不到class的處理方法

 更新時間:2024年03月21日 09:44:36   作者:mose-x  
這篇文章主要介紹了SpringBoot集成jersey打包jar找不到class的處理方法,文中通過代碼示例介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下

環(huán)境 java17 + springboot 3.x

如題,簡單來說,jersey官方希望用戶通過 register 的方式,將所有的資源類注冊到jersey中,但是,一般開發(fā)中,可能定義了N個Resource類,一個一個的加入,太麻煩,也可能遺漏,解決方案就是,寫個方法,掃描到resource包下的所有資源類,然后 register 到jersey中

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

以下兩種方法

使用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() {
        // 注冊包掃描 這個方法在開發(fā)使用沒問題,但是打包jar后,找不到 class 文件
//        packages("com.xxx.xxx.api");

        // 定義掃描包含接口資源包
        registerClasses(ClassUtil.findAllClasses("com.xxx.xxx.api"));
    }
}

使用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);
        }
        @Override
        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
            AnnotationMetadata metadata = beanDefinition.getMetadata();
            // 注意這里的值,最好debug一下,我使用的時候,只有第一個metadata.isIndependent()是true
            return (metadata.isIndependent() && metadata.isAbstract() && !beanDefinition.getMetadata().isAnnotation());
        }
    }
}

2.2 引用

@Configuration
public class JerseyConfig extends ResourceConfig implements ApplicationContextAware {

    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @PostConstruct
    public void init() {
        registerClasses(JerseyServiceAutoScanner.getPublishJerseyServiceClasses(applicationContext, "com.xxx.xxx.api"));
    }
    public JerseyConfig() {
    // 。。。 其他的 。。。
    }
}

完結?。。?/p>

以上就是SpringBoot集成jersey打包jar找不到class的處理方法的詳細內容,更多關于SpringBoot jersey找不到class的資料請關注腳本之家其它相關文章!

相關文章

  • 淺談Spring中幾個PostProcessor的區(qū)別與聯(lián)系

    淺談Spring中幾個PostProcessor的區(qū)別與聯(lián)系

    這篇文章主要介紹了淺談Spring中幾個PostProcessor的區(qū)別與聯(lián)系,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • spring boot 日志配置詳解

    spring boot 日志配置詳解

    本篇文章主要介紹了spring boot 日志配置 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • JAVA設計模式之建造者模式原理與用法詳解

    JAVA設計模式之建造者模式原理與用法詳解

    這篇文章主要介紹了JAVA設計模式之建造者模式,簡單說明了建造者模式的原理、組成,并結合實例形式分析了java建造者模式的定義與用法,需要的朋友可以參考下
    2017-08-08
  • Java基于MySQL實現(xiàn)學生管理系統(tǒng)

    Java基于MySQL實現(xiàn)學生管理系統(tǒng)

    這篇文章主要為大家詳細介紹了Java基于MySQL實現(xiàn)學生管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java.io.IOException:你的主機中的軟件中止了一個已建立的連接踩坑實戰(zhàn)

    java.io.IOException:你的主機中的軟件中止了一個已建立的連接踩坑實戰(zhàn)

    最近在工作中遇到了個問題,分享給同樣遇到問題的同學,這篇文章主要給大家介紹了關于java.io.IOException:你的主機中的軟件中止了一個已建立的連接的踩坑實戰(zhàn)記錄,需要的朋友可以參考下
    2023-03-03
  • springboot整合webservice使用簡單案例總結

    springboot整合webservice使用簡單案例總結

    WebService是一個SOA(面向服務的編程)的架構,它是不依賴于語言,平臺等,可以實現(xiàn)不同的語言間的相互調用,下面這篇文章主要給大家介紹了關于springboot整合webservice使用的相關資料,需要的朋友可以參考下
    2024-07-07
  • Java深入講解AWT實現(xiàn)事件處理流程

    Java深入講解AWT實現(xiàn)事件處理流程

    AWT的事件處理是一種委派式事件處理方式:普通組件(事件源)將整個事件處理委托給特定的對象(事件監(jiān)聽器);當該事件源發(fā)生指定的事件時,就通知所委托的事件監(jiān)聽器,由事件監(jiān)聽器來處理這個事件
    2022-04-04
  • 小程序與后端Java接口交互實現(xiàn)HelloWorld入門

    小程序與后端Java接口交互實現(xiàn)HelloWorld入門

    本文主要介紹了小程序與后端Java接口交互實現(xiàn)HelloWorld入門 ,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • Mybatis如何傳入多個參數的實現(xiàn)代碼

    Mybatis如何傳入多個參數的實現(xiàn)代碼

    這篇文章主要介紹了Mybatis如何傳入多個參數的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • SpringBoot整合Jasypt實現(xiàn)配置加密的步驟詳解

    SpringBoot整合Jasypt實現(xiàn)配置加密的步驟詳解

    Jasypt是一個Java庫,提供了一種簡單的加密解密方式,可用于保護敏感數據,例如密碼、API密鑰和數據庫連接信息等,本文給大家介紹了SpringBoot整合Jasypt實現(xiàn)配置加密的詳細步驟,感興趣的同學可以參考一下
    2023-11-11

最新評論