我正在使用 Spring MVC 3 开发一个 webapp,并让 DispatcherServlet
像这样(web.xml)捕获所有对“/”的请求:
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
现在这可以像宣传的那样工作,但是我该如何处理静态内容?以前,在使用 RESTful URL 之前,我会捕获所有 *.html 例如并将其发送到 DispatcherServlet
,但现在它是一个不同的球类游戏。
我有一个 /static/ 文件夹,其中包括 /styles/、/js/、/images/ 等,我想从 DispatcherServlet
中排除 /static/*。
现在,当我这样做时,我可以让静态资源正常工作:
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/</url-pattern>
</servlet-mapping>
但我希望它有很好的 URL(我使用 Spring MVC 3 的重点)而不是登录页面是 www.domain.com/app/
我也不想要与 tomcat 或任何其他 servlet 容器耦合的解决方案,因为这是(相对)低流量,我不需要前端的网络服务器(如 apache httpd)。
有一个干净的解决方案吗?
由于我在这个问题上花了很多时间,我想我会分享我的解决方案。从 spring 3.0.4 开始,有一个名为 <mvc:resources/>
的配置参数(有关 reference documentation website 的更多信息)可用于提供静态资源,同时仍使用站点根目录上的 DispatchServlet。
为了使用它,请使用如下所示的目录结构:
src/
springmvc/
web/
MyController.java
WebContent/
resources/
img/
image.jpg
WEB-INF/
jsp/
index.jsp
web.xml
springmvc-servlet.xml
文件的内容应如下所示:
src/springmvc/web/HelloWorldController.java:
package springmvc.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloWorldController {
@RequestMapping(value="/")
public String index() {
return "index";
}
}
网页内容/WEB-INF/web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
网页内容/WEB-INF/springmvc-servlet.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- not strictly necessary for this example, but still useful, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-controller for more information -->
<context:component-scan base-package="springmvc.web" />
<!-- the mvc resources tag does the magic -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- also add the following beans to get rid of some exceptions -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>
<!-- JSTL resolver -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
网页内容/jsp/index.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<h1>Page with image</h1>
<!-- use c:url to get the correct absolute path -->
<img src="<c:url value="/resources/img/image.jpg" />" />
这个问题在 spring 3.0.4.RELEASE 中得到解决,您可以在 spring 调度程序配置文件中使用 <mvc:resources mapping="..." location="..."/>
配置元素。
在 Spring 3.0.x 中,将以下内容添加到您的 servlet-config.xml(在 web.xml 中配置为 contextConfigLocation 的文件。您还需要添加 mvc 命名空间,但如果您不知道如何添加,只需 Google 即可!
这对我行得通
<mvc:default-servlet-handler/>
如果我正确理解您的问题,我想我已经找到了解决您问题的方法:
我遇到了同样的问题,原始输出显示没有找到 css 样式、javascripts 或 jquery 文件。
我刚刚将映射添加到“默认”servlet。以下内容已添加到 web.xml 文件中:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
这应该过滤掉来自 DispatcherRequest 对象的 javascript 和 css 文件请求。
同样,不确定这是否是您所追求的,但它对我有用。我认为“默认”是 JBoss 中默认 servlet 的名称。不太确定其他服务器是什么。
<servlet-mapping>
中添加所有 <url-pattern>
标签
还有另一个具有 excellent solution 的堆栈溢出帖子。
它似乎不是 Tomcat 特定的,很简单,而且效果很好。我已经使用 spring mvc 3.1 尝试了这篇文章中的几个解决方案,但是在获取我的动态内容时遇到了问题。
简而言之,它说添加一个像这样的 servlet 映射:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>
我使用 tukey 的 urlrewritefilter 找到了解决方法。如果您有更好的答案,请随时提供!
在 web.xml 中:
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
在 urlrewrite.xml 中:
<urlrewrite default-match-type="wildcard">
<rule>
<from>/</from>
<to>/app/</to>
</rule>
<rule match-type="regex">
<from>^([^\.]+)$</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/$1</to>
</outbound-rule>
这意味着任何带有 '.' 的 uri其中(例如 style.css )不会被重写。
<mvc:resources/>
。
我刚刚在 Spring MVC 3.0 中解决了这个问题,我最初选择了 UrlRewriteFilter 选项。但是我对这个解决方案并不满意,因为它“感觉不对”(我不是唯一一个 - 请参阅上面的 Spring 论坛链接,其中多次出现“hack”一词)。
所以我想出了一个与上面的“Unknown (Google)”类似的解决方案,但是借用了从 /static/ 提供所有静态内容的想法(取自 Pet Store 应用程序的 Spring Roo 版本)。 “默认” servlet 对我不起作用,但 Spring Webflow ResourceServlet 起作用(也取自 Spring Roo 生成的应用程序)。
Web.xml:
<servlet>
<servlet-name>mainDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>Resource Servlet</servlet-name>
<servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mainDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Resource Servlet</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
我对 JSP 所做的唯一更改是将 /static/ 路径添加到 CSS、JS 和图像的 URL。例如“${pageContext.request.contextPath}/static/css/screen.css”。
对于 Maven 用户,“org.springframework.js.resource.ResourceServlet”的依赖项是:
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>org.springframework.js</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
我自己对这个问题的经验如下。大多数与 Spring 相关的网页和书籍似乎都建议最合适的语法如下。
<mvc:resources mapping="/resources/**" location="/resources/" />
上述语法建议您可以将静态资源(CSS、JavaScript、图像)放在应用程序根目录中名为“resources”的文件夹中,即 /webapp/resources/。
但是,根据我的经验(我使用的是 Eclipse 和 Tomcat 插件),唯一可行的方法是将资源文件夹放在 WEB_INF(或 META-INF)中。所以,我推荐的语法如下。
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
在您的 JSP(或类似)中,按如下方式引用资源。
<script type="text/javascript"
src="resources/my-javascript.js">
</script>
不用说,整个问题的出现只是因为我希望我的 Spring 调度程序 servlet(前端控制器)拦截一切,一切都是动态的,也就是说。所以我的 web.xml 中有以下内容。
<servlet>
<servlet-name>front-controller</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
<!-- spring automatically discovers /WEB-INF/<servlet-name>-servlet.xml -->
</servlet>
<servlet-mapping>
<servlet-name>front-controller</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
最后,由于我使用的是当前的最佳实践,我的前端控制器 servlet xml 中有以下内容(见上文)。
<mvc:annotation-driven/>
而且我在我的实际控制器实现中有以下内容,以确保我有一个默认方法来处理所有传入的请求。
@RequestMapping("/")
我遇到了同样的问题,发现 Joris 的回答非常有帮助。但另外我需要添加
<mvc:annotation-driven />
到 servlet 配置文件。没有该资源映射将无法工作,所有处理程序都将停止工作。
如果您想这样称呼它,则 URLRewrite 有点像“黑客”。归根结底,您是在重新发明轮子;因为已经有现有的解决方案。要记住的另一件事是 Http 服务器 = 静态内容 & 应用服务器 = 动态内容(这就是它们的设计方式)。通过将适当的职责委派给每台服务器,您可以最大限度地提高效率......但现在这可能只是性能关键环境中的一个问题,并且像 Tomcat 这样的东西很可能在大部分时间都可以很好地工作;但仍然需要牢记这一点。
我是这样解决的:
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
这适用于 Tomcat,当然还有 Jboss。但是最后我决定使用更便携的解决方案 Spring provides(如 rozky 所述)。
我在spring mvc 3.0.x中使用了urlrewrite和基于注释的两种方法,发现基于注释的方法最合适,即
<annotation-driven />
<resources mapping="/resources/**" location="/resources/" />
在 urlrewrite 的情况下,必须定义大量规则,并且有时还会为 UrlRewriteFilter 获取类未找到异常,因为已经为其提供了依赖项。我发现这是由于传递依赖的存在而发生的,因此将再次增加一步,并且必须使用从 pom.xml 中排除该依赖
<exclusion></exclusion> tags.
因此,基于注释的方法将是不错的选择。
从 Spring 3 开始,所有资源都需要以不同的方式映射。您需要使用标签来指定资源的位置。
例子 :
<mvc:resources mapping="/resources/**" location="/resources/" />
通过这样做,您可以指示调度程序 servlet 查看目录资源以查找静态内容。
我解决这个问题的方法是把你的所有动作都加上一个特定的前缀,比如“web”或“service”,并配置所有带有该前缀的 url 都将被 DispatcherServlet 拦截。
我只是在tukey的urlrewritefilter(urlrewrite.xml)的spring默认规则(/**)前添加三个规则来解决问题
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
<urlrewrite default-match-type="wildcard">
<rule>
<from>/</from>
<to>/app/welcome</to>
</rule>
<rule>
<from>/scripts/**</from>
<to>/scripts/$1</to>
</rule>
<rule>
<from>/styles/**</from>
<to>/styles/$1</to>
</rule>
<rule>
<from>/images/**</from>
<to>/images/$1</to>
</rule>
<rule>
<from>/**</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
我知道有一些配置可以使用静态内容,但我的解决方案是我只是在你的 tomcat 中创建一个批量 web-application 文件夹。这个“批量网络应用程序”只提供所有静态内容而不提供应用程序。这是为您的实际 spring webapp 提供静态内容的轻松且简单的解决方案。
例如,我在我的 tomcat 上使用了两个 webapp 文件夹。
springapp:它只运行 spring web 应用程序,没有像 imgs、js 或 css 这样的静态内容。 (专用于 spring 应用程序。)资源:它只提供静态内容,没有 JSP、servlet 或任何类型的 java web 应用程序。 (专用于静态内容)
如果我想使用 javascript,我只需为我的 javascript 文件添加 URI。
EX> /resources/path/to/js/myjavascript.js
对于静态图像,我使用相同的方法。
EX> /resources/path/to/img/myimg.jpg
最后,我在我的 tomcat 上放置了“security-constraint”以阻止对实际目录的访问。我将“nobody”用户滚动设置为约束,以便当人们尝试访问静态内容路径时页面生成“403 禁止错误”。
到目前为止,它对我来说效果很好。我还注意到许多流行的网站,如 Amazon、Twitter 和 Facebook,它们使用不同的 URI 来提供静态内容。要找出这一点,只需右键单击任何静态内容并检查其 URI。
在我的情况下,这做了真正的工作
在 web.xml 中:
...
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
<url-pattern>/css/*</url-pattern>
<url-pattern>/javascripts/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring-mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
...
对于基于 java 的 spring 配置,您可以使用以下
使用 ResourceHandlerRegistry 存储资源处理程序的注册以提供静态资源。
更多信息@WebMvcConfigurerAdapter,它定义了回调方法以自定义通过 @EnableWebMvc 启用的 Spring MVC 的基于 Java 的配置。
@EnableWebMvc
@Configurable
@ComponentScan("package.to.scan")
public class WebConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static_resource_path/*.jpg").addResourceLocations("server_destination_path");
}
在遇到并经历了这里描述的相同决策过程之后,我决定采用效果很好的 ResourceServlet 提案。
请注意,您可以在此处获得有关如何在 maven 构建过程中使用 webflow 的更多信息:http://static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch01s05.html
如果您使用标准 Maven 中央存储库,则工件是(与上面提到的 springsource 包相反):
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-js</artifactId>
<version>2.0.9.RELEASE</version>
</dependency>
这可以通过至少三种方式实现。
解决方案:
将 html 公开为资源文件
指示 JspServlet 也处理 *.html 请求
编写您自己的 servlet(或将请求传递给另一个现有的 servlet 到 *.html)。
有关如何实现此目的的完整代码示例,请参阅我在另一篇文章中的回答:How to map requests to HTML file in Spring MVC?
问题在于 URLPattern
将 servlet 映射上的 URL 模式从“/”更改为“/*”
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:default-servlet-handler/>
</beans>
如果您想使用基于注释的配置,请使用以下代码
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
将 css 、js 等静态内容放在以下路径中
resources
->static
->css
->js
(or)
resources
->public
->css
->js