文档章节

Spring resource

zswitos
 zswitos
发布于 2015/04/25 14:40
字数 5348
阅读 67
收藏 0
点赞 0
评论 0

Spring Resource 1


1、介绍

    java的标准的URL类不足够能访问大部分情况的资源,如没有一个标准的功能获取一个classpath或者想对于servletContext路径下的资源

2、spring resoruce class

    spring的resource是一个能够访问low-level resources的抽象接口

public interface InputStreamSource {   /**    * Return an {@link InputStream}.    * <p>It is expected that each call creates a <i>fresh</i> stream.    * <p>This requirement is particularly important when you consider an API such    * as JavaMail, which needs to be able to read the stream multiple times when    * creating mail attachments. For such a use case, it is <i>required</i>    * that each {@code getInputStream()} call returns a fresh stream.    * @return the input stream for the underlying resource (must not be {@code null})    * @throws IOException if the stream could not be opened    * @see org.springframework.mail.javamail.MimeMessageHelper#addAttachment(String, InputStreamSource)    */   InputStream getInputStream() throws IOException;}
/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.core.io;import java.io.File;import java.io.IOException;import java.net.URI;import java.net.URL;/** * Interface for a resource descriptor that abstracts from the actual * type of underlying resource, such as a file or class path resource. * * <p>An InputStream can be opened for every resource if it exists in * physical form, but a URL or File handle can just be returned for * certain resources. The actual behavior is implementation-specific. * * @author Juergen Hoeller * @since 28.12.2003 * @see #getInputStream() * @see #getURL() * @see #getURI() * @see #getFile() * @see WritableResource * @see ContextResource * @see FileSystemResource * @see ClassPathResource * @see UrlResource * @see ByteArrayResource * @see InputStreamResource * @see PathResource */public interface Resource extends InputStreamSource {   /**    * Return whether this resource actually exists in physical form.    * <p>This method performs a definitive existence check, whereas the    * existence of a {@code Resource} handle only guarantees a    * valid descriptor handle.    */   boolean exists();   /**    * Return whether the contents of this resource can be read,    * e.g. via {@link #getInputStream()} or {@link #getFile()}.    * <p>Will be {@code true} for typical resource descriptors;    * note that actual content reading may still fail when attempted.    * However, a value of {@code false} is a definitive indication    * that the resource content cannot be read.    * @see #getInputStream()    */   boolean isReadable();   /**    * Return whether this resource represents a handle with an open    * stream. If true, the InputStream cannot be read multiple times,    * and must be read and closed to avoid resource leaks.    * <p>Will be {@code false} for typical resource descriptors.    */   boolean isOpen();   /**    * Return a URL handle for this resource.    * @throws IOException if the resource cannot be resolved as URL,    * i.e. if the resource is not available as descriptor    */   URL getURL() throws IOException;   /**    * Return a URI handle for this resource.    * @throws IOException if the resource cannot be resolved as URI,    * i.e. if the resource is not available as descriptor    */   URI getURI() throws IOException;   /**    * Return a File handle for this resource.    * @throws IOException if the resource cannot be resolved as absolute    * file path, i.e. if the resource is not available in a file system    */   File getFile() throws IOException;   /**    * Determine the content length for this resource.    * @throws IOException if the resource cannot be resolved    * (in the file system or as some other known physical resource type)    */   long contentLength() throws IOException;   /**    * Determine the last-modified timestamp for this resource.    * @throws IOException if the resource cannot be resolved    * (in the file system or as some other known physical resource type)    */   long lastModified() throws IOException;   /**    * Create a resource relative to this resource.    * @param relativePath the relative path (relative to this resource)    * @return the resource handle for the relative resource    * @throws IOException if the relative resource cannot be determined    */   Resource createRelative(String relativePath) throws IOException;   /**    * Determine a filename for this resource, i.e. typically the last    * part of the path: for example, "myfile.txt".    * <p>Returns {@code null} if this type of resource does not    * have a filename.    */   String getFilename();   /**    * Return a description for this resource,    * to be used for error output when working with the resource.    * <p>Implementations are also encouraged to return this value    * from their {@code toString} method.    * @see Object#toString()    */   String getDescription();}


它有好多的实现类

UrlResource

/* * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.core.io;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URI;import java.net.URISyntaxException;import java.net.URL;import java.net.URLConnection;import org.springframework.util.Assert;import org.springframework.util.ResourceUtils;import org.springframework.util.StringUtils;/** * {@link Resource} implementation for {@code java.net.URL} locators. * Obviously supports resolution as URL, and also as File in case of * the "file:" protocol. * * @author Juergen Hoeller * @since 28.12.2003 * @see java.net.URL */public class UrlResource extends AbstractFileResolvingResource {   /**    * Original URI, if available; used for URI and File access.    */   private final URI uri;   /**    * Original URL, used for actual access.    */   private final URL url;   /**    * Cleaned URL (with normalized path), used for comparisons.    */   private final URL cleanedUrl;   /**    * Create a new UrlResource based on the given URI object.    * @param uri a URI    * @throws MalformedURLException if the given URL path is not valid    */   public UrlResource(URI uri) throws MalformedURLException {      Assert.notNull(uri, "URI must not be null");      this.uri = uri;      this.url = uri.toURL();      this.cleanedUrl = getCleanedUrl(this.url, uri.toString());   }   /**    * Create a new UrlResource based on the given URL object.    * @param url a URL    */   public UrlResource(URL url) {      Assert.notNull(url, "URL must not be null");      this.url = url;      this.cleanedUrl = getCleanedUrl(this.url, url.toString());      this.uri = null;   }   /**    * Create a new UrlResource based on a URL path.    * <p>Note: The given path needs to be pre-encoded if necessary.    * @param path a URL path    * @throws MalformedURLException if the given URL path is not valid    * @see java.net.URL#URL(String)    */   public UrlResource(String path) throws MalformedURLException {      Assert.notNull(path, "Path must not be null");      this.uri = null;      this.url = new URL(path);      this.cleanedUrl = getCleanedUrl(this.url, path);   }   /**    * Create a new UrlResource based on a URI specification.    * <p>The given parts will automatically get encoded if necessary.    * @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);    * also known as "scheme"    * @param location the location (e.g. the file path within that protocol);    * also known as "scheme-specific part"    * @throws MalformedURLException if the given URL specification is not valid    * @see java.net.URI#URI(String, String, String)    */   public UrlResource(String protocol, String location) throws MalformedURLException  {      this(protocol, location, null);   }   /**    * Create a new UrlResource based on a URI specification.    * <p>The given parts will automatically get encoded if necessary.    * @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);    * also known as "scheme"    * @param location the location (e.g. the file path within that protocol);    * also known as "scheme-specific part"    * @param fragment the fragment within that location (e.g. anchor on an HTML page,    * as following after a "#" separator)    * @throws MalformedURLException if the given URL specification is not valid    * @see java.net.URI#URI(String, String, String)    */   public UrlResource(String protocol, String location, String fragment) throws MalformedURLException  {      try {         this.uri = new URI(protocol, location, fragment);         this.url = this.uri.toURL();         this.cleanedUrl = getCleanedUrl(this.url, this.uri.toString());      }      catch (URISyntaxException ex) {         MalformedURLException exToThrow = new MalformedURLException(ex.getMessage());         exToThrow.initCause(ex);         throw exToThrow;      }   }   /**    * Determine a cleaned URL for the given original URL.    * @param originalUrl the original URL    * @param originalPath the original URL path    * @return the cleaned URL    * @see org.springframework.util.StringUtils#cleanPath    */   private URL getCleanedUrl(URL originalUrl, String originalPath) {      try {         return new URL(StringUtils.cleanPath(originalPath));      }      catch (MalformedURLException ex) {         // Cleaned URL path cannot be converted to URL         // -> take original URL.         return originalUrl;      }   }   /**    * This implementation opens an InputStream for the given URL.    * It sets the "UseCaches" flag to {@code false},    * mainly to avoid jar file locking on Windows.    * @see java.net.URL#openConnection()    * @see java.net.URLConnection#setUseCaches(boolean)    * @see java.net.URLConnection#getInputStream()    */   @Override   public InputStream getInputStream() throws IOException {      URLConnection con = this.url.openConnection();      ResourceUtils.useCachesIfNecessary(con);      try {         return con.getInputStream();      }      catch (IOException ex) {         // Close the HTTP connection (if applicable).         if (con instanceof HttpURLConnection) {            ((HttpURLConnection) con).disconnect();         }         throw ex;      }   }   /**    * This implementation returns the underlying URL reference.    */   @Override   public URL getURL() throws IOException {      return this.url;   }   /**    * This implementation returns the underlying URI directly,    * if possible.    */   @Override   public URI getURI() throws IOException {      if (this.uri != null) {         return this.uri;      }      else {         return super.getURI();      }   }   /**    * This implementation returns a File reference for the underlying URL/URI,    * provided that it refers to a file in the file system.    * @see org.springframework.util.ResourceUtils#getFile(java.net.URL, String)    */   @Override   public File getFile() throws IOException {      if (this.uri != null) {         return super.getFile(this.uri);      }      else {         return super.getFile();      }   }   /**    * This implementation creates a UrlResource, applying the given path    * relative to the path of the underlying URL of this resource descriptor.    * @see java.net.URL#URL(java.net.URL, String)    */   @Override   public Resource createRelative(String relativePath) throws MalformedURLException {      if (relativePath.startsWith("/")) {         relativePath = relativePath.substring(1);      }      return new UrlResource(new URL(this.url, relativePath));   }   /**    * This implementation returns the name of the file that this URL refers to.    * @see java.net.URL#getFile()    * @see java.io.File#getName()    */   @Override   public String getFilename() {      return new File(this.url.getFile()).getName();   }   /**    * This implementation returns a description that includes the URL.    */   @Override   public String getDescription() {      return "URL [" + this.url + "]";   }   /**    * This implementation compares the underlying URL references.    */   @Override   public boolean equals(Object obj) {      return (obj == this ||         (obj instanceof UrlResource && this.cleanedUrl.equals(((UrlResource) obj).cleanedUrl)));   }   /**    * This implementation returns the hash code of the underlying URL reference.    */   @Override   public int hashCode() {      return this.cleanedUrl.hashCode();   }}

ClassPathResource:

    This Resource implementation supports resolution as java.io.File if the class path resource
    resides in the file system, but not for classpath resources which reside in a jar and have not been
    expanded (by the servlet engine, or whatever the environment is) to the filesystem. To address this the
    various Resource implementations always support resolution as a java.net.URL.

/* * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.core.io;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.net.URL;import org.springframework.util.Assert;import org.springframework.util.ClassUtils;import org.springframework.util.ObjectUtils;import org.springframework.util.StringUtils;/** * {@link Resource} implementation for class path resources. * Uses either a given ClassLoader or a given Class for loading resources. * * <p>Supports resolution as {@code java.io.File} if the class path * resource resides in the file system, but not for resources in a JAR. * Always supports resolution as URL. * * @author Juergen Hoeller * @author Sam Brannen * @since 28.12.2003 * @see ClassLoader#getResourceAsStream(String) * @see Class#getResourceAsStream(String) */public class ClassPathResource extends AbstractFileResolvingResource {   private final String path;   private ClassLoader classLoader;   private Class<?> clazz;   /**    * Create a new {@code ClassPathResource} for {@code ClassLoader} usage.    * A leading slash will be removed, as the ClassLoader resource access    * methods will not accept it.    * <p>The thread context class loader will be used for    * loading the resource.    * @param path the absolute path within the class path    * @see java.lang.ClassLoader#getResourceAsStream(String)    * @see org.springframework.util.ClassUtils#getDefaultClassLoader()    */   public ClassPathResource(String path) {      this(path, (ClassLoader) null);   }   /**    * Create a new {@code ClassPathResource} for {@code ClassLoader} usage.    * A leading slash will be removed, as the ClassLoader resource access    * methods will not accept it.    * @param path the absolute path within the classpath    * @param classLoader the class loader to load the resource with,    * or {@code null} for the thread context class loader    * @see ClassLoader#getResourceAsStream(String)    */   public ClassPathResource(String path, ClassLoader classLoader) {      Assert.notNull(path, "Path must not be null");      String pathToUse = StringUtils.cleanPath(path);      if (pathToUse.startsWith("/")) {         pathToUse = pathToUse.substring(1);      }      this.path = pathToUse;      this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());   }   /**    * Create a new {@code ClassPathResource} for {@code Class} usage.    * The path can be relative to the given class, or absolute within    * the classpath via a leading slash.    * @param path relative or absolute path within the class path    * @param clazz the class to load resources with    * @see java.lang.Class#getResourceAsStream    */   public ClassPathResource(String path, Class<?> clazz) {      Assert.notNull(path, "Path must not be null");      this.path = StringUtils.cleanPath(path);      this.clazz = clazz;   }   /**    * Create a new {@code ClassPathResource} with optional {@code ClassLoader}    * and {@code Class}. Only for internal usage.    * @param path relative or absolute path within the classpath    * @param classLoader the class loader to load the resource with, if any    * @param clazz the class to load resources with, if any    */   protected ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) {      this.path = StringUtils.cleanPath(path);      this.classLoader = classLoader;      this.clazz = clazz;   }   /**    * Return the path for this resource (as resource path within the class path).    */   public final String getPath() {      return this.path;   }   /**    * Return the ClassLoader that this resource will be obtained from.    */   public final ClassLoader getClassLoader() {      return (this.clazz != null ? this.clazz.getClassLoader() : this.classLoader);   }   /**    * This implementation checks for the resolution of a resource URL.    * @see java.lang.ClassLoader#getResource(String)    * @see java.lang.Class#getResource(String)    */   @Override   public boolean exists() {      return (resolveURL() != null);   }   /**    * Resolves a URL for the underlying class path resource.    * @return the resolved URL, or {@code null} if not resolvable    */   protected URL resolveURL() {      if (this.clazz != null) {         return this.clazz.getResource(this.path);      }      else if (this.classLoader != null) {         return this.classLoader.getResource(this.path);      }      else {         return ClassLoader.getSystemResource(this.path);      }   }   /**    * This implementation opens an InputStream for the given class path resource.    * @see java.lang.ClassLoader#getResourceAsStream(String)    * @see java.lang.Class#getResourceAsStream(String)    */   @Override   public InputStream getInputStream() throws IOException {      InputStream is;      if (this.clazz != null) {         is = this.clazz.getResourceAsStream(this.path);      }      else if (this.classLoader != null) {         is = this.classLoader.getResourceAsStream(this.path);      }      else {         is = ClassLoader.getSystemResourceAsStream(this.path);      }      if (is == null) {         throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");      }      return is;   }   /**    * This implementation returns a URL for the underlying class path resource,    * if available.    * @see java.lang.ClassLoader#getResource(String)    * @see java.lang.Class#getResource(String)    */   @Override   public URL getURL() throws IOException {      URL url = resolveURL();      if (url == null) {         throw new FileNotFoundException(getDescription() + " cannot be resolved to URL because it does not exist");      }      return url;   }   /**    * This implementation creates a ClassPathResource, applying the given path    * relative to the path of the underlying resource of this descriptor.    * @see org.springframework.util.StringUtils#applyRelativePath(String, String)    */   @Override   public Resource createRelative(String relativePath) {      String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);      return new ClassPathResource(pathToUse, this.classLoader, this.clazz);   }   /**    * This implementation returns the name of the file that this class path    * resource refers to.    * @see org.springframework.util.StringUtils#getFilename(String)    */   @Override   public String getFilename() {      return StringUtils.getFilename(this.path);   }   /**    * This implementation returns a description that includes the class path location.    */   @Override   public String getDescription() {      StringBuilder builder = new StringBuilder("class path resource [");      String pathToUse = path;      if (this.clazz != null && !pathToUse.startsWith("/")) {         builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));         builder.append('/');      }      if (pathToUse.startsWith("/")) {         pathToUse = pathToUse.substring(1);      }      builder.append(pathToUse);      builder.append(']');      return builder.toString();   }   /**    * This implementation compares the underlying class path locations.    */   @Override   public boolean equals(Object obj) {      if (obj == this) {         return true;      }      if (obj instanceof ClassPathResource) {         ClassPathResource otherRes = (ClassPathResource) obj;         return (this.path.equals(otherRes.path) &&               ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) &&               ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz));      }      return false;   }   /**    * This implementation returns the hash code of the underlying    * class path location.    */   @Override   public int hashCode() {      return this.path.hashCode();   }}


FileSystemResource :

This is a Resource implementation for java.io.File handles. It obviously supports resolution as a File, and as a URL.

/* * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.core.io;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.URI;import java.net.URL;import org.springframework.util.Assert;import org.springframework.util.StringUtils;/** * {@link Resource} implementation for {@code java.io.File} handles. * Obviously supports resolution as File, and also as URL. * Implements the extended {@link WritableResource} interface. * * @author Juergen Hoeller * @since 28.12.2003 * @see java.io.File */public class FileSystemResource extends AbstractResource implements WritableResource {   private final File file;   private final String path;   /**    * Create a new {@code FileSystemResource} from a {@link File} handle.    * <p>Note: When building relative resources via {@link #createRelative},    * the relative path will apply <i>at the same directory level</i>:    * e.g. new File("C:/dir1"), relative path "dir2" -> "C:/dir2"!    * If you prefer to have relative paths built underneath the given root    * directory, use the {@link #FileSystemResource(String) constructor with a file path}    * to append a trailing slash to the root path: "C:/dir1/", which    * indicates this directory as root for all relative paths.    * @param file a File handle    */   public FileSystemResource(File file) {      Assert.notNull(file, "File must not be null");      this.file = file;      this.path = StringUtils.cleanPath(file.getPath());   }   /**    * Create a new {@code FileSystemResource} from a file path.    * <p>Note: When building relative resources via {@link #createRelative},    * it makes a difference whether the specified resource base path here    * ends with a slash or not. In the case of "C:/dir1/", relative paths    * will be built underneath that root: e.g. relative path "dir2" ->    * "C:/dir1/dir2". In the case of "C:/dir1", relative paths will apply    * at the same directory level: relative path "dir2" -> "C:/dir2".    * @param path a file path    */   public FileSystemResource(String path) {      Assert.notNull(path, "Path must not be null");      this.file = new File(path);      this.path = StringUtils.cleanPath(path);   }   /**    * Return the file path for this resource.    */   public final String getPath() {      return this.path;   }   /**    * This implementation returns whether the underlying file exists.    * @see java.io.File#exists()    */   @Override   public boolean exists() {      return this.file.exists();   }   /**    * This implementation checks whether the underlying file is marked as readable    * (and corresponds to an actual file with content, not to a directory).    * @see java.io.File#canRead()    * @see java.io.File#isDirectory()    */   @Override   public boolean isReadable() {      return (this.file.canRead() && !this.file.isDirectory());   }   /**    * This implementation opens a FileInputStream for the underlying file.    * @see java.io.FileInputStream    */   @Override   public InputStream getInputStream() throws IOException {      return new FileInputStream(this.file);   }   /**    * This implementation returns a URL for the underlying file.    * @see java.io.File#toURI()    */   @Override   public URL getURL() throws IOException {      return this.file.toURI().toURL();   }   /**    * This implementation returns a URI for the underlying file.    * @see java.io.File#toURI()    */   @Override   public URI getURI() throws IOException {      return this.file.toURI();   }   /**    * This implementation returns the underlying File reference.    */   @Override   public File getFile() {      return this.file;   }   /**    * This implementation returns the underlying File's length.    */   @Override   public long contentLength() throws IOException {      return this.file.length();   }   /**    * This implementation creates a FileSystemResource, applying the given path    * relative to the path of the underlying file of this resource descriptor.    * @see org.springframework.util.StringUtils#applyRelativePath(String, String)    */   @Override   public Resource createRelative(String relativePath) {      String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);      return new FileSystemResource(pathToUse);   }   /**    * This implementation returns the name of the file.    * @see java.io.File#getName()    */   @Override   public String getFilename() {      return this.file.getName();   }   /**    * This implementation returns a description that includes the absolute    * path of the file.    * @see java.io.File#getAbsolutePath()    */   @Override   public String getDescription() {      return "file [" + this.file.getAbsolutePath() + "]";   }   // implementation of WritableResource   /**    * This implementation checks whether the underlying file is marked as writable    * (and corresponds to an actual file with content, not to a directory).    * @see java.io.File#canWrite()    * @see java.io.File#isDirectory()    */   @Override   public boolean isWritable() {      return (this.file.canWrite() && !this.file.isDirectory());   }   /**    * This implementation opens a FileOutputStream for the underlying file.    * @see java.io.FileOutputStream    */   @Override   public OutputStream getOutputStream() throws IOException {      return new FileOutputStream(this.file);   }   /**    * This implementation compares the underlying File references.    */   @Override   public boolean equals(Object obj) {      return (obj == this ||         (obj instanceof FileSystemResource && this.path.equals(((FileSystemResource) obj).path)));   }   /**    * This implementation returns the hash code of the underlying File reference.    */   @Override   public int hashCode() {      return this.path.hashCode();   }}

ServletContextResource :

    This is a Resource implementation for ServletContext resources, interpreting relative paths within
the relevant web application’s root directory.
This always supports stream access and URL access, but only allows java.io.File access when
the web application archive is expanded and the resource is physically on the filesystem. Whether or
not it’s expanded and on the filesystem like this, or accessed directly from the JAR or somewhere else
like a DB (it’s conceivable) is actually dependent on the Servlet container.

ServletContextResourceServletContextResourceServletContextResource

InputStreamResource :

A Resource implementation for a given InputStream. This should only be used if no specific Resource implementation is applicable. In particular, prefer ByteArrayResource or any of the file-based Resource implementations where possible.In contrast to other Resource implementations, this is a descriptor for an already opened resource - therefore returning true from isOpen(). Do not use it if you need to keep the resource descriptor

somewhere, or if you need to read a stream multiple times.

InputStreamResourceInputStreamResource


ByteArrayResource:

    This is a Resource implementation for a given byte array. It creates a ByteArrayInputStream for the given byte array. It’s useful for loading content from any given byte array, without having to resort to a single-use InputStreamResource.


ByteArrayResourceByteArrayResourceByteArrayResource


3、Spring ResourceLoader

这个接口是用来获取Resource类的


有第二部分可知每个Resource会对应有个ResourceLoader类

/* * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.core.io;import org.springframework.util.ResourceUtils;/** * Strategy interface for loading resources (e.. class path or file system * resources). An {@link org.springframework.context.ApplicationContext} * is required to provide this functionality, plus extended * {@link org.springframework.core.io.support.ResourcePatternResolver} support. * * <p>{@link DefaultResourceLoader} is a standalone implementation that is * usable outside an ApplicationContext, also used by {@link ResourceEditor}. * * <p>Bean properties of type Resource and Resource array can be populated * from Strings when running in an ApplicationContext, using the particular * context's resource loading strategy. * * @author Juergen Hoeller * @since 10.03.2004 * @see Resource * @see org.springframework.core.io.support.ResourcePatternResolver * @see org.springframework.context.ApplicationContext * @see org.springframework.context.ResourceLoaderAware */public interface ResourceLoader {   /** Pseudo URL prefix for loading from the class path: "classpath:" */   String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;   /**    * Return a Resource handle for the specified resource.    * The handle should always be a reusable resource descriptor,    * allowing for multiple {@link Resource#getInputStream()} calls.    * <p><ul>    * <li>Must support fully qualified URLs, e.g. "file:C:/test.dat".    * <li>Must support classpath pseudo-URLs, e.g. "classpath:test.dat".    * <li>Should support relative file paths, e.g. "WEB-INF/test.dat".    * (This will be implementation-specific, typically provided by an    * ApplicationContext implementation.)    * </ul>    * <p>Note that a Resource handle does not imply an existing resource;    * you need to invoke {@link Resource#exists} to check for existence.    * @param location the resource location    * @return a corresponding Resource handle    * @see #CLASSPATH_URL_PREFIX    * @see org.springframework.core.io.Resource#exists    * @see org.springframework.core.io.Resource#getInputStream    */   Resource getResource(String location);   /**    * Expose the ClassLoader used by this ResourceLoader.    * <p>Clients which need to access the ClassLoader directly can do so    * in a uniform manner with the ResourceLoader, rather than relying    * on the thread context ClassLoader.    * @return the ClassLoader (only {@code null} if even the system    * ClassLoader isn't accessible)    * @see org.springframework.util.ClassUtils#getDefaultClassLoader()    */   ClassLoader getClassLoader();}

    

Resource template = ctx.getResource("some/resource/path/myTemplate.txt")

当你这样获取一个资源的时候,ctx为ClassPathXmlApplicationContext得到ClassPathResource,FileSystemXmlApplicationContext得到FileSystemResource,WebApplicationContext,得到ServletContextResource,用啥环境的什么资源

Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");

可以这样子指定资源的url


Table 6.1. Resource strings

Prefix
Example Explanation
classpath: classpath:com/myapp/config.xml Loaded from the classpath.
file: file:///data/config.xml Loaded as a URL, from thefilesystem.
http: http://myserver/logo.png Loaded as a URL.
(none) /data/config.xml Depends on the underlying ApplicationContext.

 

4、The ResourceLoaderAware interface

/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.context;import org.springframework.beans.factory.Aware;import org.springframework.core.io.ResourceLoader;/** * Interface to be implemented by any object that wishes to be notified of * the <b>ResourceLoader</b> (typically the ApplicationContext) that it runs in. * This is an alternative to a full ApplicationContext dependency via the * ApplicationContextAware interface. * * <p>Note that Resource dependencies can also be exposed as bean properties * of type Resource, populated via Strings with automatic type conversion by * the bean factory. This removes the need for implementing any callback * interface just for the purpose of accessing a specific file resource. * * <p>You typically need a ResourceLoader when your application object has * to access a variety of file resources whose names are calculated. A good * strategy is to make the object use a DefaultResourceLoader but still * implement ResourceLoaderAware to allow for overriding when running in an * ApplicationContext. See ReloadableResourceBundleMessageSource for an example. * * <p>A passed-in ResourceLoader can also be checked for the * <b>ResourcePatternResolver</b> interface and cast accordingly, to be able * to resolve resource patterns into arrays of Resource objects. This will always * work when running in an ApplicationContext (the context interface extends * ResourcePatternResolver). Use a PathMatchingResourcePatternResolver as default. * See also the {@code ResourcePatternUtils.getResourcePatternResolver} method. * * <p>As alternative to a ResourcePatternResolver dependency, consider exposing * bean properties of type Resource array, populated via pattern Strings with * automatic type conversion by the bean factory. * * @author Juergen Hoeller * @author Chris Beams * @since 10.03.2004 * @see ApplicationContextAware * @see org.springframework.beans.factory.InitializingBean * @see org.springframework.core.io.Resource * @see org.springframework.core.io.support.ResourcePatternResolver * @see org.springframework.core.io.support.ResourcePatternUtils#getResourcePatternResolver * @see org.springframework.core.io.DefaultResourceLoader * @see org.springframework.core.io.support.PathMatchingResourcePatternResolver * @see org.springframework.context.support.ReloadableResourceBundleMessageSource */public interface ResourceLoaderAware extends Aware {   /**    * Set the ResourceLoader that this object runs in.    * <p>This might be a ResourcePatternResolver, which can be checked    * through {@code instanceof ResourcePatternResolver}. See also the    * {@code ResourcePatternUtils.getResourcePatternResolver} method.    * <p>Invoked after population of normal bean properties but before an init callback    * like InitializingBean's {@code afterPropertiesSet} or a custom init-method.    * Invoked before ApplicationContextAware's {@code setApplicationContext}.    * @param resourceLoader ResourceLoader object to be used by this object    * @see org.springframework.core.io.support.ResourcePatternResolver    * @see org.springframework.core.io.support.ResourcePatternUtils#getResourcePatternResolver    */   void setResourceLoader(ResourceLoader resourceLoader);}

获取ResourceLoader的方法实现 ResourceLoaderAware 这个接口,在容器启动给你注入(这个样子不好,耦合api)

第二种做法用注解

@Autowired private ResourceLoader resourceLoader;

看来spring为大家提供了好多Aware接口去获取系统的对象啊这个一个扩展思路,可以借鉴下!


4、何时加载Resource


ApplicationContext applicationContext =
        new FileSystemXmlApplicationContext("file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml");

为例子,在

 1

FileSystemXmlApplicationContext("file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml");
调用
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
   this(new String[] {configLocation}, true, null);
}
再调用
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}


一直调用至父类 AbstractApplicationContext
public AbstractApplicationContext(ApplicationContext parent) {
   this();
   setParent(parent);
}

在调用
public AbstractApplicationContext() {
   this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
   return new PathMatchingResourcePatternResolver(this);
}
这个时候获取Resource的Resolver类被设定了
PathMatchingResourcePatternResolver

public PathMatchingResourcePatternResolver() {
        this.resourceLoader = new DefaultResourceLoader();
    }

public ResourceLoader getResourceLoader() {
   return this.resourceLoader;
}

@Override
public ClassLoader getClassLoader() {
   return getResourceLoader().getClassLoader();
}

@Override
public Resource[] getResources(String locationPattern) throws IOException {
   Assert.notNull(locationPattern, "Location pattern must not be null");
   if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
      // a class path resource (multiple resources for same name possible)
      if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
         // a class path resource pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // all class path resources with the given name
         return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
      }
   }
   else {
      // Only look for a pattern after a prefix here
      // (to not get fooled by a pattern symbol in a strange prefix).
      int prefixEnd = locationPattern.indexOf(":") + 1;
      if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
         // a file pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // a single resource with the given name
         return new Resource[] {getResourceLoader().getResource(locationPattern)};
      }
   }
}


