2

我尝试使用 Spring-MVC 和 Spring-Security 在 Java 上构建 Web 应用程序。在我需要从数据库中获取信息的一个模块中,我无法获取 SessionFactory。表单更多信息,这里是我的 java config 和其他文件源代码:WebAppConfig.java:

package com.sprsec.init;

import org.hibernate.SessionFactory;
import org.springframework.context.annotation.*;
import org.springframework.context.support.AbstractMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.LocaleResolver;
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.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.sprsec")
@PropertySource("classpath:application.properties")
@ImportResource("classpath:spring-security.xml")
public class WebAppConfig extends WebMvcConfigurerAdapter {

    private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
    private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
    private static final String PROPERTY_NAME_POOL_SIZE = "hibernate.pool_size";

    @Resource
    private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
        dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
        dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
        dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));

        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource());
        sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
        sessionFactoryBean.setHibernateProperties(hibProperties());
        return sessionFactoryBean;
    }

    @Bean
    public SessionFactory getSessioFactory(){
        return sessionFactory().getObject();
    }

    private Properties hibProperties() {
        Properties properties = new Properties();
        properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
        properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
        properties.put(PROPERTY_NAME_POOL_SIZE, env.getRequiredProperty(PROPERTY_NAME_POOL_SIZE));
        return properties;  
    }

    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory().getObject());
        return transactionManager;
    }

    @Bean(name = "messageSource")
    public AbstractMessageSource getMesageSource(){
        return new DatabaseMessageSource(sessionFactory().getObject());
    }

    @Bean
    public HandlerInterceptor localeChangeInterceptor(){
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        return  localeChangeInterceptor;
    }

    @Bean
    public UrlBasedViewResolver setupViewResolver() {
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();
        resolver.setPrefix("/WEB-INF/pages/");
        //resolver.setSuffix(".xhtml");
        resolver.setSuffix(".jsp");
        resolver.setViewClass(JstlView.class);
        return resolver;
    }


    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        registry.addInterceptor(localeChangeInterceptor);
    }

    @Bean
    public LocaleResolver localeResolver() {

        CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
        cookieLocaleResolver.setDefaultLocale(StringUtils.parseLocaleString("en"));
        return cookieLocaleResolver;
    }

}

用户DAOImpl.java:

package com.sprsec.dao;

import com.sprsec.model.User;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;


@Repository
public class UserDAOImpl implements UserDAO {

    @Autowired
    private SessionFactory sessionFactory;
    private Session getSession(){
        return sessionFactory.getCurrentSession();
    }

    public User getUser(String login) {
        List<User> userList = new ArrayList<User>();
        Query query = getSession().createQuery("from User u where u.login = :login");
        query.setParameter("login", login);
        System.out.println(query.getQueryString());
        userList = query.list();
        if (userList.size() > 0)
            return userList.get(0);
        else
            return null;    
    }

    public User getUserByLoginAndPassword(String login, String password){
        Query query = getSession().createQuery("from User u where u.login = :login and u.password = :password");
        query.setParameter("login", login);
        query.setParameter("password", password);
        User user = (User) query.uniqueResult();
        return user;
    }

}

在这里,在 UserDAOImpl.java 中,我检索了一个异常。会话工厂为空。我介意我的 WebAppConfig 类中存在什么问题,因为在 DatabaseMessageSource.java 中我检索到相同的异常,我将在配置中添加这个类,并在构造函数中放置 SessionFactory。我不想在那里添加每个需要这种依赖关系的类。

错误信息:

Caused by: java.lang.NullPointerException
        at com.sprsec.init.DatabaseMessageSource.openSession(DatabaseMessageSource.java:95)
        at com.sprsec.init.DatabaseMessageSource.getSQLDictionary(DatabaseMessageSource.java:104)
        at com.sprsec.init.DatabaseMessageSource.loadTexts(DatabaseMessageSource.java:114)
        at com.sprsec.init.DatabaseMessageSource.refreshProperties(DatabaseMessageSource.java:90)
        at com.sprsec.init.DatabaseMessageSource.reload(DatabaseMessageSource.java:132)
        at com.sprsec.init.DatabaseMessageSource.<init>(DatabaseMessageSource.java:35)
        at com.sprsec.init.WebAppConfig.getMesageSource(WebAppConfig.java:90)
        at com.sprsec.init.WebAppConfig$$EnhancerByCGLIB$$f4b941bb.CGLIB$getMesageSource$3(<generated>)
        at com.sprsec.init.WebAppConfig$$EnhancerByCGLIB$$f4b941bb$$FastClassByCGLIB$$c1655200.invoke(<generated>)
        at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
        at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:286)
        at com.sprsec.init.WebAppConfig$$EnhancerByCGLIB$$f4b941bb.getMesageSource(<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:160)
        ... 57 more

