java - Controller 中的Spring WebMvcConfigurerAdapter,WebApplicationInitializer和DWR空bean

标签 java spring spring-mvc spring-boot dwr

注意以前已将其标记为已回答,但是随着我对基本组件的理解得到了改善,我看到我们的最初答案仅解决了空指针,但未解决根本原因。目前,根本原因似乎是缺少对分发侦听器和附加到容器的dwrServlet上上下文的可见性。

更新解决方案仍然难以捉摸,但是由于以下几个原因,我决定放弃DWR:自从上一次DWR更新以来,Spring和Jquery提供了合适的替代品已经很久了,并且最近进行了维护,从而消除了我们对DWR的依赖将简化我们的项目。仅在这一点上,这个问题仅出于学术目的。

强制性地提到我花了一些时间来研究它。怜悯

我相信我的设置是正确的,但显然我缺少一些关键的东西,我认为现在该是寻找第二组眼睛的时候了。

问题总结

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

详细问题描述

使用Spring 4.3.0.RELEASE版本和Direct Web Remoting(org.directwebremoting.dwr)3.0.2-RELEASE版本;


包com.mytest.beans中定义的给定bean,其中仅包含包含字符串(beanName)的字段,
在SpringWebConfig中以@Bean表示法建立(使用所有Java表示法进行Srping,那里没有xml-仅在dwr中使用xml),
并在com.mytest.controller中定义的控制器中与@Autowired自动连接,该控制器被注释为@RemoteProxy,名称为“ SController”,
注释@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属性。由于这些东西都在实时应用程序中工作(从中得出示例),因此我在示例中省略了它们,因为我不怀疑问题出在工作组件上。日志记录配置也可能不相关,因此将其省略。就是说,如果您除了以下部分之外还有其他想看的内容,请告诉我,我将更新此问题。

组态

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

AppInitializer如下。我正在使用家庭自用的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
    }


}


这些是示例中最复杂的部分。为了说明起见,以下较简单的部分尽可能地备用。

SController类:

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!";
        }

    }
}


SBean类

package com.mytest.bean;

import org.springframework.stereotype.Component;

@Component
public class SBean {
    public String beanName="Sean";
}


dwr.xml文件

<!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>


如当前所示,考虑到Angelo的最初评论,dwr在/ dwr运行,而dwr / index.html在工作。 Spring也可以正常工作,因此只需单击/ getBeanName现在将返回“ Sean”,而不是像以前那样尝试重定向到/ Sean。但是,从自动生成的dwr测试页执行测试调用仍会产生错误,指示在访问sBean的Controller中的行为空。

感谢您花时间审查此问题。当然,非常感谢您为解决这个问题提供帮助!

最佳答案

正如我告诉您的那样,关键是您使用的是DWR Servlet,而不是spring servlet。为了解决第一个问题,您必须使用DWR提供的弹簧支撑,如在此链接中所见http://directwebremoting.org/dwr/documentation/server/integration/spring.html

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

安杰洛

关于java - Controller 中的Spring WebMvcConfigurerAdapter,WebApplicationInitializer和DWR空bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49755428/

相关文章:

java - 使用 Hibernate 在 J2EE 应用程序中存储全局数据的最佳实践

如果类路径上有 jar,Java 编译器不会看到包

java - 简单的 Java 示例使用 14 个线程运行。为什么?

java - 如何获取与 ArrayList 中的条目匹配的所有 SQL 条目?

java - 使用 spring 框架将 Java 对象中的顺序保存为 json

tomcat - SpringMVC 应用程序的 Heroku Procfile

java - 在线程 "main"java.lang.Error : Unresolved compilation: at FileTest. main(FileTest.java:39) 中获取异常

java - 为什么 TestRestTemplate 会忽略 404 客户端错误?

java - Spring MVC : Dynamic Param Name or Param Name using Regex?

java - 从 Spring websocket session 中提取远程端点对象