【问题标题】:Servlet Dispatcher Issue when upgrading to spring 4.1 with xml config使用 xml 配置升级到 spring 4.1 时的 Servlet Dispatcher 问题
【发布时间】:2017-08-28 09:15:18
【问题描述】:

我在挠头。

我有一个使用基于 spring 3.2 xml 的配置的应用程序,我正在升级到 spring 4.X,最好是 4.3.7(这是为了简化事情,因为我实际上也在升级 hibernate 等)。当/如果我迁移到 4.0.6(小于 4.1)时,我设法复制了这个问题,一切正常。

我尝试了多个 4.1.X 和 4.3.X,但实际上我没有从 servlet 获得映射分辨率。

https://localhost:8443/oldApp/home

结果

2017-04-03 12:06:40,383 WARN {OLDAPP}[org.springframework.web.servlet.PageNotFound] - 在 DispatcherServlet 中找不到带有 URI [/oldApp/home] 的 HTTP 请求的映射,名称为“spring-” mvc' 2017-04-03 12:06:40,383 WARN {OLDAPP}[org.springframework.web.servlet.PageNotFound] - 在 DispatcherServlet 中找不到带有 URI [/oldApp/404] 的 HTTP 请求的映射,名称为“spring-mvc”

基本上,它会尝试去 /home 的映射但失败,根据配置被重定向到 404,并且 /404 的映射也失败了..

applicationContext-mvc.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:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc.xsd
                        http://www.springframework.org/schema/context 
                        http://www.springframework.org/schema/context/spring-context.xsd">          

        <mvc:annotation-driven/>

    <context:component-scan base-package="com.verification.migration.controller.*" />
    <!-- Static resources -->
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving 
        up static resources in the ${webappRoot}/resources directory -->
    <mvc:resources mapping="/resources/**" location="/resources/" order="0" />
    <mvc:resources mapping="/favicon.ico" location="/favicon.ico" order="0" />  
    <mvc:resources mapping="/robots.txt" location="/robots.txt" order="0" />

    <mvc:resources mapping="/css/**" location="/css/" order="0" />
    <mvc:resources mapping="/js/libs/**" location="/js/libs/" order="0" />
    <mvc:resources mapping="/img/**" location="/img/" order="0" />
    <mvc:resources mapping="/img/flags/**" location="/img/flags/" order="0" />



    <!-- Welcome page -->
    <mvc:view-controller path="/" view-name="redirect:/home"/>

    <!--  wrapper of org.springframework.web.multipart.commons.CommonsMultipartResolver -->
    <bean id="multipartResolver" class="com.verification.migration.util.DropOversizeFilesMultipartResolver">
        <!-- the maximum file size in bytes -->
        <property name="maxUploadSize" value="500000000000000000"/>
        <property name="maxInMemorySize">
        <value> 50000000 </value>
        </property>
    </bean>

    <!-- Message internalization by using a db -->
    <bean id="messageSource" class="com.verification.migration.util.DatabaseMessageSource">
        <property name="messageRepository" ref="messageRepository" />
    </bean>

    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <!-- <property name="defaultLocale" value="en_UK"/> -->
    </bean>

    <mvc:interceptors>
        <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
            <property name="paramName" value="ln" />
        </bean>
    </mvc:interceptors>

    <!-- THYMELEAF: Template Resolver for email templates -->
    <bean id="emailTemplateResolver"
        class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
        <property name="prefix" value="templates/" />
        <property name="templateMode" value="HTML" />
        <property name="characterEncoding" value="UTF-8" />
        <property name="checkExistence" value="true" />
        <property name="order" value="1" />
    </bean>

    <!-- THYMELEAF: Template Resolver for webapp pages templates -->
    <bean id="webTemplateResolver"
        class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".html" />
        <property name="templateMode" value="HTML" />
        <property name="cacheable" value="false" />
        <property name="characterEncoding" value="UTF-8" />
        <property name="checkExistence" value="true" />
        <property name="order" value="2" />
    </bean> 

    <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
        <property name="templateResolvers">
            <set>
                <ref bean="emailTemplateResolver" />
                <ref bean="webTemplateResolver" />
            </set>
        </property> 

          <!-- These lines configure the dialects to use with Thymeleaf -->
          <property name="dialects">
            <set>
              <bean class="org.thymeleaf.spring4.dialect.SpringStandardDialect"/>

            </set>
          <!-- Table4j additional dialect  -->
          </property>       
          <property name="additionalDialects">
            <set>
                <bean class="org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect"/>
            </set>
          </property>
    </bean>

    <bean id="viewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
        <property name="templateEngine" ref="templateEngine" />
        <property name="contentType" value="text/html;charset=UTF-8" />
        <property name="characterEncoding" value="UTF-8" /> 
    </bean>

</beans> 

而 web.xml 是

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_0.xsd"
metadata-complete="true" version="3.0">

<display-name>OLDAPP</display-name>

<description></description>

<!-- Character encoding filter -->
<filter>
    <filter-name>encodingFilter</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>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Spring-security filter -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Multipart Filter -->
