函数 isAssignableFrom 在服务器启动期间返回 false [英] Function isAssignableFrom returns false during server startup

查看:47
本文介绍了函数 isAssignableFrom 在服务器启动期间返回 false的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

实现一个 oauth2 系统,我在使用以下代码时遇到了一些问题:

Implementing an oauth2 system, I am having some problems with the following code:

import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping;
import org.springframework.web.servlet.HandlerMapping;

...
HandlerMapping.class.isAssignableFrom(FrameworkEndpointHandlerMapping.class);

确实,由于FrameworkEndpointHandlerMapping 类正在实现接口HandlerMapping,因此该函数应始终返回true.当我对这个函数运行单元测试时就是这种情况.但是,在服务器启动期间,此函数返回false(使用调试器检查).这是一个巨大的问题,因为当 DispatcherServlet 被实例化时,它会搜索实现 HandlerMapping 的类,而我的 FrameworkEndpointHandlerMapping 被丢弃导致错误申请.

Indeed, as the class FrameworkEndpointHandlerMapping is implementing the interface HandlerMapping, this function should always return true. It is the case when I run a unit test on this function. However, during the startup of the server, this function returns false (checked using the debugger). This is a huge problem because when the DispatcherServlet is instantiated, it searches for the class implementing HandlerMapping and my FrameworkEndpointHandlerMapping is discarded leading to bugs in the application.

我已经搜索过类似这样的其他问题,但大多数人的回答是 isAssignableFrom 方法未正确使用(类和函数参数的混合).情况并非如此,因为 JUnit 正在运行.

I have searched for other questions like this one but most of them answer that the isAssignableFrom method is not used correctly (mix of the class and the parameter of the function). This is not the case here since the JUnit is working.

怀疑导入的 jar 文件有问题,我将它们限制为以下几个:

Suspecting the imported jar files to be the problem, I have limited them to the following ones:

  • spring-beans-4.1.4.RELEASE.jar
  • spring-security-oauth2-2.0.6.RELEASE.jar
  • spring-webmvc-4.1.4.RELEASE.jar(也用 4.0.9 试过)
  • spring-core-4.1.4.RELEASE.jar
  • ...

您有什么想法可以探索吗?

Do you have any idea of a solution to explore please?

有关更多信息,以下是来源:

For more information, here are the sources:

我自己的DispatcherServlet(以String为参数的构造函数被JUnit测试调用,系统启动时调用默认构造函数)

My own DispatcherServlet (the constructor with the String as a parameter is called by the JUnit test and the default constructor is called during the startup of the system)

import org.junit.Assert;
import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

public class MobileDispatcherServlet extends DispatcherServlet
{

    private static final long serialVersionUID = 1L;

    public MobileDispatcherServlet()
    {
        super();
        HandlerMapping.class.isAssignableFrom(FrameworkEndpointHandlerMapping.class);
    }

    public MobileDispatcherServlet(final WebApplicationContext webApplicationContext)
    {
        super(webApplicationContext);
        final FrameworkEndpointHandlerMapping handlerMapping = webApplicationContext.getBean(FrameworkEndpointHandlerMapping.class);

        HandlerMapping.class.isAssignableFrom(handlerMapping.getClass());
    }

    public MobileDispatcherServlet(final String test)
    {
        Assert.assertTrue(HandlerMapping.class.isAssignableFrom(FrameworkEndpointHandlerMapping.class));
    }
}

oauth 配置文件:

<?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:security="http://www.springframework.org/schema/security"
    xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
                        http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd">

    <!-- Root of the configuration -->
    <!-- The FrameworkEndpointHandlerMapping is created here -->
    <oauth:authorization-server client-details-service-ref="clientDetails"
                                token-services-ref="tokenServices"
                                user-approval-handler-ref="userApprovalHandler"
                                authorization-endpoint-url="/oauth/authorize.action"
                                token-endpoint-url="/oauth/token.action" >
        <oauth:authorization-code authorization-code-services-ref="authorizationCodeServices" disabled="false" />
        <oauth:refresh-token />
    </oauth:authorization-server>

    ...

</beans>

web.xml:

<web-app id="sitestorefront" version="3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app.xsd" 
         metadata-complete="true">

...

    <context-param>
        <description>
            The 'contextConfigLocation' param specifies where your configuration files are located.
            The 'WEB-INF/config/web-application-config.xml' file includes several other XML config
            files to build up the configuration for the application.
        </description>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/config/web-application-config.xml</param-value>
    </context-param>
    <context-param>
        <param-name>tagpoolMaxSize</param-name>
        <param-value>50</param-value>
    </context-param>

<servlet>
        <description>
            DispatcherServlet
        </description>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>be.sbh.site.storefront.oauth2.MobileDispatcherServlet</servlet-class>
        <init-param>
            <description>
                Specifies the location for Spring MVC to load an additional XML configuration file.
                Because hybris is already configured with the XML spring configuration files to load
                we must set this param value to EMPTY in order to prevent loading of the default
                /WEB-INF/applicationContext.xml file.
            </description>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <!-- Map all requests to the DispatcherServlet -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

...

</web-app>

web-application-config.xml 导入所有配置文件(其中包括 oauth 配置文件).其中之一有一个 来启用 mvc 注释.

The web-application-config.xml imports all the configuration files (among them, the oauth configuration file). One of them has a <mvc:annotation-driven /> to enable the mvc annotations.

我试图将我的来源限制在与我相关的来源.如果您需要更多,请随时问我.

I tried to limit my sources to the ones that seems relevant to me. If you need more, do not hesitate to ask me.

感谢您阅读这个问题,

劳伦特

推荐答案

这真的很奇怪.遇到这样的问题,我首先怀疑是没有找到这个bean,或者是被子应用上下文中的同名bean隐藏了.但是正如您所说,您设法看到 ClassUtils.isAssignableFrom 被调用并返回 False,我承认找到并测试了正确的 bean.

This is really weird. Facing such a problem, I would first suspect that the bean is not found, or is hidden by a bean of same name in a child application context. But as you say you managed to see that ClassUtils.isAssignableFrom was called and returned False, I admit the correct bean was found and tested.

我能想象的最后一个问题是类路径中 HandlerMapping 的多个实例.正如 JonSkeet 的评论所建议的,如果类路径中有多个 spring-webmvc.jarFrameworkEndpointHandlerMapping 的类加载器可以选择一个,而自定义 的类加载器DispatcherServlet 可以选择另一个.

The last problem I can imagine would be multiple instances of HandlerMapping in classpath. As suggested by JonSkeet's comment, if you have multiple spring-webmvc.jar in classpath, the classloader for FrameworkEndpointHandlerMapping could have pick one, and the classloader for your custom DispatcherServlet could have pick another one.

如果您使用的是 maven,请控制依赖关系图.无论如何,请控制您的应用程序和 servlet 容器的 lib 文件夹中的 jar 列表,以及可通过全局 CLASSPATH 环境变量公开访问的 jar 列表

If you are using maven, do control the dependency graph. And anyway, do control the list of jars in lib folder of you app and of the servlet container, and the ones publically accessible through a global CLASSPATH environment variable

这篇关于函数 isAssignableFrom 在服务器启动期间返回 false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