Java가 자원 파일을 로드할 때의 경로 문제 해결 방법

3157 단어 java경로 문제
리소스 파일을 로드하는 데 일반적으로 사용되는 두 가지는 다음과 같습니다.
1. ClassLoader로 말하자면 ClassLoader의 분류를 빼놓을 수 없다. 자바에 내장된 ClassLoader는 주로 세 가지가 있다.
첫 번째는 루트 클래스 캐리어 (bootstrap classloader) 입니다. C++로 작성하고 자바 같은 관건적인 자바 클래스를 작성합니다.lang.Object와 다른 실행 시 코드를 메모리에 불러옵니다.불러오는 패키지: BootStrp----->JRE/lib/rt.jar
두 번째는 확장 클래스 로더(ExtClassLoader)입니다. 자바 클래스가 작성하여 JRE의 일부 클래스를 메모리에 불러옵니다.불러오는 패키지: ExtClassLoader----------->JRE/lib/ext/*.jar
세 번째는 응용 클래스 로더(AppClassLoader) 또는 시스템 클래스 로더라고 하는데 CLASSPATH의 클래스를 메모리에 불러오는 것을 책임진다.ClassLoader를 통해 가능합니다.getSystemClassLoader () 를 사용하여 클래스 로더 가져오기;
다시 말하면 클래스 캐리어의 계승은 클래스 캐리어는 수직 계승의 부자 관계가 아니라 조합 관계이다. 실례화된 클래스 캐리어를 통해 클래스 캐리어의 실례를 구조 매개 변수로 클래스 캐리어에 전달할 수 있다.
클래스 캐리어에 대한 상세한 자료는 스스로 검색할 수 있습니다. 
응용 프로그램 캐리어를 가져오면 자원 파일을 가져오고loader를 호출합니다.getResource(path)는 해당 경로 아래의 자원 파일을 불러올 수 있습니다.'/'로 시작할 수 없습니다. 가방 안의 자원에 대해서는 가방을 일반적인 폴더로 하고'/'로 가방을 구분할 수 있습니다.
예: URL url2 = ClassLoader.getSystemClassLoader().getResource("demo/names.ser");데모 패키지에 있는names를 가져옵니다.ser 정렬화 파일.
둘째, 불러오는 현재 클래스의 get Resource 방법으로 불러옵니다. 사실 이 방법도 이 클래스를 불러오는 클래스 불러오는 장치로 자원 파일을 얻을 수 있습니다. 단지 가져온 파라미터가 다를 뿐입니다.
(1)class가 있는 가방 안의 파일을 가져오려면 상대적인 경로로 가방 안의 자원에 직접 접근할 수 있다.예: Demo1.class.getResource("names.ser");Demo1의 class 파일이 있는 패키지의 리소스를 가져옵니다.
(2) 패키지 이외의 리소스 파일을 가져오려면 URL URL = Demo1과 같이'/'으로 시작해야 합니다.class.getResource("/demo/names.ser");데모 패키지에 있는names를 가져옵니다.ser 파일
사실 두 번째 방식은 첫 번째 방식의 봉인입니다. 모두 ClassLoader로 불러오는 자원 파일입니다.왜 그랬을까?Class 클래스의 원본을 보면 알 수 있습니다

public java.net.URL getResource(String name) {
         name = resolveName(name);
         ClassLoader cl = getClassLoader0();
         if (cl==null) {
             // A system class.
             return ClassLoader.getSystemResource(name);
         }
         return cl.getResource(name);
     }

private String resolveName(String name) {
         if (name == null) {
             return name;
         }
         if (!name.startsWith("/")) {
             Class c = this;
             while (c.isArray()) {
                 c = c.getComponentType();
             }
             String baseName = c.getName();
             int index = baseName.lastIndexOf('.');
             if (index != -1) {
                 name = baseName.substring(0, index).replace('.', '/')
                     +"/"+name;
             }
         } else {
             name = name.substring(1);
         }
         return name;
     }
get Resource는 전송된name 값(즉 상대 경로 또는 절대 경로의 형식)에 따라 ResolveName 처리를 거친 후에 ClassLoader c1을 호출하여 불러왔습니다. ClassLoader의 불러오는 경로의 형식은'/'로 시작하지 않는 상대 경로입니다. 이것은 resolveName이 경로를 한 번 바꾼 것이 틀림없습니다. 다시resolveName 방법을 보십시오. 우선'/'로 시작하는지,'/'로 시작하면,상대적인 경로입니다. 그렇지 않으면 절대 경로입니다. 이 코드 블록은 첫 번째 문자를 제거합니다. 제거한 후에 ClassLoader의 불러오는 경로에 부합됩니다. 만약에 블록에서 현재 클래스의 패키지 경로를 캡처한 다음.'/'으로 바뀌었고 상대 경로를 추가했습니다. 또한 ClassLoader에 맞는 로드 경로가 형성되었습니다.

좋은 웹페이지 즐겨찾기