<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <servlet-name>/*</servlet-name>
</filter-mapping>

<!-- CAS filter -->
<filter>
    <filter-name>CAS Single Sign Out Filter</filter-name>
    <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CAS Single Sign Out Filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!--  Session timemout Filter -->
<filter>
    <filter-name>SessionTimeoutCookieFilter</filter-name>
    <filter-class>com.verification.migration.filter.SessionTimeoutCookieFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SessionTimeoutCookieFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Parameters for make autowire possible inside filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
       classpath:applicationContext.xml
    </param-value>
</context-param>

<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext*.xml</param-value>
</context-param>

<!-- If the environment variable -Dspring.profiles.active is not set the default profile is local -->
<context-param>
    <param-name>spring.profiles.default</param-name>
    <param-value>local</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Simple context initializer that log current envirnoment profile used 
    by the webapplication  -->
<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.verification.migration.util.ContextProfileInitializer</param-value>
</context-param>

<listener>
    <description>Servet Listener used to avoid ClassLoader Memory Leak</description>
    <listener-class>com.verification.migration.util.DciContextListener</listener-class>
</listener>

<listener>
    <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

<!-- Processes application requests -->
<servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>spring-mvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<error-page>
    <error-code>403</error-code>
    <location>/403</location>
</error-page>

<error-page>
    <error-code>404</error-code>
    <location>/404</location>
</error-page>

<error-page>
    <error-code>405</error-code>
    <location>/405</location>
</error-page>

<error-page>
    <exception-type>org.springframework.web.bind.MissingServletRequestParameterException</exception-type>
    <location>/404</location>
</error-page>

<error-page>
    <exception-type>org.springframework.web.bind.ServletRequestBindingException</exception-type>
    <location>/404</location>
</error-page>

<error-page>
    <exception-type>org.springframework.web.multipart.support.MissingServletRequestPartException</exception-type>
    <location>/404</location>
</error-page>

<error-page>
    <error-code>400</error-code>
    <location>/404</location>
</error-page>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Restricted methods</web-resource-name>
        <url-pattern>/*</url-pattern>
        <http-method>PUT</http-method>
        <http-method>DELETE</http-method>
        <http-method>TRACE</http-method>
        <http-method>OPTIONS</http-method>
    </web-resource-collection>
    <auth-constraint/>
</security-constraint>

<session-config>
    <session-timeout>10</session-timeout>
    <cookie-config>
        <http-only>true</http-only>
    </cookie-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>

HomeController.java

package com.verification.migration.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;

import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.write.WriteException;
import nl.captcha.Captcha;
import nl.captcha.servlet.CaptchaServletUtil;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
    import org.springframework.web.bind.WebDataBinder;
    import org.springframework.web.bind.annotation.InitBinder;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.SessionAttributes;
    import org.springframework.web.bind.support.SessionStatus;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.servlet.mvc.support.RedirectAttributes;

    import com.google.common.base.Optional;
    import com.google.common.collect.FluentIterable;
    import com.google.common.collect.Lists;
    import com.googlecode.flyway.core.Flyway;

    @SessionAttributes({ "userLogged", "mpFields"})
    @Controller
    public class HomeController {

        private static final Logger logger = LoggerFactory
                .getLogger(HomeController.class);

        @Value("${receipt.folder}")
        private String RECEIPT_FOLDER;

    @RequestMapping(value = { "/home", "/homeprivate" }, method = RequestMethod.GET)
        public String entryPoint(Model model, Locale locale,
                HttpServletRequest request, HttpServletResponse response,
                SessionStatus sessionStatus) {
            model.addAttribute("isHomepage", "true");
            return "homepage";
        }
    }

因为这似乎适用于 3.2.X(旧版本和依赖项)和 4.0.6(我在此处发布的完全相同的文件,只是指向 spring-core 和 spring MVC 4.0 的不同 maven 依赖项版本。 X)我倾向于认为就 XML 配置而言,4.1 肯定发生了一些变化,因为我有其他应用程序在 4.3.7 中使用 java config 运行得很好。 旧版本也使用 Thymeleaf2,我升级到 Thymeleaf3,但这不是罪魁祸首,因为使用 spring 4.0.6 我设法让应用程序在 Thymeleaf2 和 Thymeleaf3 上完美运行。同样适用于休眠版本的升级。

因此,我将其定位为 spring,因为只需从 spring spring 3.2.2 升级 --> spring 4.0.6(并且仅在需要时进行修改,因为从 spring3 到 spring4 有一些依赖关系切换)它可以工作--> spring 4.1.9 除了 spring(核心、mvc 等)之外没有触及任何东西,调用的调度失败......

谁能指出我在这里完全遗漏了什么?

提前致谢。

【问题讨论】:

  • 作为一种解决方法,我更改了 applicationContext-mvc.xml 以引用一个可以处理 mvc 的 java 配置文件,并且它可以工作.. 这只是确认在我的 xml 文件中正确完成了一些事情..但是由于在 4.0.X 到 4.1.X 中没有记录关于 spring mvc xml 配置文件的“更改”,而不是责怪我,我会把它归咎于缺乏文档。如果没有人提供替代方案,我会将此作为答案并将问题标记为已解决,但我真的更喜欢达到适当的解决方案,而不仅仅是“使其工作”以某种方式或其他方式......

标签: java spring spring-mvc servlets spring-4


【解决方案1】:

由于我没有收到有关此主题的答案,我将自己提出一个答案,这本身就是一种 hack,但至少允许我通过..

我更改了 applicationContext-mvc.xml 以引用一个 java 配置文件,该文件反过来处理配置.. 虽然这可行,但这只是证实了我的 xml 文件中没有正确完成某些事情,但是由于 4.0.X 到 4.1.X 中没有记录关于 spring mvc xml 配置文件的“更改”,我会归咎于缺乏文档..

因此请注意,当从 3.X 或 4.0.X 切换到 4.1.x 时,您可能会遇到一些麻烦,我建议您如果无法弄清楚到底出了什么问题(就像我没能做到一样) ,使用 xml 配置声明对 java 配置的组件扫描(仅用于 mvc)来启动应用程序的 mvc 组件就可以了..

不是最漂亮的东西,但这是我想出的唯一解决方案......

【讨论】:

    猜你喜欢
    • 2011-03-04
    • 2014-01-11
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多