编程踩坑记录

classpathresource的区别

classpath

classpath是指类路径目录,在javaWeb项目中,构建打包完成后生成的war包中,所有编译生成的class文件,项目的xml配置文件,.properties/.yml属性文件,甚至是.db数据库文件都会放在此目录下。附一张打好的war包的截图:

1.png

class目录下放着的online文件夹正是我们的java类文件夹。static之类的其他的文件是resource目录下的文件。

在javaWeb中,打包时默认会将resource下的文件放到和java包同级的一个叫classes的文件夹中,这个文件夹就是classpath。

当然,还见过一种情况就是在编写测试类时会有这样的目录:

2.png

在test目录中往往也有一个resources文件夹(当然,我截图这里没有),如果有一些在测试里专门用的配置,可以放在这里,在运行测试类时编译打包会将test/resources目录下的配置文件一起放到classes目录下,使之和main/resources/下的配置文件一样生效。

resource

在配置SQLite数据库时,.db文件是放置在resource目录下,按道理classpath是可以实现的,我也查看过,编译时数据库文件是直接转移到target/web-inf/classes目录下的,但是不知道为什么使用classpath是不行的,后来我在这里找到的解决方案:

3.png

附上地址:https://bitbucket.org/xerial/sqlite-jdbc/wiki/Usage

后来我又搜了搜,觉得可能是SQLite的文件加载器的问题,然后就开始用断点单步走,我的探索历程如下:

探索日志:

  1. 从设置DateSource属性的对象开始,看哪里使用了我设置的URL
4.png
  1. 找到了org.sqlite.javax包下的SQLiteConnectionPoolDataSource
5.png
  1. 又转回了SQLiteDataSource下的getConnection方法
6.png
  1. 转到了org.sqlite包下的JDBC类的createConnection()方法
7.png
  1. 转到了org.sqlite包下的SQLiteConnection构造函数,这里直接调用了JDBC4Connection的构造函数,然后再次调用上一级的JDBC3Connection的构造函数然后再次调用父类org.sqlite.core.CoreConnection的构造函数
8.png
  1. 在调用this.open()时报错了,然后点进去:soga!

     private void open(int openModeFlags, int busyTimeout) throws SQLException {
            if (!":memory:".equals(this.fileName) && !this.fileName.startsWith("file:") && !this.fileName.contains("mode=memory")) {
                if (this.fileName.startsWith(":resource:")) {
                    String resourceName = this.fileName.substring(":resource:".length());
                    ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
                    URL resourceAddr = contextCL.getResource(resourceName);
                    if (resourceAddr == null) {
                        try {
                            resourceAddr = new URL(resourceName);
                        } catch (MalformedURLException var9) {
                            throw new SQLException(String.format("resource %s not found: %s", resourceName, var9));
                        }
                    }
    
                    try {
                        this.fileName = this.extractResource(resourceAddr).getAbsolutePath();
                    } catch (IOException var8) {
                        throw new SQLException(String.format("failed to load %s: %s", resourceName, var8));
                    }
                } else {
                    File file = (new File(this.fileName)).getAbsoluteFile();
                    File parent = file.getParentFile();
                    if (parent != null && !parent.exists()) {
                        for(File up = parent; up != null && !up.exists(); up = up.getParentFile()) {
                            parent = up;
                        }
    
                        throw new SQLException("path to '" + this.fileName + "': '" + parent + "' does not exist");
                    }
    
                    try {
                        if (!file.exists() && file.createNewFile()) {
                            file.delete();
                        }
                    } catch (Exception var10) {
                        throw new SQLException("opening db: '" + this.fileName + "': " + var10.getMessage());
                    }
    
                    this.fileName = file.getAbsolutePath();
                }
            }
    
            try {
                NativeDB.load();
                this.db = new NativeDB();
            } catch (Exception var7) {
                SQLException err = new SQLException("Error opening connection");
                err.initCause(var7);
                throw err;
            }
    
            this.db.open((SQLiteConnection)this, this.fileName, openModeFlags);
            this.setBusyTimeout(busyTimeout);
        }
    

    这里加载数据库文件的函数用的并不是classpath的界定符,而是resource

list.indexof()方法要注意的

出问题的代码:

public static Boolean addToFile(MappingVO mappingVO) throws IOException {
        mappingVO.setIfActive(true);
        if (mappingVOs.indexOf(mappingVO) != -1) {
            return false;
        }
        mappingVOs.add(mappingVO);
        writeToFile();
        return false;
    }

明明我的两个MappingVO是一样的,但是indexOf()返回的仍然是-1,原因是如果不是基本类型,indexOf()会调用对象的equals()方法进行比较,如果没有重写equals(),那么会通过比较对象的存储地址比较是否是一个附上ArrayListindexOf()方法:

   /**
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index i such that
     * (o==null ? get(i)==null : o.equals(get(i))),
     * or -1 if there is no such index.
     */
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

boolean与数据库类型的对应

boolean和数据库int【或者其他的类型对应】,对应的规则是true->1,false->0,脑袋抽了,直接和"true","false"字符串对应了。

你可能感兴趣的:(编程踩坑记录)