• jersey在 spring boot 添加 packages 扫描路径支持


    最近公司内部系统要做数据对接,故使用 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;
        }
  • 相关阅读:
    关于viewports 设备像素比 密度
    脚本检测 media query 分界点
    chrome Web开放 字体格式不能显示问题
    响应式图片
    ECMAScript 6 proxies
    大小不固定 文字图片居中
    prototype
    基于综合服务平台浅谈Sass应用
    Sass浅谈
    JQ怎么获取margin-left的值
  • 原文地址:https://www.cnblogs.com/suiyueqiannian/p/8946720.html
Copyright © 2020-2023  润新知