Webx框架:ResourceLoader

Spring中的ResourceLoader

获取Resource的方法有两种。一种是通过ResourceLoader载入资源,另外一种是通过注入。通过ResourceLoader载入资源的方法如下:

public class Test implements ResourceLoaderAware {
  private ResourceLoader resourceLoader;

  public void setResourceLoader(ResourceLoader v){...}

  public void test(){
    Resource resource = resourceLoader.getResource("myfile.xml");
  }
}

通过注入载入资源。

// 首先一个普通的类,注意它有一个方法参数类型为URL。
public class MyBean {
  public void setLocation(URL resource){}
}

Bean的声明如下。它将一个字符串注入到MyBean中,但是MyBean只接受URL类型,不接受字符串。这时Spring就会将字符串通过ResourceLoading进行解析得到URL,再将URL注入到Bean中。

<bean id="mybean" class="MyBean">
  <property name="location" value="myfile.xml"/>
</bean>

稍作改动还可以载入一组资源:

public class MyBean{
  public void setLocations(URL[] locations){}
}
<bean id="mybean" class="MyBean">
  <property name="locations" value="WEB-INF/webx-*.xml"/>
</bean>

从代码中我们可以看到我们只是指定了文件的相对路径,那么到底相对于哪个目录呢?这跟Spring的ApplicationContext类型有关系。我们知道Spring有多种ApplicationContext,不同的ApplicationContext载入资源时行为是不一样的。ClassPathXmlApplicationContext会从Classpath中载入资源,FileSystemXmlApplicationContext会从文件系统中载入资源、XmlWebApplicationContext会从WEB-INF中载入资源。另外它们都支持从classpath载入,请看下面的例子,下面几个都可以作为文件名交给ResourceLoader进行载入。

classpath:myFile.xml
classpath*:/META-INF/my*.xml

Spring的ResourceLoader缺点有以下几个: * 一次只能指定一个ApplicationContext,无法从多个位置载入资源。 * 每次都要指定资源的绝对路径,移植性不高。 * 没有扩展性,因为只能从文件中载入,如果想从数据库载入就很难做到。

Webx中的ResourceLoading

Webx改进了Spring在资源载入方面的不足,引入了ResourceLoading服务。它兼容Spring中ResourceLoader的所有功能,同时增加了很多新的特性。

ResourceLoading用于统一管理资源,便于资源的载入。资源可以存放在多个地方,可以是文件系统,可以是classpath,也可以是jar包。每种资源位置访问的方式、遍历文件的方式都不一样,这样在访问不同类型的资源时就会很麻烦,而且代码的移植性也不好。ResourceLoading服务就是将这些不同位置的资源统一成Resource接口。它的定义如下:

public interface Resource {
  InputStream getInputStream();
  URL getURL();
  File getFile();
  boolean exists();
}

ResourceLoading服务的配置在webx.xml文件中进行。通过resource-loading标签就可以实现对资源的统一管理。

下面介绍resource-loading标签中能包含的子标签。

定义新资源。需要告诉框架资源的名称是什么,文件在哪个位置。下面这个例子表示建立一个文件夹,文件夹中的内容和java的安装目录一致。

<resource pattern="/jdk">
<res-loaders:file-loader basedir="${java.home}" />
</resource>

注入资源的时候只要以jdk目录为开头即可,请看下面的例子。

<property name="location" value="/jdk/lib/tools.jar" />

资源别名。有时候资源名会暴露具体的实现,造成移植性低。比如一个资源名为/WEB-INF/webx.xml,很明显它就是从WEB-INF目录中加载的,如果有一天把webx.xml移动到classpath中,那么这个资源名是很不合理的。所以需要把/WEB-INF/webx.xml进行重命名,请看下面的例子。

<resource-alias pattern="/myapp/conf" name="/webroot/WEB-INF" />
<resource pattern="/webroot" internal="true">
<res-loaders:webapp-loader />
</resource>

载入资源就可以这样载入:

<property name="location" value="/myapp/conf/webx.xml" />

第二行代码中出现了internal属性,它的值为true。表示这个资源只能在webx.xml内部使用,不能在spring配置文件中使用。

重定向资源。和资源别名类似,区别在于可以指定res-loader。请看下面的例子,它将template目录中的cms子目录重定向到另外一个目录中,而其他的目录不会受到影响。

<resource-alias pattern="/templates" name="/webroot/templates" />
<resource pattern="/templates/cms">
<res-loaders:file-loader basedir="${cms_root}" />
</resource>

在应用程序中,开发人员无法感知到某个资源被重定向,因此耦合度更低,修改方便。

