【问题标题】:Adding a ContextListener to a full java based Spring configuration将 ContextListener 添加到基于 Java 的完整 Spring 配置中
【发布时间】:2019-01-20 11:05:57
【问题描述】:

我正在尝试基于 Java @Configuration 类和 web.xml 文件设置 Spring 配置。 我定义了两种不同的配置:KatherineConfig.java 保存了 JPA 层的配置; KatherineWebConfig.java 导入第一个配置文件并将 servlet 映射添加到 Spring 配置。

现在我想在我的配置中添加一个ContextLoaderListener。我不知道该怎么做。

这是我的 web.xml 配置:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.3"
    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_2_3.xsd">

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>it.manuelgozzi.katherine.web.configuration.KatherineWebConfig
        </param-value>
    </context-param>

    <display-name>Katherine</display-name>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

这是我的KatherineWebConfig.java 文件:

package it.manuelgozzi.katherine.web.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import it.manuelgozzi.katherine.finance.configuration.KatherineConfig;

@Configuration
@Import(KatherineConfig.class)
@ComponentScan(basePackages = { "it.manuelgozzi.katherine.web" })
@EnableWebMvc
public class KatherineWebConfig {

    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/jsp/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

}

最后这是KatherineConfig.java文件:

package it.manuelgozzi.katherine.finance.configuration;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * Configurazione di Katherine. I parametri sono gestiti esternamente mediante
 * il file katherine.configuration.properties.
 * 
 * @author Manuel Gozzi
 * @date Jan 6, 2019
 * @time 6:12:48 PM
 */
@Configuration
@ComponentScan(basePackages = {"it.manuelgozzi.katherine.finance", "it.manuelgozzi.katherine.web"})
@EnableJpaRepositories(basePackages = "it.manuelgozzi.katherine.finance.model.entity.repository")
@PropertySource("classpath:katherine.configuration.properties")
public class KatherineConfig {

    @Value("${datasource.username}")
    private String dataSourceUsername;

    @Value("${datasource.password}")
    private String dataSourcePassword;

    @Value("${datasource.url}")
    private String dataSourceUrl;

    @Value("${datasource.driverclassname}")
    private String dataSourceDriverClassName;

    @Value("${entitymanager.packagestoscan}")
    private String entityManagerPackagesToScan;

    /**
     * Configurazione del bean relativo al datasource.
     * 
     * @author Manuel Gozzi
     * @date Jan 6, 2019
     * @time 6:13:01 PM
     * @return
     */
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUsername(dataSourceUsername);
        dataSource.setPassword(dataSourcePassword);
        dataSource.setUrl(dataSourceUrl);
        dataSource.setDriverClassName(dataSourceDriverClassName);
        return dataSource;
    }

    /**
     * Configurazione del TransactionManager.
     * 
     * @author Manuel Gozzi
     * @date Jan 6, 2019
     * @time 6:13:12 PM
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }

    /**
     * Configurazione dell'EntityManagerFactory.
     * 
     * @author Manuel Gozzi
     * @date Jan 6, 2019
     * @time 6:13:24 PM
     * @return
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] { entityManagerPackagesToScan });
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        return em;
    }

}

您能否解释一下如何实施此解决方案? 我的目标是支持 Java 配置和 web.xml 一起。

我正在尝试按原样运行我的应用程序,但出现以下异常:

java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?

感谢您的建议!

编辑:

我创建了一个以这种方式实现WebApplicationInitializer 的类:

package it.manuelgozzi.katherine.web.configuration;

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

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import it.manuelgozzi.katherine.finance.configuration.KatherineConfig;

public class KatherineWebInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext annotationConfigContext = new AnnotationConfigWebApplicationContext();
        annotationConfigContext.register(KatherineWebConfig.class);
        annotationConfigContext.register(KatherineConfig.class);
        servletContext.addListener(new ContextLoaderListener(annotationConfigContext));
    }

}

现在我收到以下异常:

java.lang.IllegalArgumentException: ResourceLoader must not be null!

我错过了什么?

【问题讨论】:

    标签: java xml spring web configuration


    【解决方案1】:

    你需要添加你的配置类AnnotationConfigWebApplicationContext:

     context = new AnnotationConfigWebApplicationContext();
     context.register(KatherineConfig.class);
    

    WebApplicationContext 实现接受带注释的类作为输入 - 特别是 @Configuration-annotated 类

    【讨论】:

    • 您好,感谢您的回答。我怎么能那样做?我是否必须创建一个实现 WebApplicationInitializer 的新类并执行“onStartup”方法的@Override?如果是,一旦完成,我怎么能告诉 Spring 加载那个?我有点困惑。
    • @ManuelGozzi Spring 会在启动时找到这个类
    • 我添加了一个EDIT,请检查一下。
    • @ManuelGozzi 你的 web.xml &lt;web-app 标签应该使用版本 3.0
    • 问题仍然存在。我按照建议用 3.0 版本更新了我的 web.xml 文件。
    猜你喜欢
    • 2014-09-25
    • 2012-02-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 2014-10-30
    • 2017-04-25
    • 2017-11-20
    • 1970-01-01
    相关资源
    最近更新 更多