Java 控制器中的Spring WebMVCConfigureAdapter、WebApplicationInitializer和DWR空bean

Java 控制器中的Spring WebMVCConfigureAdapter、WebApplicationInitializer和DWR空bean,java,spring,spring-mvc,spring-boot,dwr,Java,Spring,Spring Mvc,Spring Boot,Dwr,注意这之前被标记为已回答,但随着我对底层组件的理解有所提高,我发现我们最初的回答只是针对空指针,而没有针对根本原因。目前的根本原因似乎是dispatchListener和附加到容器的dwrServlet上的上下文都不可见 更新解决方案仍然难以捉摸,但我现在决定放弃DWR,原因有几个:DWR的上次更新已经很久了,Spring和Jquery提供了合适的替代方案,并且是最近维护的,删除我们的DWR依赖项将简化我们的项目。这个问题目前仅限于学术目的 必须提到我花了多少时间研究这个。发发慈悲吧 我相信我的

注意这之前被标记为已回答,但随着我对底层组件的理解有所提高,我发现我们最初的回答只是针对空指针,而没有针对根本原因。目前的根本原因似乎是dispatchListener和附加到容器的dwrServlet上的上下文都不可见

更新解决方案仍然难以捉摸,但我现在决定放弃DWR,原因有几个:DWR的上次更新已经很久了,Spring和Jquery提供了合适的替代方案,并且是最近维护的,删除我们的DWR依赖项将简化我们的项目。这个问题目前仅限于学术目的

必须提到我花了多少时间研究这个。发发慈悲吧

我相信我的设置是正确的,但很明显我错过了一些关键的东西,我认为是时候寻找第二双眼睛了

问题摘要

当通过DWR调用的控制器方法访问我的bean时,它们是空的

详细问题描述

使用SpringVersion4.3.0.RELEASE和directwebremoting(org.directwebremoting.dwr)Version3.0.2-RELEASE

  • 包com.mytest.beans中定义的给定bean,它只包含一个包含字符串的字段(beanName)

  • 在SpringWebConfig中使用@Bean表示法建立(使用所有Java表示法进行Srping,没有xml-仅使用xml和dwr)

  • 并在com.mytest.controller中定义的控制器中使用@autowired进行自动连接,该控制器被注释为@RemoteProxy,名称为“scocontroller”

  • 注释@Controller和注释@RequestMapping的值为“/dwr/*”,其中包含一个名为getBeanName的方法注释@RemoteMethod,该方法调用自动连线实例sbean.beanName

  • 为自动连线实例引发null异常

尝试过的事情

在本例中,我消除了错误实例化bean的可能性,这是@Autowired的一个已知问题。我还小心地确保bean被注释为@Component,这是bean无法出现的另一个可能原因。我将dwr上的加载顺序设置为2,以便首先加载应用程序上下文,希望能够确保工作正常,这确实允许我访问dwr index.html进行测试和调试

我还尝试将以下行添加到AppInitializer:

dwr.setInitParameter("classes","com.mytest.bean.SBean, com.mytest.controller.SController");
但这没有帮助

本例中省略的内容

这不是完整的项目。省略了pom、项目结构和一些.jsp。在我的测试中,我的身份验证功能正常,如果我添加一个dwr@RemoteMethod来注入会话并请求它,那么可以访问添加到HttpSession的adUser属性。由于这些东西在live app(示例就是从中派生出来的)中起作用,我在示例中省略了它们,因为我不怀疑问题出在工作组件上。日志记录配置也可能不相关,因此被省略。这就是说,如果有什么你想看到除了以下部分,请让我知道,我会更新这个问题

配置

在我的包com.mytest.config中,我有三个类:AppInitializer、RootConfig和SpringWebConfig。RootConfig只是空的

AppInitializer如下所示。我使用的是一个home brew Active Directory身份验证模块,它在其他Spring应用程序中运行良好,因此是UserLoginServlet

package com.mytest.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class AppInitializer implements WebApplicationInitializer {

    private Logger logger = LoggerFactory.getLogger(AppInitializer.class);

    public void onStartup(ServletContext container) throws ServletException {

        try {

            AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            ctx.register(SpringWebConfig.class);
            ctx.setServletContext(container);
            container.addListener(new ContextLoaderListener(ctx));
            container.addListener(new RequestContextListener());
            logger.info("Created AnnotationConfigWebApplicationContext");

            ServletRegistration.Dynamic dispatcher = container.addServlet("spring-mvc-dispatcher", new DispatcherServlet(ctx));
            dispatcher.setLoadOnStartup(1);
            dispatcher.addMapping("/");
            logger.info("DispatcherServlet added to AnnotationConfigWebApplicationContext");

            ServletRegistration.Dynamic servlet = container.addServlet("login", new com.mycompany.ad.UserLoginServlet());

            servlet.setLoadOnStartup(1);
            servlet.addMapping("/login/*");
            logger.info("UserLoginServlet added to AnnotationConfigWebApplicationContext");

            ServletRegistration.Dynamic dwr = container.addServlet("dwr", new org.directwebremoting.servlet.DwrServlet());
            dwr.setInitParameter("debug", "true");
            dwr.setLoadOnStartup(2);
            dwr.addMapping("/dwr/*");
            logger.info("DWR Servlet Mapping Created");
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage(), e);
        }

    }

}
SpringWebConfig的定义如下

package com.mytest.config;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.directwebremoting.annotations.DataTransferObject;
import org.directwebremoting.annotations.GlobalFilter;
import org.directwebremoting.annotations.RemoteProxy;
import org.directwebremoting.extend.Configurator;
import org.directwebremoting.spring.DwrClassPathBeanDefinitionScanner;
import org.directwebremoting.spring.DwrController;
import org.directwebremoting.spring.DwrHandlerMapping;
import org.directwebremoting.spring.SpringConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.mytest"})
@PropertySource(value = { "classpath:application.properties" })
public class SpringWebConfig extends WebMvcConfigurerAdapter {

    private Logger logger = LoggerFactory.getLogger(SpringWebConfig.class);

    @Bean
    public DwrController dwrController(ApplicationContext applicationContext){
        logger.info("Starting dwrController Bean");
        BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry)applicationContext.getAutowireCapableBeanFactory();
        Map<String,String> configParam = new HashMap<String, String>();


        logger.info("Configuring scanners for DWR Bean");

        ClassPathBeanDefinitionScanner scanner = new DwrClassPathBeanDefinitionScanner(beanDefinitionRegistry);
        scanner.addIncludeFilter(new AnnotationTypeFilter(RemoteProxy.class));
        scanner.addIncludeFilter(new AnnotationTypeFilter(DataTransferObject.class));
        scanner.addIncludeFilter(new AnnotationTypeFilter(GlobalFilter.class));
        scanner.scan("com.mytest.bean");


        logger.info("Instantiating DwrController instance");
        DwrController dwrController = new DwrController();
        dwrController.setDebug(true);
        dwrController.setConfigParams(configParam);

        logger.info("Setting up SpringConfigurator for dwrController");
        SpringConfigurator springConfigurator = new SpringConfigurator();
        List<Configurator> configurators = new ArrayList<Configurator>();
        configurators.add(springConfigurator);
        dwrController.setConfigurators(configurators);

        logger.info("dwrController ready.");
        return dwrController;
    }

    @Bean
    public BeanNameUrlHandlerMapping beanNameUrlHandlerMapping(){
        logger.info("Setting up beanNameUrlHandlerMapping");
        BeanNameUrlHandlerMapping beanNameUrlHandlerMapping = new BeanNameUrlHandlerMapping();
        logger.info("beanNameUrlHandlerMapping ready.");
        return beanNameUrlHandlerMapping;
    }

    @Bean
    public DwrHandlerMapping dwrHandlerMapping(DwrController dwrController){
        logger.info("Setting up dwrHandlerMapping");
        Map<String,DwrController> urlMap = new HashMap<String, DwrController>();
        urlMap.put("/dwr/**/*",dwrController);

        DwrHandlerMapping dwrHandlerMapping = new DwrHandlerMapping();
        dwrHandlerMapping.setAlwaysUseFullPath(true);
        dwrHandlerMapping.setUrlMap(urlMap);
        logger.info("dwrHandlerMappying ready.");
        return dwrHandlerMapping;
    }

    @Bean(name="sBean") 
    public SBean sBean() {
        logger.info("SBean starting");
        return new SBean();
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
        logger.info("DefaultServletHandlerConfigurer enabled");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry){          
        // not using an interceptor
    }


}
斯比恩阶级

