자바 는 클래스 경로 에서 자원 을 정확하게 가 져 옵 니 다.
Class.getResource 와 ClassLoader.getResource 의 차이
이 두 가지 방식 은 모두 하나의 문자열 형식의 경로 표현 식,즉 자원 이름 을 받 아들 이 고 찾 은 자원 의 URL 을 되 돌려 줍 니 다.두 가지 방식 은 모두 자원 을 포 지 셔 닝 하 는 데 사용 할 수 있 는데 인터넷 에서 전해 지 는 글 에서 둘 다 흔히 볼 수 있다.실제로 Class 의 getResource 방법 도 ClassLoader 의 getResource 방법 을 호출 했 지만 둘 은 매우 큰 차이 가 있 기 때문에 이 두 가지 방법의 차 이 를 모 르 면 위험 을 초래 하기 쉽다.위험 은 항상 작성 할 때 오류 가 발생 하 는 것 보다 훨씬 무 섭 습 니 다.왜냐하면 특정한 상황 에서 정상 적 이 고 쉽게 발견 되 지 않 기 때 문 입 니 다.
둘 의 가장 큰 차 이 는 어디서부터 자원 을 찾 느 냐 하 는 것 이다.ClassLoader 는 현재 클래스 의 패키지 이름 경로 에 관심 이 없습니다.classpath 를 기반 으로 자원 을 찾 습 니 다.한편,Class.getResource 는 자원 이름 이 절대 경로("/"로 시작)라면 시작 하 는"/"를 제거 하고 ClassLoader 의 getResource 방법 으로 자원 을 찾 습 니 다.자원 이름 이 상대 경로 라면 현재 패키지 경로 아래 에서 자원 을 찾 습 니 다.
예 를 들 어 우리 에 게 test.app(가방 이름 은 test)이 있 고 test 가방 아래 에 같은 이름 의 js 파일 이 있 으 며 App.js 라 고 가정 합 니 다.이 js 파일 을 ClassLoader 로 가 져 오 려 면 이렇게 써 야 합 니 다:
App.class.getClassLoader().getResource("test/App.js");
Class 의 getResource 방법 을 사용 하면 두 가지 방법 이 있 습 니 다.
App.class.getResource("App.js");
App.class.getResource("/test/App.js");
위의 예 를 보면 둘 사이 의 커 다란 차 이 를 알 수 있다.어떤 사람들 은 인터넷 에서 비슷 한 코드 를 복사 하여 정확하게 실행 되 지 않 는 것 을 보고 자원 이름 앞 에'/'를 붙 이거 나 시작 하 는'/'를 없 애 려 고 시도 하기 시작 했다.시험 에 성공 하면 완 공 된 셈 이다.이것 은 결코 정도 가 아니다.Class 와 ClassLoader 의 getResource 방법 은 또 다른 차이 가 있 습 니 다.Class 의 getResource 방법 에 있어 서 상대 적 인 경로 가 들 어 오 면 패키지 이름과 경로 이름 의 전환 을 시도 합 니 다.Class.getResource 방법의 원본 코드 를 보면 자원 이름 에 resolveName 방법 을 먼저 호출 한 다음 에 ClassLoader 의 getResource 방법 을 호출 하여 자원 의 포 지 셔 닝 을 완성 하 는 것 을 볼 수 있 습 니 다.
테스트 코드
프 리 젠 테 이 션 으로 Class 와 ClassLoader 의 getResource 방법 을 보 여 주 는 다음 코드 를 썼 습 니 다.
/**
* Copyright (c) 2014 Chen Zhiqiang <[email protected]>. Released under the MIT license.
*/
package test;
import java.net.URL;
import java.util.Enumeration;
/**
* Tests for the use of {@link Class#getResource(String)} and
* {@link ClassLoader#getResource(String)}.
*
* @author Chen Zhiqiang <[email protected]>
*/
public class ClassResourceTest {
Class<ClassResourceTest> cls = ClassResourceTest.class;
ClassLoader ldr = cls.getClassLoader(); // Thread.currentThread().getContextClassLoader()
public static void println(Object s) {
System.out.println(s);
}
void showResource(String name) {
println("## Test resource for: “" + name + "” ##");
println(String.format("ClassLoader#getResource(\"%s\")=%s", name, ldr.getResource(name)));
println(String.format("Class#getResource(\"%s\")=%s", name, cls.getResource(name)));
}
public final void testForResource() throws Exception {
showResource("");
showResource("/");
showResource(cls.getSimpleName() + ".class");
String n = cls.getName().replace('.', '/') + ".class";
showResource(n);
showResource("/" + n);
showResource("java/lang/Object.class");
showResource("/java/lang/Object.class");
}
public static void main(String[] args) throws Exception {
println("java.class.path: " + System.getProperty("java.class.path"));
println("user.dir: " + System.getProperty("user.dir"));
println("");
ClassResourceTest t = new ClassResourceTest();
t.testForResource();
}
}
위 코드 를 컴 파일 하여 서로 다른 자원 경로 의 출력 결 과 를 보십시오.Jar 가방 으로 포장 한 후의 변화
현재 상기 코드 를 컴 파일 한 결 과 를 Jar 파일 로 포장 하고 test.jar 라 고 가정 한 다음 에 이 jar 패키지 에서 상기 코드 를 실행 한 다음 에 출력 결 과 를 보고 위의 출력 과 어떤 변화 가 있 는 지 비교 해 보 세 요.
java -classpath test.jar test.ClassResourceTest
주의해 야 할 몇 가지:getResource 방법 을 정확하게 사용 합 니 다.
자바 의 CLASSPATH 는 하나의 경로 목록 이기 때문에 여러 종류의 경로 에서 같은 자원 이름 이 나타 날 수 있 습 니 다.그것들 을 열거 하려 면 ClassLoader 의 getResources 방법 을 사용 할 수 있 습 니 다.
다음 코드 는 모든"META-INF/MANIFEST.MF"를 열거 할 수 있 으 며,클래스 경로 에 어떤 jar 파일 이 이 자원 을 포함 하고 있 는 지 관찰 할 수 있 습 니 다.
import java.net.URL;
import java.util.Enumeration;
public class Test {
public static void main(String[] args) throws Exception {
ClassLoader ldr = Test.class.getClassLoader();
System.out.println("## Test for getResources(‘META-INF/MANIFEST.MF') ##");
Enumeration<URL> urls = ldr.getResources("META-INF/MANIFEST.MF");
while(urls.hasMoreElements())
System.out.println(urls.nextElement());
}
}
실례다음 코드 는 코드 의 클래스 경로 시작 점 을 정확하게 가 져 오 는 방법 을 보 여 줍 니 다.
/**
* Copyright (c) 2014 Chen Zhiqiang <[email protected]>. Released under the MIT license.
*/
package test;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
*
* @author Chen Zhiqiang <[email protected]>
*/
public class AppDirTest {
Classcls = AppDirTest.class;
URL codeLocation = getCodeLocation();
/**
* Get the code location.
*
* Return the classpath where the code run from. The return url will be:
* file:/path/my-app/calsses/ or file:/path/my-app/my-app.jar
*
* @return URL
*/
public URL getCodeLocation() {
if (codeLocation != null)
return codeLocation;
// Get code location using the CodeSource
codeLocation = cls.getProtectionDomain().getCodeSource().getLocation();
if (codeLocation != null)
return codeLocation;
// If CodeSource didn't work, use {@link } Class.getResource instead.
URL r = cls.getResource("");
synchronized (r) {
String s = r.toString();
Pattern jar_re = Pattern.compile("jar:\\s?(.*)!/.*");
Matcher m = jar_re.matcher(s);
if (m.find()) { // the code is run from a jar file.
s = m.group(1);
} else {
String p = cls.getPackage().getName().replace('.', '/');
s = s.substring(0, s.lastIndexOf(p));
}
try {
codeLocation = new URL(s);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
return codeLocation;
}
/**
* Get the class path root where the program startup, if run in a jar,
* return the jar file's parent path.
*
* @return
*/
public String getAppDir() {
File f = new File(getCodeLocation().getPath());
return f.isFile() ? f.getParent() : f.getPath();
}
public static void main(String[] args) {
AppDirTest t = new AppDirTest();
System.out.println("code location: " + t.getCodeLocation());
System.out.println("app dir: " + t.getAppDir());
}
}
이상 은 자바 가 클래스 경로 에서 자원 을 정확하게 얻 는 상세 한 내용 입 니 다.자바 가 클래스 경로 에서 자원 을 얻 는 것 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.