再获取资源的时候会调用DefaultResourceLoader的getResource

@Override
public Resource getResource(String location) {
   Assert.notNull(location, "Location must not be null");
   if (location.startsWith("/")) {
      return getResourceByPath(location);
   }
   else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
      return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
   }
   else {
      try {
         // Try to parse the location as a URL...
         URL url = new URL(location);
         return new UrlResource(url);
      }
      catch (MalformedURLException ex) {
         // No URL -> resolve as resource path.
         return getResourceByPath(location);
      }
   }
}

ok至此获取资源的流程清晰了

别忘记此时指示初始化了,还没有被调用,回到

public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
     // Prepare this context for refreshing.
     prepareRefresh();

     // Tell the subclass to refresh the internal bean factory.
     ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

     // Prepare the bean factory for use in this context.
     prepareBeanFactory(beanFactory);

     try {
        // Allows post-processing of the bean factory in context subclasses.
        postProcessBeanFactory(beanFactory);

        // Invoke factory processors registered as beans in the context.
        invokeBeanFactoryPostProcessors(beanFactory);

        // Register bean processors that intercept bean creation.
        registerBeanPostProcessors(beanFactory);

        // Initialize message source for this context.
        initMessageSource();

        // Initialize event multicaster for this context.
        initApplicationEventMulticaster();

        // Initialize other special beans in specific context subclasses.
        onRefresh();

        // Check for listener beans and register them.
        registerListeners();

        // Instantiate all remaining (non-lazy-init) singletons.
        finishBeanFactoryInitialization(beanFactory);

        // Last step: publish corresponding event.
        finishRefresh();
     }

     catch (BeansException ex) {
        logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

        // Destroy already created singletons to avoid dangling resources.
        destroyBeans();

        // Reset 'active' flag.
        cancelRefresh(ex);

        // Propagate exception to caller.
        throw ex;
     }
  }
}
 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}


protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

到了关键了在

loadBeanDefinitions(beanFactory);方法时候

AbstractXmlApplicationContext的

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
   }
}

然后是

AbstractBeanDefinitionReader的
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
   Assert.notNull(locations, "Location array must not be null");
   int counter = 0;
   for (String location : locations) {
      counter += loadBeanDefinitions(location);
   }
   return counter;
}

public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
   ResourceLoader resourceLoader = getResourceLoader();
   if (resourceLoader == null) {
      throw new BeanDefinitionStoreException(
            "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
   }

   if (resourceLoader instanceof ResourcePatternResolver) {
      // Resource pattern matching available.
      try {
         Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
         int loadCount = loadBeanDefinitions(resources);
         if (actualResources != null) {
            for (Resource resource : resources) {
               actualResources.add(resource);
            }
         }
         if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
         }
         return loadCount;
      }
      catch (IOException ex) {
         throw new BeanDefinitionStoreException(
               "Could not resolve bean definition resource pattern [" + location + "]", ex);
      }
   }
   else {
      // Can only load single resources by absolute URL.
      Resource resource = resourceLoader.getResource(location);
      int loadCount = loadBeanDefinitions(resource);
      if (actualResources != null) {
         actualResources.add(resource);
      }
      if (logger.isDebugEnabled()) {
         logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
      }
      return loadCount;
   }
}





