El contexto de Spring ofrece características de acceso a bajo de nivel de recursos más alla de las ofrecidas por la clase java.net.URL
estándar de Java.
Interface
Toda la gestión de recursos recae en la interface Resource
, que extiende InputStreamSource
, y actúa como un wrapper de java.net.URL
:
public interface InputStreamSource { InputStream getInputStream() throws IOException; } public interface Resource extends InputStreamSource { boolean exists(); boolean isOpen(); URL getURL() throws IOException; File getFile() throws IOException; Resource createRelative(String relativePath) throws IOException; String getFilename(); String getDescription(); }
El método getInputStream
es el que se encarga de localizar y dar acceso físico a los recursos, aunque es responsabilidad de la aplicación cerrar el stream una vez haya terminado de operar con él.
La disponibilidad de los métodos getURL
y getFile
dependen del tipo y ubicación del recurso concreto solicitado. Por ejemplo, una petición HTTP a un servidor remoto normalmente no se puede resolver como una instancia de java.io.File
.
Spring recomienda utilizar la interface Resource
en las aplicaciones, como cualquier otra librería de utilidades, aunque ello suponga añadir una dependencia por código con Spring.
Implementaciones
Spring proporciona varias implementaciones para la interface Resource
que pueden instanciarse directamente para acceder a un recurso:
– UrlResource
: La implementación genérica que funciona como java.net.URL
. Admite una URL válida como parámetro con cualquier tipo de prefijo habitual: «file:», «http:», «ftp:», …
– ClassPathResource
: Una implementación específica para acceder a recursos que se encuentran dentro del classpath.
– FileSystemResource
: Una implementación específica para acceder a recursos dentro de un sistema de ficheros.
– ServletContextResource
: Una implementación específica para acceder a recursos de una aplicación web relativos a su directorio de despliegue.
– InputStreamResource
: Una implementación específica para tratar con recursos que se encuentren ya abiertos y accesibles a través de InputStream
.
– ByteArrayResource
: Una implementación específica para acceder a un array de bytes que se encuentre ya disponible.
Contexto
El contexto implementa el método getResource
que permite acceder a los recursos. El tipo de objeto concreto devuelto por este método será una de las implementaciones indicadas en el apartado anterior en función de la URL dada:
Resource resource = context.getResource("http://www.inmensia.com");
Resource resource = context.getResource("file://c:/fichero.txt");
Resource resource = context.getResource("classpath://jdbc.properties");
De la forma acostumbrada, Spring proporciona una interface Aware que cualquier bean que quiera acceder a ese aspecto del contexto puede implementar:
public class Cargador implements ResourceLoaderAware { private ResourceLoader resourceLoader; public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } public Resource cargar(String recurso) { return this.resourceLoader.getResource(recurso); } )
Aunque por supuesto se puede utilizar cualquier otro medio de inyección de dependencias de Spring para obtener acceso al cargador de recursos, como la anotación @Autowired
por ejemplo.
Carga por Dependencia
Si un recurso sólo se va cargar de forma puntual en un bean, no hace falta tener acceso a la interface, basta con inyectar el recurso directamente en una propiedad del bean.
public class Cargador { private Resource fichero; public void setFichero(Resource fichero) { this.fichero = fichero; } ...
<bean id="cargador" class="com.empresa.Cargador"> <property name="fichero" value="classpath:fichero.txt"/> </bean>
Wildcards
Spring deja también especificar wildcards (caracteres comodines), pero sólo tiene sentido en algunos casos concretos.
Por ejemplo, usando classpath*:
cuando se quiere instanciar un ApplicationContext
a partir de varios ficheros de configuración ubicados en el classpath, y evitar así tener que especificarlos todos uno a uno:
classpath*:applicationContext.xml
O usando **
cuando se quiere buscar en subdirectorios a partir de un raíz dada:
classpath:com/empresa/proyecto/**/fichero.txt
No todas las combinaciones son válidas, ni dan el resultado esperado, además de ciertos problemas de compatibilidad. Lo mejor es revisar la documentación oficial en cada caso.