数据库消息源.java:

public class DatabaseMessageSource extends AbstractMessageSource implements MessageSource {

        private final Map<String, Map<String, String>> properties = new HashMap<String, Map<String, String>>();

        @Autowired
        private SessionFactory sessionFactory;

        public DatabaseMessageSource() {
            super();
            //this.sessionFactory = sessionFactory;
            this.setUseCodeAsDefaultMessage(true);
            reload();
            setParentMessageSource(this);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        protected String resolveCodeWithoutArguments(String code, Locale locale) {
            return getText(code, locale);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        protected MessageFormat resolveCode(String code, Locale locale) {
            String msg = getText(code, locale);
            MessageFormat result = createMessageFormat(msg, locale);
            return result;
        }

        /**
         * @param code
         * @param locale
         * @return
         */

        private String getText(String code, Locale locale) {
            Map<String, String> localizedText = properties.get(locale.getLanguage());
            System.out.println("===================================================");
            System.out.println("requested code: "+code+" Result: "+localizedText.get(code));
            System.out.println("===================================================");
            String textForCurrentLanguage = null;
            if (localizedText != null) {
                textForCurrentLanguage = localizedText.get(code);
                if (textForCurrentLanguage == null) {
                    saveKeyword(code);
                    reload();
                    return "__"+code;
                }else if (textForCurrentLanguage.equals("")){
                    return "__"+code;
                } else {
                    return textForCurrentLanguage;
                }
            } else {
                return "__"+code;
            }
        }

        /**
         * @return properties which keeps localized text
         */
        private Map<String, Map<String, String>> refreshProperties() {
            properties.clear();
            properties.putAll(loadTexts());
            return properties;
        }

        public Session openSession(){
            return sessionFactory.openSession();
        }

        private void saveKeyword(final String key){
            Query query = openSession().createSQLQuery("insert into b_dictionary (keyword,lang_ru,lang_lv,lang_en) values ('"+key+"','','','')");
            query.executeUpdate();
        }

        private Iterator getSQLDictionary(){
            Query query = openSession().createSQLQuery("select m.keyword, m.lang_ru, m.lang_lv, m.lang_en from b_dictionary as m");
            return query.list().iterator();
        }


        protected Map<String, Map<String, String>> loadTexts() {
            Map<String, Map<String, String>> myProp = new HashMap<String, Map<String, String>>();
            Map<String, String> dataRU = new HashMap<String, String>();
            Map<String, String> dataLV = new HashMap<String, String>();
            Map<String, String> dataEN = new HashMap<String, String>();
            Iterator result = getSQLDictionary();
            while( result.hasNext() ){
                Object[] row = (Object[]) result.next();
                String code = row[0].toString();
                dataRU.put(code,row[1].toString());
                dataLV.put(code,row[2].toString());
                dataEN.put(code,row[3].toString());
            }
            myProp.put("ru", dataRU);
            myProp.put("lv", dataLV);
            myProp.put("en", dataEN);
            return myProp;
        }

        /**
         * Reload all codes.
         */
        public void reload() {
            refreshProperties();
        }

    }
4

2 回答 2

3

你的问题在这里:

new DatabaseMessageSource(sessionFactory().getObject());

Spring 只能自动装配它管理的 bean;如果您自己调用new创建 bean,@Autowired则不会填写字段(并且@PostConstruct不会调用类似的方法)。该字段应在方法返回后填写@Bean,但如果您需要在 bean 的构造函数中访问它,则必须将其作为参数传递。首选的解决方案是将依赖于@Autowired设置的代码移动到使用@PostConstruct.

于 2013-10-24T09:15:05.333 回答
-1

尝试AnnotationSessionFactoryBean代替LocalSessionFactoryBean

LocalSessionFactoryBean sessionFactoryBean = new AnnotationSessionFactoryBean();
于 2013-10-24T08:24:58.327 回答