maven dao和service工程,spring 扫描jar中配置文件nullpointer的问题

今天试着用spring maven hibernate搭建了mvc项目时, dao,service分别作为两个子工程. service调用dao. 但是不太顺利.
dao直接运行mvn test是可以通过的.
当用service调用dao时候, 在service工程运行mvn test时, 报null指针异常. 查了下是因为dao作为jar程序聚合进了service, spring扫面实体类时, 就无法通过普通的方式加载文件了. 因为jar作为独立运行的文件格式. 得到文件目录为 xxxxxxxxxxxxxxxxxx.jar!com/xxx/xxxx/xxx.A.class
这种格式再用File对象是无法读取的.因此需要用到JarURLConnection来遍历jar文件.

String path = packagename.replace(".", "/");
            log.debug("以jar方式读取spring文件");
            log.debug("Begin scan entity package:" + path);
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            Enumeration<URL> resources = classLoader.getResources(path);
            URL url = null;
            while(resources.hasMoreElements()){
                URL resource = resources.nextElement();
                String protocol = resource.getProtocol();
                if("jar".equals(protocol)){
                    url = resource;
                    break;
                }
            }

            JarURLConnection juc = (JarURLConnection) url.openConnection();
            JarFile jf = juc.getJarFile();
            Enumeration<JarEntry> entrys = jf.entries();
            while(entrys.hasMoreElements()){
                JarEntry clazz = entrys.nextElement();
                String className = clazz.getName();
                if(className.endsWith("/")){
                    continue;
                }
                log.debug("className="+className);
                String shortName = className.substring(StringUtils.lastIndexOf(className, "/")+1,className.length()-6);
                log.debug("className="+className);
                log.debug("shortName="+shortName);
                if(!className.equalsIgnoreCase("com/meijuu/dao/entity/"+shortName+".class")){
//              if(className.startsWith("com/meijuu/dao/entity/") && className.endsWith(".class")){
//              if(!StringUtils.startsWith(className, "com/meiju/dao/entity/")||!StringUtils.endsWith(className, ".class")){
                    continue;
                }

                Class<?> cla = Class.forName(packagename + "." + className);
                Entity en = (Entity)cla.getAnnotation(Entity.class);
                if(en == null)continue;
                Table tab = (Table)cla.getAnnotation(Table.class);
                if(tab.name() == null){
                    throw new FrameException("Entity " + className + " not set table name!");
                }
                if(tables.contains(tab.name())){
                    throw new FrameException("Exists same table for entity:" + cla.getName());
                }
                tables.add(tab.name());

                Field[] fields = cla.getDeclaredFields();
                for(Field field : fields){
                    CreateIndex gi = (CreateIndex)field.getAnnotation(CreateIndex.class);
                    if(gi != null){
                        SqlKey ck = generatorIndexSql(gi, cla, field);
                        if(!cache.contains(ck)){
                            updates.add(ck);
                        }
                    }
                    CreateForeignKey fk = (CreateForeignKey)field.getAnnotation(CreateForeignKey.class);
                    if(fk != null){
                        SqlKey ck = generateForeignKey(fk, cla, field);
                        if(!cache.contains(ck)){
                            updates.add(ck);
                        }
                    }
                    CodeGroup cg = (CodeGroup)field.getAnnotation(CodeGroup.class);
                    if(cg != null){
                        for(CodeItem item : cg.items()){
                            CodeHelper.add(cg.value(), item.value(), item.text());
                        }
                    }

                }
            }

==================引发新的问题=============================
这样修改后, 理论上service是已经可以读取jar形式的dao工程了. 但是在dao工程运行mvn deploy时, 反而失败了. 因为在build时,会先test, 这个时候由于dao并不是jar, 而是以普通目录形式组织文件, 是要通过File的方式读取文件的. 为了是dao能独立运行, 又能作为子工程给service, 因此把上面代码加了一层try…catch

try{ //优先以jar方式扫面

/******上方代码*****/

}catch(Exception e){ //非jar方式扫描,用于自身子项目扫面

String path = "/" + packagename.replace(".", "/");
            System.out.println("以本工程方式扫描spring文件");
            System.out.println("Begin scan entity package:" + path);
            File dir = new File(this.getClass().getResource(path).getFile().replace("%20", " "));

            for(File f : dir.listFiles()){
                if(!f.getName().endsWith(".class"))continue;
                String className = f.getName();
                className = className.substring(0, className.lastIndexOf("."));
                Class<?> cla = Class.forName(packagename + "." + className);
                Entity en = (Entity)cla.getAnnotation(Entity.class);
                if(en == null)continue;
                Table tab = (Table)cla.getAnnotation(Table.class);
                if(tab.name() == null){
                    throw new FrameException("Entity " + className + " not set table name!");
                }
                if(tables.contains(tab.name())){
                    throw new FrameException("Exists same table for entity:" + cla.getName());
                }
                tables.add(tab.name());

                Field[] fields = cla.getDeclaredFields();
                for(Field field : fields){
                    CreateIndex gi = (CreateIndex)field.getAnnotation(CreateIndex.class);
                    if(gi != null){
                        SqlKey ck = generatorIndexSql(gi, cla, field);
                        if(!cache.contains(ck)){
                            updates.add(ck);
                        }
                    }
                    CreateForeignKey fk = (CreateForeignKey)field.getAnnotation(CreateForeignKey.class);
                    if(fk != null){
                        SqlKey ck = generateForeignKey(fk, cla, field);
                        if(!cache.contains(ck)){
                            updates.add(ck);
                        }
                    }
                    CodeGroup cg = (CodeGroup)field.getAnnotation(CodeGroup.class);
                    if(cg != null){
                        for(CodeItem item : cg.items()){
                            CodeHelper.add(cg.value(), item.value(), item.text());
                        }
                    }

                }
            }

}

分别在dao工程上测试mvn deploy, 再在service工程运行mvn test也都测试通过.

================关键点总结========================
1. 这里并不是关心spring如何扫描,所以省略了其他代码. 只列出如何读取jar文件的代码
2. File读取文件的方式不适用于读取jar文件, 这里用的是JarUrlConnection, 应该也可以用JarFile来实现.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值