dwr.xml文件


如目前所示,考虑到Angelo的初始注释,dwr在/dwr处运行,dwr/index.html正在工作。Spring也在工作,因此只需点击/getBeanName现在就会返回“Sean”,而不是像以前那样尝试重定向到/Sean。但是,从自动生成的dwr测试页面执行测试调用仍然会产生一个错误,指示在访问sBean的控制器中的行处出现null


感谢您花时间审阅此内容。当然,我们非常感谢您协助解决此问题

正如我告诉您的,重点是您使用的是DWR Servlet,而不是spring Servlet。为了解决第一个问题,您必须使用DWR提供的spring支持,正如您在本链接中看到的那样

关于第二个问题(404错误),我认为这与以下事实有关:自从您删除了dwr servlet之后,您现在只有
/dwr/Sean
路径。 尝试使用
/dwr/Sean
而不是
dwr/dwr/Sean
路径


Angelo

我看到的是您正在使用DWRServlet。在这种情况下,您没有使用SpringServlet,SpringContext也没有直接注入到这个servlet中。尝试在这里看一看感谢@Angelo的建议,我注释掉了DWR Servlet,在dispatcher上的全局映射之前添加了/DWR/*映射,并在控制器方法声明中添加了@RequestMapping(“getBeanName”),现在如果我调用mytest/DWR/DWR/getBeanName,它将返回404 DWR/DWR/Sean not found,这表明空指针问题已经解决,但我还有一些其他问题需要用标准Spring dispatcher解决。请随意添加一个我可以接受的答案。我还没有放弃让servlet共存并共享一个上下文,但一个可行但我不喜欢的解决方法是让DWR入口点不尝试连接到自动连线bean,而是向Spring控制器发出Web请求。就HTTP流量而言,它使每个DWR调用增加了一倍,但只增加了一半
package com.mytest.controller;

import javax.servlet.http.HttpSession;

import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mytest.bean.SBean;


@RemoteProxy(name="SController")
@Controller
@RequestMapping("/dwr/*")
public class SController {

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

    @Autowired
    SBean sbean;

    @RemoteMethod
    @RequestMapping("getBeanName")
    @ResponseBody public String getBeanName() {
        try {
            return sbean.beanName;
        }
        catch(Exception e) {
            logger.error(e.getLocalizedMessage(),e);
            return "Error!";
        }

    }
}
package com.mytest.bean;

import org.springframework.stereotype.Component;

@Component
public class SBean {
    public String beanName="Sean";
}
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "dwr30.dtd">
<dwr>
  <allow>

    <create creator="new" javascript="SController" scope="script">
      <param name="class" value="com.mytest.controller.SController"/>
    </create>

  <convert converter="bean" match="java.lang.Throwable"/>
  <convert converter="bean" match="java.lang.StackTraceElement"/>

  <convert match="com.mytest.bean.SBean" converter="bean"/>

  </allow>
</dwr>