@Override
public Resource[] getResources(String locationPattern) throws IOException {
   return this.resourcePatternResolver.getResources(locationPattern);
}

即是调用PathMatchingResourcePatternResolver的getResources

@Override
public Resource[] getResources(String locationPattern) throws IOException {
   Assert.notNull(locationPattern, "Location pattern must not be null");
   if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
      // a class path resource (multiple resources for same name possible)
      if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
         // a class path resource pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // all class path resources with the given name
         return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
      }
   }
   else {
      // Only look for a pattern after a prefix here
      // (to not get fooled by a pattern symbol in a strange prefix).
      int prefixEnd = locationPattern.indexOf(":") + 1;
      if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
         // a file pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // a single resource with the given name
         return new Resource[] {getResourceLoader().getResource(locationPattern)};
      }
   }
}

ok完成了 入口就是在

AbstractApplicationContext的refresh方法里面的
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();


© 著作权归作者所有

共有 人打赏支持
zswitos
粉丝 4
博文 58
码字总数 54950
作品 0
海淀
程序员
Spring中formdata方式提交json对象和file之一

问题 想使用vue-resource表单提交方式到spring,这个表单中包含json对象和file对象。 思路 将json对象和file对象都放到表单提交方式里面的中,并在中指定内容格式。 步骤 Spring实现和配置 ...

