简体   繁体   English

Spring MVC不含XML的配置异常:配置默认Servlet处理需要ServletContext

[英]Spring MVC XML-less configuration exception : A ServletContext is required to configure default servlet handling

I'm new to Spring framework, trying my hands on Spring MVC xml-less (no web.xml or mvc-dispatcher-servlet.xml) configuration, as that's what required for the project. 我是Spring框架的新手,尝试使用Spring MVC的无xml(无web.xml或mvc-dispatcher-servlet.xml)配置,因为这是项目所需要的。

I get following error when I try to run it (using Jetty Local, again a project requirement) 当我尝试运行它时出现以下错误(使用Jetty Local,也是项目要求)

Following is my config for replacing web.xml: 以下是我用于替换web.xml的配置:

(Also tried extending AbstractAnnotationConfigDispatcherServletInitializer without luck) (也尝试扩展AbstractAnnotationConfigDispatcherServletInitializer而不是碰运气)

public class WebConfig implements WebApplicationInitializer {
@Override
public void onStartup( ServletContext servletContext ) throws ServletException {
    WebApplicationContext rootContext = getContext(servletContext);
    servletContext.addListener(new ContextLoaderListener(rootContext));

    ServletRegistration.Dynamic dispatcher = servletContext.addServlet("mvc", new DispatcherServlet(rootContext));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/");
}

private AnnotationConfigWebApplicationContext getContext(ServletContext ctx) {
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    //Tried various combination of un/commenting following options.
    context.register( MvcServletConfig.class );
    //context.setConfigLocation("com.xyz.myapp.configuration");
    context.setServletContext( ctx );
    //context.refresh();
    //context.scan( "com.xyz.someapp.*" );
    return context;
}
}

This is my MVC/Servlet Config replacing mvc-dispatcher-servlet.xml: 这是我的MVC / Servlet配置,替换了mvc-dispatcher-servlet.xml:

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"com.xyz.myapp"})
public class MvcServletConfig extends WebMvcConfigurerAdapter {

public MvcServletConfig() { super(); }

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("forward:/login.jsp");
}

@Bean
public ViewResolver viewResolver() {
    InternalResourceViewResolver bean = new InternalResourceViewResolver();

    bean.setViewClass(JstlView.class);
    bean.setPrefix("/WEB-INF/pages/");
    bean.setSuffix(".jsp");

    return bean;
}
}

This is my AppConfig: 这是我的AppConfig:

@Configuration
@ComponentScan(basePackages = {"com.xyz.myapp.*"})
@Import( { HibernateConfig.class } )
public class AppConfig {}

This is my HibernateConfig where in I have a static method that accesses the context: 这是我的HibernateConfig,其中有一个访问上下文的静态方法:

@Configuration
@EnableTransactionManagement
@ComponentScan( {"com.obsm.visensia.configuration"} )
@PropertySources( value ={@PropertySource("classpath:/application.properties")} )
public class HibernateConfig {
@Transactional
public static void InitialiseDummyData()
{
    AbstractApplicationContext context = new AnnotationConfigApplicationContext( AppConfig.class);
    AccountService accountService = (AccountService) context.getBean("accountService");
    if ( accountService != null )
    {
        Role admin = new AdminRole();
        Role serverAdmin = new ServerAdminRole();
        Role normal = new NormalRole();

        User adminUser = new User();
        adminUser.setFirstName( "Kunal" );
        adminUser.setLastName( "Patel" );
        adminUser.setSex( Sex.Male );
        adminUser.setUsername( "kp" );
        adminUser.setPassword( "kp" );
        adminUser.addRole( admin );


        accountService.addUser( adminUser );

        User serverAdminUser = new User();
        serverAdminUser.setFirstName( "Server" );
        serverAdminUser.setLastName( "Admin" );
        serverAdminUser.setSex( Sex.Male );
        serverAdminUser.setUsername( "serveradmin" );
        serverAdminUser.setPassword( "serveradmin" );
        serverAdminUser.addRole( serverAdmin );

        accountService.addUser( serverAdminUser );

        User normalUser = new User();
        normalUser.setFirstName( "Normal" );
        normalUser.setLastName( "User" );
        normalUser.setSex( Sex.Undefined );
        normalUser.setUsername( "normal" );
        normalUser.setPassword( "normal" );
        normalUser.addRole( normal );

        accountService.addUser( normalUser );

        context.close();
    }
}
@Autowired
private Environment environment;

@Bean
public LocalSessionFactoryBean sessionFactory()
{
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource( dataSource() );
    sessionFactory.setPackagesToScan( new String[] { "com.obsm.visensia.model" } );
    sessionFactory.setHibernateProperties( hibernateProperties() );
    return sessionFactory;
}

@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName( environment.getRequiredProperty( "jdbc.driverClassName" ) );
    dataSource.setUrl( environment.getRequiredProperty( "jdbc.url" ) );
    dataSource.setUsername( environment.getRequiredProperty( "jdbc.username" ) );
    dataSource.setPassword( environment.getRequiredProperty( "jdbc.password" ) );
    return dataSource;
}

