使用JRebel 6.0.0进行部署时,在Spring 4.1.2更新后找不到资源

时间:2014-11-12 21:26:37

标签: java spring spring-mvc jrebel

Spring 4.1.2(4.0.8和3.2.12)包含一个安全修正错误SPR-12354,它阻止ResourceHttpRequestHandler<mvc:resources>后面的东西)从外部加载文件资源文件夹。

另一方面:是JRebel(我使用它的默认配置)。接下来,JRebel做了一些魔术来加载资源而不是从wtp文件夹加载,而是直接形成&#34;源&#34;文件夹中。

因此,在从Spring 3.2.11升级到3.2.12(以及从4.0.7到4.0.8的其他类似应用程序)之后,弹簧ResourceHttpRequestHandler不再提供维护的&#34;资源文件#34;由JRebel提供。而是传递404.原因是Spring将配置的资源文件夹的绝对文件路径与将要传递的文件的绝对文件路径进行比较。如果ResourceHttpRequestHandler认为该文件在配置的资源文件夹之外,则它假定用于选择该文件的URL是恶意的。因此,找不到ResourceHttpRequestHandler和404资源的响应。

我希望JRebel可以配置为不维护&#34; js,png和css文件,但我不知道如何。这就是问题:如何配置Spring MVC应用程序(v 4.0.8)仍然使用ResourceHttpRequestHandler提供资源的JRebel?

(我希望在升级到Spring 4.1.2,4.0.8或3.2.12之后,几乎每个JRebel用户都会遇到此问题。)

(不要误解我的意思,这不是一个如何操纵Spring不要检查文件是否在配置资源文件夹之外的问题。我已经看过源代码和观察到的行为是Bug修复的作者所期望的行为。 - 这个问题是关于配置JRebel)

3 个答案:

答案 0 :(得分:5)

感谢您提供非常好的问题说明!

看起来这个Spring更改引入了与JRebel的不兼容性。我来自JRebel团队,并确保这一点得到解决!

作为一种解决方法,您可以在rebel.xml <exclude>元素中使用<web>标记告诉JRebel不要触摸这些特定文件。以下是有关如何配置http://manuals.zeroturnaround.com/jrebel/standalone/config.html#exclude

的详细信息

其他更简单的解决方法就是完全删除<web>元素。

答案 1 :(得分:3)

基于smartman的anwser,我按如下方式配置了rebel.xml:

   <classpath>
         <dir name="${rebel.workspace.path}/myproject/target/classes">
         </dir>
         <dir name="${rebel.workspace.path}/myproject/target/test-classes">
         </dir>
   </classpath>

   <web>
         <link target="/">
                <dir name="${rebel.workspace.path}/myproject/src/main/webapp">
                       <exclude name="resources/**"/>
                </dir>
         </link>
   </web>

这将排除所有资源,但至少会更新视图(jsp-和tag-files)。但是当我做很多前端开发时,我需要同时更改控制器,视图和样式,这种配置是无用的,我必须一起关闭jrebel。

答案 2 :(得分:2)

问题已在JRebel中修复(我无法使用当前的JRebel 6.1.1重现它) - 我想它已经修复自6.0.2 (12月23日) 2014)

  

修复了Spring ResourceHttpRequestHandler无法在webroot之外提供资源的问题。

(JRebel Changelog https://zeroturnaround.com/software/jrebel/download/changelog/6-x/


对于有兴趣的人如何解决它:

我只能猜测,因为它很奇怪。 Spring 4.1.6(即我用于测试的版本)类org.springframework.web.servlet.resource.PathResourceResolver的方法为checkResource(Resource resource, Resource location)

protected boolean checkResource(Resource resource, Resource location) throws IOException {
    if (isResourceUnderLocation(resource, location)) {
        return true;
    }
    if (getAllowedLocations() != null) {
        for (Resource current : getAllowedLocations()) {
            if (isResourceUnderLocation(resource, current)) {
                return true;
            }
        }
    }
    return false;
}

第一个ifisResourceUnderLocation...是检查请求是否正在访问已配置资源文件夹之外的资源的方法

isResourceUnderLocation(Resource resource, Resource location) {
    ...
    resourcePath = ((ServletContextResource) resource).getPath();
    locationPath = StringUtils.cleanPath(((ServletContextResource) location).getPath());
    ...
    if (!resourcePath.startsWith(locationPath)) {
        return false;
    }
    ...
 }

当我使用调试器检查发生了什么时,当JRebel处于活动状态时,会发生一些奇怪的事情:当JVM命中行if (isResourceUnderLocation(resource, location)) {时,方法isResourceUnderLocation不会被调用!

所以我得出结论,JRebel做了一些字节码操作,以防止检查(以及整个isResourceUnderLocation方法)被执行。