亚林瓜子 ⋅ 06/12 ⋅ 0

Spring 常用的注解及“依赖注入”的实现

1、spring注解 @Controller 声明Action组件 @Service 声明Service组件 @Service("myMovieLister") @Repository 声明Dao组件 @Component 泛指组件, 当不好归类时. @RequestMapping("/menu") ......

沉淀人生 ⋅ 05/28 ⋅ 0

Spring系列之Spring常用注解总结

传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点: 1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么...

HJCui ⋅ 05/29 ⋅ 0

Spring Boot 注解(1)

启动类注解 @SpringBootApplication 使用@SpringbootApplication注解 可以解决根类或者配置类(我自己的说法,就是main所在类)头上注解过多的问题,一个@SpringbootApplication相当于@Conf...

细节探索者 ⋅ 前天 ⋅ 0

详解Java的Spring框架中的注解的用法

使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的 类的实现: 配置文件: 1.2. 引入@Autowired注解(不推荐使用,建议使用@Resource) 类的实现(对成员变量进行标注) 或者...

Airship ⋅ 04/22 ⋅ 0

Spring下的@Inject、@Autowired、@Resource注解区别(转)

1、@Inject javax.inject JSR330 (Dependency Injection for Java) 这是JSR330中的规范,通过AutowiredAnnotationBeanPostProcessor类实现的依赖注入。 @Inject使用 如下是@Inject的使用,不......

easonjim ⋅ 2017/10/24 ⋅ 0

spring boot 2.x静态资源会被HandlerInterceptor拦截的原因和解决方法

在spring boot 1.5.x中,resources/static目录下的静态资源可以直接访问,并且访问路径上不用带static,比如静态资源放置位置如下图所示: 那么访问静态资源的路径可以是: http://localhost...

Mr---D ⋅ 04/13 ⋅ 0

说说 Spring 的注解配置

1 定义 Bean XML 或注解配置方式,都是表达 Bean 定义的载体,其实质都是为 Spring 容器提供 Bean 定义的信息 。 基于注解的配置方式,从 Spring2.0 开始引入, Spring2.5 完善, Spring4.0 ...

deniro ⋅ 05/10 ⋅ 0

Spring Boot 单元测试详解+实战教程

Spring Boot 的测试类库 Spring Boot 提供了许多实用工具和注解来帮助测试应用程序,主要包括以下两个模块。 spring-boot-test:支持测试的核心内容。 spring-boot-test-autoconfigure:支持...

Java技术栈 ⋅ 06/14 ⋅ 0

Spring中涉及的设计模式总结

Spring中涉及的设计模式总结 1.简单工厂(非23种设计模式中的一种) 实现方式:BeanFactory。 Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是...

caoxiaohong1005 ⋅ 04/22 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

行政区划代码转为字典形式

原数据为: http://www.mca.gov.cn/article/sj/xzqh/2018/201804-12/201804-06041553.html 手动替换了一下格式,并使用下面的代码处理. # 输入格式s = """110000:北京市110101:东城区1101...

漫步海边小路 ⋅ 10分钟前 ⋅ 0

android apk 签名

创建key,需要用到keytool.exe (位于C:\Program Files\Java\jdk1.6.0_10\bin目录下),使用产生的key对apk签名用到的是jarsigner.exe (位于C:\Program Files\Java\jdk1.6.0_10\bin目录下),把...

国仔饼 ⋅ 18分钟前 ⋅ 0

springcloud+jps+mybatis多数据库配置

多数据库配置 配置我们目录结构设置: config ---datasource ----jpa ----mybatis ----redis Datasource中是数据的相关配置 Jap中是springDatajpa的相关配置 Mybatis中是mybatis的相关配置 ...

大-智-若-愚 ⋅ 26分钟前 ⋅ 0

Spring mvc HandlerMapping 实现机制

概述 当DispatcherServlet接受到客户端的请求后,SpringMVC 通过 HandlerMapping 找到请求的Controller。 HandlerMapping 在这里起到路由的作用,负责找到请求的Controller。 Spring MVC 默认...

轨迹_ ⋅ 29分钟前 ⋅ 0

JavaScript零基础入门——(十)JavaScript的DOM基础

JavaScript零基础入门——(十)JavaScript的DOM基础 欢迎大家回到我们的JavaScript零基础入门,上一节课,我们了解了JavaScript中的函数,这一节课,我们来了解一下JavaScript的DOM。 第一节...

JandenMa ⋅ 今天 ⋅ 0

Weex起步

本教程假设你已经在你的本地环境安装了node 其实weex起步教程在 https://github.com/lilugirl/incubator-weex 项目说明文件中都已经有了,但为了有些同学看到英文秒变文盲,所以这里我重新写...

lilugirl ⋅ 今天 ⋅ 0

Jenkins实践1 之安装

1 下载 http://mirrors.jenkins.io/war/latest/jenkins.war 2 启动 java -jar jenkins.war 前提:安装jdk并配置环境变量 启动结果节选: ************************************************......

晨猫 ⋅ 今天 ⋅ 0

组合数学 1-2000 中,能被6或10整除的数的个数

1--2000 中,能被6或10整除的数的个数 利用集合的性质 能被6整除的个数 2000/6 = 333 能被10整除的个数 2000/10 = 200 能被6和10整除的个数 2000/30 = 66 能被6或10整除的个数 333+200-66 =...

阿豪boy ⋅ 今天 ⋅ 0

一篇文章学懂Shell脚本

Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合。 Shell可以直接使用在win/Unix/Linux上面,并且可以调用...

Jake_xun ⋅ 今天 ⋅ 0

大数据工程师需要精通算法吗,要达到一个什么程度呢?

机器学习是人工智能的一个重要分支,而机器学习下最重要的就是算法,本文讲述归纳了入门级的几个机器学习算法,加大数据学习群:716581014一起加入AI技术大本营。 1、监督学习算法 这个算法由...

董黎明 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部