pattern属性。在resource-aliasresource标签中都需要指定pattern属性。pattern可以包含绝对路径和相对路径,绝对路径一定是以/开头的,而相对路径则相反。下面请看几个例子: *
/aaa/bbb能匹配/aaa/bbb/ccc,不能匹配/xxx/aaa/bbb/ccc *
aaa/bbb能匹配/aaa/bbb/ccc,也能匹配/xxx/aaa/bbb/ccc

在pattern中还可以加入通匹配符号。*表示任意一个目录,**表示任意多个目录,?表示一个可有可无的字符。通匹配的内容会按照顺序分别赋值给$1$2等变量,下面请看例子。

<resource-alias pattern="/myapp/conf/**/*.xml" name="/webroot/WEB-INF/$1/$2.xml" />

从多个位置加载资源。有时候配置文件分散在多个文件夹中,但是我们要将这几个文件夹合并在一个资源目录下,那么代码可以这样写:

<resource pattern="/myapp/conf">
<res-loaders:super-loader name="/webroot/WEB-INF" />
<res-loaders:super-loader name="/classpath" />
</resource>

内容过滤。在载入资源的时候还可以对资源文件的内容进行加工。比如下面的例子就是将所有的xml文件转换成xslt。

<resource-filters pattern="test-*.xml">
<res-filters:xslt-filter xslt="/stylesheet.for.test/test.xsl" saveTo="/tempdir" />
</resource-filters>

上面例子中的xslt和saveTo属性也是webx资源pattern

ResourceLoadingService对象。它能提供一些Spring没有的功能。 获取资源:

Resource resource = resourceLoadingService.getResource("/myapp/conf/myFile.xml");
Resource resource = resourceLoadingService.getResource("/myapp/conf/myFile.xml",
ResourceLoadingService.FOR_CREATE);

获取特定类型的资源:

// 取得资源文件
File file = resourceLoadingService.getResourceAsFile("/myapp/conf/myFile.xml");
// 取得资源 URL
URL url = resourceLoadingService.getResourceAsURL("/myapp/conf/myFile.xml");
// 取得资源输入流
InputStream stream = resourceLoadingService.getResourceAsStream("/myapp/conf/myFile.xml");

资源是否存在:

resourceLoadingService.exists("/myapp/conf/myFile.xml")

枚举资源:

String[] resourceNames = resourceLoadingService.list("/myapp/conf");
Resource[] resources = resourceLoadingService.listResources("/myapp/conf");

调试资源的加载过程:

ResourceTrace trace = resourceLoadingService.trace("/myapp/conf/webx.xml");
for (ResourceTraceElement element : trace) {
  System.out.println(element);
}

列出所有可用的pattern。

String[] patterns = resourceLoadingService.getPatterns(true);

在Web环境中ResourceLoadingService可以通过@Autowired注入到程序中。在非Web环境中,需要调用ResourceLoadingXmlApplicationContext对象。

ResourceLoader对象。它是ResourceLoading服务的核心。分为多种类型,有FileResourceLoaderWebappResourceLoader等。

FileResourceLoader负责从文件系统中加载资源。
<resource pattern="/my/virtual">
<res-loaders:file-loader />
</resource>
这样就会从当前配置文件的目录中加载资源。

指定文件系统位置。
<resource pattern="/my/virtual">
<res-loaders:file-loader basedir="${my.basedir}" />
</resource>

指定多个路径。通过path标签,可以指定相对路径和绝对路径。
<resource pattern="/my/virtual">
<res-loaders:file-loader basedir="...">
<res-loaders:path>relativePathToBasedir</res-loaders:path>
<res-loaders:path type="absolute">c:/absolutePath</res-loaders:path>
</res-loaders:file-loader>
</resource>

WebappResourceLoader负责从当前Web应用中加载资源。
<resource pattern="/my/virtual">
<res-loaders:webapp-loader />
</resource>

ClassPathResourceLoader负责从Classpath路径中载入资源。
<resource pattern="/my/virtual">
<res-loaders:classpath-loader />
</resource>

SuperResourceLoader负责从另外一个ResourceLoader中载入资源。
从/webroot/WEB-INF中加载资源。
<resource pattern="/my/virtual">
<res-loaders:super-loader basedir="/webroot/WEB-INF" />
</resource>

从父容器中载入资源。
<resource pattern="/my/virtual">
<res-loaders:super-loader />
</resource>

Spring容器有继承关系。上面这个例子载入资源时,如果无法从子容器中载入资源,就从父容器中载入。当然也可以改变加载顺序,先从父容器中加载,再从其他位置加载。

<resource pattern="...">
<res-loaders:super-loader />
<res-loaders:file-loader />
</resource>

