spring 中定义了资源接口,部分类关系如下:

spring 资源 resource AbstractFileResolvingResource 抽象文件资源解析

1:getFile 方法实现:
public File getFile() throws IOException {
   URL url = getURL();
   if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {//忽略vfs 文件加载逻辑
      return VfsResourceDelegate.getResource(url).getFile();
   }
   return ResourceUtils.getFile(url, getDescription());
}

getUrl()在子类中实现。

public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {
   Assert.notNull(resourceUrl, "Resource URL must not be null");
   if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) {
      throw new FileNotFoundException(
            description + " cannot be resolved to absolute file path " +
            "because it does not reside in the file system: " + resourceUrl);
   }
   try {
      return new File(toURI(resourceUrl).getSchemeSpecificPart());
      //可以替换成return new File(toURI(resourceUrl));
   }
   catch (URISyntaxException ex) {
      // Fallback for URLs that are not valid URIs (should hardly ever happen).
      return new File(resourceUrl.getFile());
   }
}

2 getFileForLastModifiedCheck 方法实现:

protected File getFileForLastModifiedCheck() throws IOException {
   URL url = getURL();
   if (ResourceUtils.isJarURL(url)) {
      URL actualUrl = ResourceUtils.extractArchiveURL(url);
      if (actualUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
         return VfsResourceDelegate.getResource(actualUrl).getFile();
      }
      return ResourceUtils.getFile(actualUrl, "Jar URL");
   }
   else {
      return getFile();
   }
}
public static boolean isJarURL(URL url) {
   String protocol = url.getProtocol();
   return (URL_PROTOCOL_JAR.equals(protocol) || URL_PROTOCOL_WAR.equals(protocol) ||
         URL_PROTOCOL_ZIP.equals(protocol) || URL_PROTOCOL_VFSZIP.equals(protocol) ||
         URL_PROTOCOL_WSJAR.equals(protocol));
}
//提取档案包 url 地址:
public static URL extractArchiveURL(URL jarUrl) throws MalformedURLException {
   String urlFile = jarUrl.getFile();

   int endIndex = urlFile.indexOf(WAR_URL_SEPARATOR); //WAR_URL_SEPARATOR=="*/"
   if (endIndex != -1) {
      // Tomcat's "war:file:...mywar.war*/WEB-INF/lib/myjar.jar!/myentry.txt"
      String warFile = urlFile.substring(0, endIndex);
      if (URL_PROTOCOL_WAR.equals(jarUrl.getProtocol())) {
         return new URL(warFile);
      }
      int startIndex = warFile.indexOf(WAR_URL_PREFIX);//WAR_URL_PREFIX=="war:"
      if (startIndex != -1) {
         return new URL(warFile.substring(startIndex + WAR_URL_PREFIX.length()));
      }
   }

   // Regular "jar:file:...myjar.jar!/myentry.txt"
   return extractJarFileURL(jarUrl);
}
 //提取jar文件url: Regular "jar:file:...myjar.jar!/myentry.txt"
public static URL extractJarFileURL(URL jarUrl) throws MalformedURLException {
   String urlFile = jarUrl.getFile();
   int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);//JAR_URL_SEPARATOR =="!/"
   if (separatorIndex != -1) {
      String jarFile = urlFile.substring(0, separatorIndex);
      try {
         return new URL(jarFile);
      }
      catch (MalformedURLException ex) {
         // Probably no protocol in original jar URL, like "jar:C:/mypath/myjar.jar".
         // This usually indicates that the jar file resides in the file system.
         if (!jarFile.startsWith("/")) {
            jarFile = "/" + jarFile;
         }
         return new URL(FILE_URL_PREFIX + jarFile);//FILE_URL_PREFIX=="file:"
      }
   }
   else {
      return jarUrl;
   }
}

 

public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {
   Assert.notNull(resourceUrl, "Resource URL must not be null");
   if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) {
      throw new FileNotFoundException(
            description + " cannot be resolved to absolute file path " +
            "because it does not reside in the file system: " + resourceUrl);
   }
   try {
      return new File(toURI(resourceUrl).getSchemeSpecificPart());
   }
   catch (URISyntaxException ex) {
      // Fallback for URLs that are not valid URIs (should hardly ever happen).
      return new File(resourceUrl.getFile());
   }
}

3 exists方法解析:

public boolean exists() {
   try {
      URL url = getURL();
      if (ResourceUtils.isFileURL(url)) {
         // Proceed with file system resolution
         return getFile().exists();
      }
      else {
         // Try a URL connection content-length header
         URLConnection con = url.openConnection();
         customizeConnection(con);
         HttpURLConnection httpCon =
               (con instanceof HttpURLConnection ? (HttpURLConnection) con : null);
         if (httpCon != null) {
            int code = httpCon.getResponseCode();
            if (code == HttpURLConnection.HTTP_OK) {
               return true;
            }
            else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
               return false;
            }
         }
         if (con.getContentLength() >= 0) {
            return true;
         }
         if (httpCon != null) {
            // no HTTP OK status, and no content-length header: give up
            httpCon.disconnect();
            return false;
         }
         else {
            // Fall back to stream existence: can we open the stream?
            InputStream is = getInputStream();
            is.close();
            return true;
         }
      }
   }
   catch (IOException ex) {
      return false;
   }
}
customizeConnection(con)解析:
protected void customizeConnection(URLConnection con) throws IOException {
   ResourceUtils.useCachesIfNecessary(con);
   if (con instanceof HttpURLConnection) {
      customizeConnection((HttpURLConnection) con);
   }
}
protected void customizeConnection(HttpURLConnection con) throws IOException {
   con.setRequestMethod("HEAD");
}

4 isReadable 是否可读:

public boolean isReadable() {
   try {
      URL url = getURL();
      if (ResourceUtils.isFileURL(url)) {
         // Proceed with file system resolution
         File file = getFile();
         return (file.canRead() && !file.isDirectory());
      }
      else {
         return true;
      }
   }
   catch (IOException ex) {
      return false;
   }
}

5 contentLength 解析:

public long contentLength() throws IOException {
   URL url = getURL();
   if (ResourceUtils.isFileURL(url)) {
      // Proceed with file system resolution
      return getFile().length();
   }
   else {
      // Try a URL connection content-length header
      URLConnection con = url.openConnection();
      customizeConnection(con);
      return con.getContentLength();
   }
}

6lastModified 解析:

public long lastModified() throws IOException {
   URL url = getURL();
   if (ResourceUtils.isFileURL(url) || ResourceUtils.isJarURL(url)) {
      // Proceed with file system resolution
      try {
         return super.lastModified();
      }
      catch (FileNotFoundException ex) {
         // Defensively fall back to URL connection check instead
      }
   }
   // Try a URL connection last-modified header
   URLConnection con = url.openConnection();
   customizeConnection(con);
   return con.getLastModified();
}
public long lastModified() throws IOException {
   long lastModified = getFileForLastModifiedCheck().lastModified();
   if (lastModified == 0L) {
      throw new FileNotFoundException(getDescription() +
            " cannot be resolved in the file system for resolving its last-modified timestamp");
   }
   return lastModified;
}

 

 

 

 

 

相关文章: