【问题标题】:Spring themes and application contextSpring 主题和应用程序上下文
【发布时间】:2013-12-09 22:06:26
【问题描述】:

我正在向现有 Spring 3.0.5 项目添加主题。我正在使用 CookieThemeResolver 。虽然我可以加载一个主题,但它不是指定的默认值(在 theResolver bean 中指定),并且 themeChangeInterceptor 似乎没有工作。

我知道我添加的三个主题配置是有效的,因为我将它们(和 CSS 资源)添加到了 spring MVC-basic 项目中。他们工作得很好。此外,Spring mvc-basic 项目不需要 web.xml 中的 ContextLoaderListener,就像我的项目一样。

最初我没有应用程序上下文(我不需要)但是将主题配置添加到我的项目会导致包含 spring:theme 标记的页面在该页面上出错并抱怨 java.lang.IllegalStateException: No找到 WebApplicationContext:没有在 spring:theme 标签上注册 ContextLoaderListener。所以我添加了一个 ContextLoaderListener 并将 spring mvc-basic 应用程序中不存在的所有内容放入 application-context.xml。

由于 Spring mvc-basic 项目中相同的 spring 标记和主题配置不会发生此错误(并且 mvc 项目没有侦听器或上下文参数属性),因此我必须得出结论,其中一个元素在什么现在是我的应用程序上下文是问题所在。

当我的应用程序在下面的配置中运行时,它会加载 theme.properties 文件(该文件与 theme-day.properties 和 theme-night.properties 一起位于类路径中)。发出 ?theme=day 或 ?theme=night 请求时没有设置 cookie。但是,即使我的日志设置被跟踪,它也不会抛出任何错误。

希望有人能够指出 WTF 正在发生。我已将配置配对到最低限度。一个或多个剩余元素是问题的原因。如果您有任何问题,请提出。

我尝试将所有内容都移到应用程序上下文中,但这并没有解决问题。我试图删除元素,但这里发布的元素是最低限度的,不会破坏整个应用程序。重新检查了我的 jar 中的正确版本和相同版本的 POM 文件。

更多信息:由于语言环境解析器遵循相同的模式(不需要标签),我从 JSP 中删除了所有主题配置和标签,并将我的所有声明移回 servlet.xml 并终止了 ContextLoaderListener 及其配置。结果与主题相似,因为 spring 默认(又名浏览器区域设置的默认设置)可以工作,但无法设置 cookie,并且与区域设置功能相关的其他任何内容似乎都没有工作。将所有的回退到 application.xml 并将 ContextLoaderListener 放回具有相同的结果。所以至少这是一致的,由于我的配置的某些部分,语言环境和主题都被破坏了。此外,对 ContextLoaderListener 的需求不是主题标签的直接功能,而是其他元素之一的副作用。

更新 2 我升级到 3.0.6,在跟踪级别运行时发现以下项目。

    DEBUG ResourceBundleThemeSource,"http-bio-8080"-exec-5: 109 - Theme created: name 'theme',basename [theme]

此行显示在每个视图渲染之前。它暗示(对我而言)ResourceBundleThemeSource 仅在其默认设置下运行。

    TRACE DefaultListableBeanFactory,Thread-7:201 Ignoring Constructor [public.org.springframework.web.servlet.handler.MappedInterceptor(java.lang.String[],org.springframework.web.context.request.WebRequestInterceptor)] of bean 'org.springframework.web.servlet.handler.MappedInterceptor#1' :org.springframework.beans.factoryUnsatisfiedDependancyException: Error creating bean with name 'org.springframework.web.servlet.handler.MappedInterceptor#1':Unsatisfied dependnacy expressed through contructor argument with index 1 of type [org.springframework.web.context.request.WebRequestInterceptor]: Could not convert constructor argument value of type [org.springframework.web.servlet.theme.ThemeChangeInterceptor] to required type [org.springframeworkweb.context.request.WebRequestInterceptor]: Failed to convert value of type 'org.springframework.web.servlet.theme.ThemeChangeInterceptor' to required type 'org.springframeworkweb.context.request.WebRequestInterceptor';nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.servlet.theme.ThemeChangeInterceptor] to required type [org.springframeworkweb.context.request.WebRequestInterceptor]: no matching editors or conversion strategy found

应用程序初始化时出现此错误。由于完全相同的配置在 MVC-Basic 项目中有效,我不确定为什么会发生这种情况。我明白它在说什么我只是看不出有什么问题。

设置如下

servlet-context.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:http-conf="http://cxf.apache.org/transports/http/configuration"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd">

<!-- Scans the classpath of this application for @Components to deploy as beans -->
<context:component-scan base-package="org.myproject.test" />

<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />

<!-- Configures Handler Interceptors -->    
<mvc:interceptors>
    <!-- Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de -->
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />

    <bean id="themeChangeInterceptor" class="org.springframework.web.servlet.theme.ThemeChangeInterceptor">
        <property name="paramName" value="theme" />
    </bean>
</mvc:interceptors>

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />

<!-- Saves a locale change using a cookie -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />

<!-- Application Message Bundle -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="/WEB-INF/messages/messages" />
    <property name="cacheSeconds" value="0" />
</bean>

<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>
   <!-- Theme source and Resolver definition -->

<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource">
    <property name="basenamePrefix" value="theme-" />
</bean>

<bean id="themeResolver" class="org.springframework.web.servlet.theme.CookieThemeResolver">
    <property name="defaultThemeName" value="day" />
</bean>

   </beans>

应用程序上下文.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"
xsi:schemaLocation="http://www.springframework.org/schema/mvc       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <!--       Read the config.properties file-->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:config.properties</value>
        </list>
    </property>
</bean>

<bean id="myService" class="com.stuff.generated.service1">
    <constructor-arg value="${service1UrlPrefix}?wsdl"/>
</bean>

<bean id="myServiceFactory" factory-bean="myService1" factory-method="getServicePort"/>

<bean id="myOtherService" class="com.stuff.generated.service2">
    <constructor-arg value="${service2UrlPrefix}?wsdl"/>
</bean>
<bean id="myOtherServiceFactory" factory-bean="myService2" factory-method="getServicePort2"/>  

  <!-- assembles some variables used widely which are autowired into other classes
   contains getter and setters and some code running in afterPropertiesSet() method -->
   <bean id="myStartVars" class="com.myClass.myStartVars"/> 

  <bean id="autowiredAnnotationBeanPostProcessor" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

web.xml

     <?xml version="1.0" encoding="UTF-8"?>
     <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Reads request input using UTF-8 encoding -->
<filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Handles all requests into the application -->
<servlet>
    <servlet-name>myTest Servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value> /WEB-INF/spring/servlet-context.xml </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>myTest Servlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/application-context.xml</param-value>
</context-param>

【问题讨论】:

  • 我不确定您所说的“我没有应用程序上下文(我不需要)”是什么意思,因为每个 Spring 应用程序都有一个应用程序上下文。仅供参考,&lt;context-param&gt; 元素适用于整个 Web 应用程序,而 contextConfigLocation 尤其适用于一个 servlet。我首先将这些配置文件合并为一个(不管是哪个),以确保没有奇怪的交互。另外,您是否真的发布了错误发生时您正在使用的真正的最小配置文件? XML 似乎无效。
  • 从 spring 示例中可以看出,它可能有一个只有 servlet 上下文的应用程序。然后 Spring 将其推高。它在文档中。最初它们在一个文件 servlet-conext.xml 中,我不得不出于未知原因创建一个应用程序上下文。我说未知是因为我能够将主题标签和配置添加到 spring mvc basic 中,并且它只在 servlet-context 中运行良好。是的,这些是我剪切和粘贴的真实文件。堆栈溢出解释器弄乱了 cmets 的外观,但看起来所有部分都在那里
  • 我的错误,XML 是有效的。接下来我要做的是在 Spring 代码的各个点放置断点,例如 ResourceBundleThemeSource 和 CookieThemeResolver 的构造函数,您想要了解其行为的那些类中的方法等。然后,在调试器,看看到底发生了什么——这些类是如何被实例化的,等等。或者,一种不同的方法是更多地剥离应用程序(你可以这样做),以便它除了测试主题或语言环境之外什么都不做。完成这项工作后,逐个添加功能。

标签: java spring spring-mvc themes


【解决方案1】:

解决这个问题。

事实证明,语言环境和主题系统无法应用于 WEB-INF 之外的应用程序元素。

因此,将尝试使用语言环境和主题的 spring 标记放在应用程序中“松散”的 JSP 上将会失败。

因此,在上述代码的情况下,我将所有内容移回 servlet-context.xml。将我的标签从 index.jsp 文件(位于 web-app 的根目录)中取出并将所有内容移回进入意见。现在一切正常。

我希望这对某人有所帮助。如果你有不同的发现请在这里发帖

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-24
    • 2016-05-20
    • 1970-01-01
    • 2019-08-13
    • 2014-02-23
    • 1970-01-01
    • 2010-09-12
    • 2016-08-27
    相关资源
    最近更新 更多