Resource 추상화

Resource 추상화

조금 정리하면

ApplicationContext는 단순한 빈 팩토리 뿐만아니라, 여태껏 정리한

ResourceLoader, EventPublisher, MessageSource 등등 여러가지 기능을 가지고있습니다.

Resource 추상화

org.springframework.core.io.Resource

특징

java.net.URL 을 추상화 한 것. java.net.URL 을 org.springframework.core.io.Resource 로 감싸서 실제로 로우레벨에있는 리소스에 접근하는 기능을 추상화 한 것.

스프링 내부에서 많이 사용하는 인터페이스.

추상화 한 이유

클래스패스 기준으로 리소스 읽어오는 기능 부재

ServletContext를 기준으로 상대 경로로 읽어오는 기능 부재

새로운 핸들러를 등록하여 특별한 URL 접미사를 만들어 사용할 수는 있지만 구현이 복잡하고 편의성 메소드가 부족하다.

인터페이스 둘러보기

상속받은 인터페이스

주요 메소드 getInputStream() exist() isOpen() getDescription() : 전체 경로 포함한 파일 이름 또는 실제 URL

구현체

UrlResource : java.net.URL 참고. 기본으로 지원하는 프로토콜 http, https, ftp, file, jar

ClassPathResource : 지원하는 접두어 classpath:

FileSystemResource

ServletContextResource : 웹 애플리케이션 루트에서 상대 경로로 리소스 찾는다.

...

리로스 읽어오기

Resouce 의 타입은 location 문자열과 ApplicationContext 의 타입에 따라 결정된다. ClassPathXmlApplicationContext → ClassPathResource FileSystemXmlApplicationContext → FileSystemResource WebApplicationContext → ServletContextResource

결정된다. ApplicationContext의 타입에 상관없이 리소스 타입을 강제하려면 java.net.URL 접두어(+ classpath:) 중 하나를 사용할 수 있다. classpath: me/whiteship/config.xml → ClassPathResource file: //some/resource/path/config.xml → FileSystemResource 접두어를 사용하는게 명시적이라서 추천.

@Component public class AppRunner implements ApplicationRunner { @Autowired ApplicationContext resourceLoader; @Override public void run(ApplicationArguments args) throws Exception { System.out.println(resourceLoader.getClass()); // ~~WebApplicationContext 로 나와야 함. Resource resource = resourceLoader.getResource("classpath:test.txt"); // 원래는 위와 같아야하지만, System.out.println(resource.getClass()); // classpath: 로 지정하였기 때문에 ClassPathResource 로 나와야함. System.out.println(resource.exists()); System.out.println(resource.getDescription()); System.out.println(Files.readString(Path.of(resource.getURI()))); } }

@Component public class AppRunner implements ApplicationRunner { @Autowired ApplicationContext resourceLoader; @Override public void run(ApplicationArguments args) throws Exception { System.out.println(resourceLoader.getClass()); // ~~WebApplicationContext 로 나와야 함. Resource resource = resourceLoader.getResource("test.txt"); // 접두어를 없앴기때문에, System.out.println(resource.getClass()); // ServletContextResource 로 찍혀야 함. System.out.println(resource.exists()); // tomcat 이 기본 contextPath 가 없으므로. false System.out.println(resource.getDescription()); // ServletContext resource System.out.println(Files.readString(Path.of(resource.getURI()))); // tomcat 이 기본 contextPath 가 없으므로. 에러가 나옴. } }

접두어를 붙이지 않았으므로 지정한 ApplicationContext에 맞는 리소스 형태로 받아옵니다.

ServletContextResource

tomcat 은 기본 contextPath가 없습니다.

추천

Springboot 기반의 애플리케이션을 만들 때, 보통 classPath 기준으로 많은 리소스를 사용합니다.

그러므로 classPath 접두어를 사용하는것을 추천.

주의점

그냥 리소스이름만 적으면 ServletContextResource로 리졸빙 됨.

from http://in-intuition.tistory.com/45 by ccl(A) rewrite - 2021-12-24 01:27:30