所有的ResourceLoader都支持容错,比如SuperResourceLoader即使在没有父容器的情况下也不会报错。

时间: 2024-10-17 09:56:47

Webx框架:ResourceLoader的相关文章

Webx框架:RequestContext详解

RequestContext RequestContext可以看成request和response的合体.多个RequestContext还可以串起来,就像Filter链条一样.每个外层RequestContext都会在内层RequestContext的基础上增加功能.在设计模式中这叫装饰器. RequestContext种类有basic/buffered/lazy-commit/parser/rewrite/session/set-locale功能.后面还会具体介绍. 下面是配置方法: <se

Webx框架:Spring Schema 和 Spring Ext

webx诞生的原因是当时市面上没有好用的web框架.现在的Web框架有很多,然后它们背后的思想都是相似的,而且越来越趋同. Spring Schema 在传统的spring中,配置bean时需要手动去指定具体的实现类是什么,参数有哪些.这样开发者需要记住具体的实现类.参数名称.含义等,会带来很大的记忆负担.为了解决这个问题,SpringSchema出现了.它的解决办法是将所有的参数转换成标签.标签是可以通过XML Schema定义的.这样只需要记忆标签的名字即可.标签的名称一般都很短,因此减轻了

Webx框架:会话管理

在Servlet中,Session和Cookie是分开的.Session一般保存在内存中,当然也可以保存在数据库等其他地方.如果保存在内存中,对于服务集群来说就需要解决Session共享的问题.如果保存在数据库,就存在单点故障.性能差等问题. webx提供了会话框架,将session这样复杂的问题统一进行解决.在webx框架中,主张将cookie合并到session中,再通过规则,路由到cookie或者session中.cookie保存在客户端,session保存在服务端,它们的区别这里就不赘述

Webx框架自带的petstore

Webx框架:http://openwebx.org/ petstore:webx3/webx-sample/petstore/tags/3.0/petstore 编译之后:mvn jetty:run即可, 访问:http://localhost:8081/ Webx MVC(以webx3为基础) 1.webx3的入口点 <filter> <filter-name>webx</filter-name> <filter-class>com.alibaba.ci

我的WebX框架学习总结与心得分享

最近学习了webx框架, 利用博客园跟大家分享一下自己的学习心得; 周建旭 2014-08-21 网上关于webx的资料少的可怜, 怎么办?  这种情况下不用去求助别人求人只会耽误时间, 不用畏惧; 看文档写demo 就ok了; API是最好的资料, webx官方有个pdf的中文文档提供下载, 建议在学webx之前, 先整体浏览一遍文档以便于把握webx框架的大体脉络, 第一遍看的过程不必钻牛角尖 ; 然后结合淘宝官方Michael Zhou的Petstore(宠物商店)例子对比一下文档(那块不

Webx框架:依赖注入

Webx的依赖注入和Spring的依赖注入很像,仅仅是有一点点的差别. 注入的时候仅仅能让生命周期长的注入到生命周期短的对象中,比方requestScope对象注入到singleton时就会错误发生.可是对于一些特殊的对象,比方request.session.response它们的生命周期是requestScope,而它们能够注入到随意对象中.这是由于webx对这些对象进行了特殊的处理. 依赖注入有多种方式.能够通过Spring中的Autowired字段进行注入. @Autowired priv

Webx框架:Valve详解

Valve用于控制请求的执行流程.它采用责任链的设计模式(类似于struts的拦截器).valve的意思是阀,阀控制水流(网络请求)的走向. 自定义阀. public class MyValve implements Valve { public void invoke(PipelineContext pipelineContext) throws Exception { System.out.println("valve started."); pipelineContext.inv

Webx框架:Pipeline简介

Pipeline.它的含义就是管道,一个管道可以安装很多的阀门,可以有很多分支.它用于控制页面的处理流程.它需要定义在pipeline.xml文件中,该文件中的每个标签都是一个阀门.该文件中可以放一些简单的控制语句.在项目中,下面这样的管道配置就已经够用了. <services:pipeline xmlns="http://www.alibaba.com/schema/services/pipeline/valves"> <!-- 初始化 turbine rundat

Webx框架:Pipeline基本介绍

Pipeline. 它是管道的含义.一个管道阀门可以安装非常多.有许多可能的分支.它是用来控制页处理.它需要在被定义pipeline.xml文件.该文件是为每个阀的标签.该文件可以放一些简单的控制语句.在项目.这条管线有以下配置足够好. <services:pipeline xmlns="http://www.alibaba.com/schema/services/pipeline/valves"> <!-- 初始化 turbine rundata,并在 pipeli