【发布时间】:2015-02-27 22:39:48
【问题描述】:
事实证明,通过 Restlet 提供静态文件比想象的要难。我怀疑与上下文初始化有关的一些深层问题,但我可能是错的。基本上,我还不能通过Directory 获得任何实际内容,尽管所有路由和所有经典的restlet 都工作得很好。
核心问题看起来像它在日志消息中显示的那样:
WARNING: No client dispatcher is available on the context. Can't get the target URI: war:///
我尝试了许多不同的基本 URL,但似乎都没有任何作用。当我调试时,果然getClientDispatcher() 返回null。
当我(错误地)修改 Spring 初始化以使用原始上下文而不是子上下文时,我没有收到此警告,并且显示了目录列表,但它还显示了大约七条 SEVERE 消息,说明这是一个安全风险。
我的 Spring XML 如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="trackerComponent" class="org.restlet.ext.spring.SpringComponent">
<property name="defaultTarget" ref="trackerApplication" />
</bean>
<bean id="trackerComponentChildContext" class="org.restlet.Context">
<lookup-method name="createChildContext" bean="trackerComponent.context" />
</bean>
<bean id="trackerApplication" class="ca.uhnresearch.pughlab.tracker.application.TrackerApplication">
<property name="root" ref="router" />
</bean>
<!-- Define the router -->
<bean name="router" class="org.restlet.ext.spring.SpringRouter">
<constructor-arg ref="trackerComponentChildContext" />
<property name="attachments">
<map>
<entry key="/" value-ref="staticsDirectory" />
</map>
</property>
</bean>
<bean id="staticsDirectory" class="ca.uhnresearch.pughlab.tracker.resource.SpringDirectory">
<constructor-arg ref="router" />
<constructor-arg value="war:///" />
<property name="listingAllowed" value="true" />
</bean>
...
我的 SpringDirectory 类只是一个包装器,用于提供来自父级 Router 的 Context,就像其他 Spring 助手一样,它似乎工作得很好:传递相同的上下文 - 而没有一个子级上下文有一个有效的getClientDispatcher()。
如果需要,这里是web.xml 的一些相关部分。我不完全确定为什么我需要添加 FILE 以允许客户端访问(毕竟我想通过 Web 容器提供服务)但我也尝试使用 file: URL,这对我没有任何影响可以看到,除了我不得不在不寻常的地方添加额外的设置。
<servlet>
<servlet-name>tracker</servlet-name>
<servlet-class>org.restlet.ext.spring.SpringServerServlet</servlet-class>
<init-param>
<param-name>org.restlet.clients</param-name>
<param-value>HTTP HTTPS FILE</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>tracker</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
我非常感谢您提供这方面的建议——实际上,我在尝试显示 index.html 上花费的时间比我在所有 Restlets 上的总和还要多,因此非常欢迎任何想法或建议。
更新
Thierry 的回复很有帮助,但我仍有一些问题,仍然无法提供静态文件。唯一的变化是我没有test.CustomSpringServerServlet——而且我并不完全清楚我需要一个,因为默认情况下似乎接受了额外的init-param。
当使用 Jetty JAR 文件 (mvn jetty:run-war) 运行时,我现在得到一个堆栈回溯:
WARNING: Exception or error caught in status service
java.lang.NoSuchMethodError: org.restlet.Context.getClientDispatcher()Lorg/restlet/Restlet;
at ca.uhnresearch.pughlab.tracker.restlets.DirectoryFactoryBean$1.getContext(DirectoryFactoryBean.java:16)
at org.restlet.Restlet.handle(Restlet.java:220)
at org.restlet.resource.Finder.handle(Finder.java:449)
at org.restlet.resource.Directory.handle(Directory.java:245)
at org.restlet.routing.Filter.doHandle(Filter.java:156)
...
这个堆栈回溯很容易是我更新的结果——我现在使用的是 Restlets 2.3.1 和 Spring 3.1.4,因为它与之前的警告非常相似。
奇怪的是,我没有从mvn jetty:run 那里得到这个,自相矛盾的是,它现在在顶层提供目录列表,但仍然拒绝提供任何文件。这样就确认了 WAR 协议能够访问某些东西。 war:// 协议没有高度记录,所以我猜测它只是从战争内容中服务,而且它当然还不能做到这一点。
我仍然希望file:// 协议能够正常工作——老实说,任何静态文件的服务都很棒,我已经不在乎了。但是,尝试仍然会导致错误:
WARNING: The protocol used by this request is not declared in the list of client connectors. (FILE). In case you are using an instance of the Component class, check its "clients" property.
我不太明白,因为它在 web.xml 的客户列表中,而且没有其他任何地方可以说明。
事实证明这已经够难了,我觉得也许我应该整理一个 Github 存储库供人们使用。
【问题讨论】:
标签: spring file static restlet