private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put( "hibernate.dialect", environment.getRequiredProperty( "hibernate.dialect" ) );
    properties.put( "hibernate.show_sql", environment.getRequiredProperty( "hibernate.show_sql" ) );
    properties.put( "hibernate.hbm2ddl.auto", environment.getRequiredProperty( "hibernate.hbm2ddl.auto" ) );
    properties.put( "hibernate.format_sql", environment.getRequiredProperty( "hibernate.format_sql" ) );
    return properties;
}

@Bean
@Autowired
public HibernateTransactionManager transactionManager ( SessionFactory sessFact )
{
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory( sessFact );
    return transactionManager;
}
}

My LoginController: 我的LoginController:

@Controller
@RequestMapping("/")
public class LoginController {

    @Autowired
    private AccountService accountService;

    @RequestMapping(method = RequestMethod.GET)
    public String login(ModelMap model) {
        HibernateConfig.InitialiseDummyData();
        model.addAttribute( "user", new User() );
        return "login";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String verifyUser(@ModelAttribute("user") User user, Model model)
    {
        if ( accountService.verifyUser( user.getUsername(), user.getPassword() ) ) {
            User usr = accountService.findUserByUsername( user.getUsername() );
            model.addAttribute( "message", "Welcome, " + usr.getFirstName() );
            return "hello";
        }
        else
            return "login";
    }
}

My HelloController: 我的HelloController:

@Controller
@RequestMapping("/")//Doesn't work even if I change it to '/hello'
public class HelloController {
    @RequestMapping(method = RequestMethod.GET)
    public String printWelcome(ModelMap model) {
        model.addAttribute("message", "Hello world!");
        return "hello";
    }
}

Please help, I've been stuck here for 3 days now :'( 请帮助,我已经在这里停留了3天了:'(

UPDATE UPDATE

Jetty 9.2.4v20141103 and this is the stacktrace: Jetty 9.2.4v20141103,这是堆栈跟踪:

Jetty 9.2.4v20141103 and following is the stacktrace:
`java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.util.Assert.notNull(Assert.java:112)
    at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.<init>(DefaultServletHandlerConfigurer.java:54)
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:416)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$b833a897.CGLIB$defaultServletHandlerMapping$30(<generated>)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$b833a897$$FastClassBySpringCGLIB$$56ff08f3.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$b833a897.defaultServletHandlerMapping(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1113)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1008)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:505)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
    at com.obsm.visensia.configuration.HibernateConfig.InitialiseDummyData(HibernateConfig.java:32)
    at com.obsm.visensia.controller.LoginController.login(LoginController.java:26)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:800)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1125)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1059)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:497)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:248)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:620)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:540)
    at java.lang.Thread.run(Thread.java:722)`

Added a class to initialise my db right after my context is refreshed, as thus: 在刷新上下文后立即添加了一个类来初始化数据库,如下所示:

@Component
public class DbInitialiserOnStartUp implements ApplicationListener<ContextRefreshedEvent> {

@Autowired
private AccountService accountService;

@Transactional
@Override
public void onApplicationEvent( ContextRefreshedEvent contextRefreshedEvent ) {
    if ( accountService != null )
    {
        //inserts etc...
    }
}
}

I tested it and it's working fine...try this: 我测试了它,它工作正常...尝试这个:

// You named it WebConfig
public class WebAppInitializer implements WebApplicationInitializer { // web.xml replacement
  @Override
  public void onStartup(ServletContext servletContext) throws ServletException {
    AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();

    // Here you need to change "io.shido.config" to your config location
    applicationContext.setConfigLocation("io.shido.config");

    ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher",
        new DispatcherServlet(applicationContext)); // Register and map the dispatcher servlet

    //servletContext.setInitParameter("spring.profiles.default", "development");
    servletContext.addListener(new ContextLoaderListener(applicationContext));
    //applicationContext.register(AppConfig.class); // Manage the lifecycle of the root application context
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/web/*"); // ...and here also change the context
  }
}

Notice I'm using /web as my context also...so change it accordingly. 请注意,我还将/web用作上下文...因此请相应地对其进行更改。 There is sample project here in case you want to take a look; 这里有示例项目以备您查看。 and this is really, really good article about the subject by the ZeroTurnaround guys. 是ZeroTurnaround伙计们关于该主题的非常非常好的文章。

Additionally, I have in my Maven POM file: 另外,我的Maven POM文件中有:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-war-plugin</artifactId>
  <version>2.6</version>
  <configuration>
    <!--<packagingExcludes>WEB-INF/web.xml</packagingExcludes>-->
    <failOnMissingWebXml>false</failOnMissingWebXml>
  </configuration>
</plugin>

UPDATE UPDATE

Your Spring configuration is working fine (but you can really improve it a little bit more); 您的Spring配置工作正常(但您确实可以进一步改善它); the issue is in the LoginController on the line when you are calling HibernateConfig.InitialiseDummyData(); 当您调用HibernateConfig.InitialiseDummyData();时,问题出在该行的LoginController HibernateConfig.InitialiseDummyData(); . Comment that line and everything will be fine. 评论那条线,一切都会好起来的。

You are starting another Spring context when you call that method. 调用该方法时,您正在启动另一个Spring上下文。 I couldn't fix the issues with the database since I don't have your schema...better to use an in-memory database when doing Proof of Concepts . 我无法解决数据库问题,因为我没有您的架构...在进行概念验证时最好使用内存数据库。 Try to improve/fix that piece of code and you should good to go. 尝试改进/修复这段代码,您应该一切顺利。

import javax.servlet.MultipartConfigElement;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {



    @Override
    protected Class<?>[] getRootConfigClasses() {
        // TODO Auto-generated method stub
        return new Class<?>[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        // TODO Auto-generated method stub
        return new Class<?>[] { WebConfig2.class };
    }

    @Override
    protected String[] getServletMappings() {
        // TODO Auto-generated method stub

        return new String[] { "/" };
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring JavaConfig配置异常:需要ServletContext来配置默认的servlet处理 - Spring JavaConfig configuration exception : A ServletContext is required to configure default servlet handling Spring引导:需要ServletContext来配置默认的servlet处理 - Spring boot : A ServletContext is required to configure default servlet handling Spring的无XML配置 - XML-less configuration for spring Tapestry-spring是否可以实现Servlet 3.0的无XML配置? - Is Servlet 3.0 XML-less configuration possible with tapestry-spring? 使用Spnego / Kerberos的Spring Boot-配置问题-配置默认Servlet处理需要ServletContext - Spring Boot with Spnego/Kerberos - Config Issues - A ServletContext is required to configure default servlet handling 嵌入式码头:需要ServletContext来配置默认的Servlet处理 - Embedded Jetty: A ServletContext is required to configure default servlet handling Spring MVC - 从ServletContext资源[/WEB-INF/mvc-dispatcher-servlet.xml]解析XML文档的意外异常; - Spring MVC - Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]; Spring 3批注:无xml声明式事务管理 - Spring 3 Annotations: xml-less Declarative Transaction Management 在Spring MVC中以Servlet异步模式检索ServletContext - retrieve servletContext in Servlet Async mode in Spring mvc 从 ServletContext 资源 [/WEB-INF/spring-servlet.xml] 解析 XML 文档时出现意外异常; - Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/spring-servlet.xml];
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM