资源和资源加载器
建议订阅博主专栏,从下到上系统手写spring源码,体会其中过程!
本代码实现了spring中资源路径加载需求
- 资源加载总共分三种方法进行加载,一种是classpath:,一种是文件系统,还有一种是URL资源定位方式,我们需要为这三个类编写一个抽象的资源接口,对外展示该接口,不涉及具体的实现。编写Resource接口如下:
/**
* 资源的抽象和访问接口
* @author WangChao
* @date 2023/6/17 19:53
*/
public interface Resource {
InputStream getInputStream() throws IOException;
}
以下三种方法都是显示了该接口,为具体的实现类:
- classpath下的资源,编写ClassPathResource如下,该类是通过类加载器获取类路径下的资源文件的输入流:
public class ClassPathResource implements Resource{
private final String path;
public ClassPathResource(String path){
this.path = path;
}
@Override
public InputStream getInputStream() throws IOException {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(this.path);
if(is == null){
throw new FileNotFoundException(this.path + " cannot be opened because it does not exist");
}
return is;
}
}
- 文件系统下的资源,先通过File类的toPath方法获取Path类实例,再通过File类的newInputStream方法获取到文件的输入流:
public class FileSystemResource implements Resource{
private final String path;
public FileSystemResource(String path){
this.path = path;
}
@Override
public InputStream getInputStream() throws IOException {
try{
Path path = new File(this.path).toPath();
return Files.newInputStream(path);
}catch (NoSuchFileException ex){
throw new FileNotFoundException(ex.toString());
}
}
}
- URL下的资源,该方法通过得到URLConnection类来获取文件输入流,具体代码如下:
public class UrlResource implements Resource {
private final URL url;
public UrlResource(URL url){
this.url = url;
}
@Override
public InputStream getInputStream() throws IOException {
URLConnection urlConnection = this.url.openConnection();
try{
return urlConnection.getInputStream();
}catch (IOException ex) {
throw ex;
}
}
}
- 编写资源加载器接口,该接口是用来获取Resource对象,从而获取path路径对应的资源文件输入流:
public interface ResourceLoader {
Resource getResource(String location);
}
- 编写该接口的实现类,通过解析localtion变量,决定使用哪种资源加载器来加载资源文件,代码如下:
public class DefaultResourceLoader implements ResourceLoader{
public static final String CLASSPATH_URL_PREFIX = "classpath:";
@Override
public Resource getResource(String location) {
if(location.startsWith(CLASSPATH_URL_PREFIX)){
//classpath下的资源
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()));
}else{
try {
//尝试当成url来处理
URL url = new URL(location);
return new UrlResource(url);
}catch (MalformedURLException e){
//当成文件系统下的资源处理
return new FileSystemResource(location);
}
}
}
}
- 总结测试:
public class ResourceAndResourceLoaderTest {
@Test
public void testResourceLoader() throws Exception {
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
//加载classpath下的资源
Resource resource = resourceLoader.getResource("classpath:hello.txt");
InputStream inputStream = resource.getInputStream();
String content = IoUtil.readUtf8(inputStream);
System.out.println(content);
Assert.equals(content,"hello world!");
//加载文件系统资源
resource = resourceLoader.getResource("src/test/resources/hello.txt");
Assert.isInstanceOf(FileSystemResource.class,resource);
inputStream = resource.getInputStream();
content = IoUtil.readUtf8(inputStream);
System.out.println(content);
//加载url资源
resource = resourceLoader.getResource("https://www.baidu.com");
Assert.isInstanceOf(UrlResource.class,resource);
inputStream = resource.getInputStream();
content = IoUtil.readUtf8(inputStream);
System.out.println(content);
}
}