2016-08-13 69 views
1

web.xml中:如何使用@Transactional和的sessionFactory豆在Servlet過濾器與彈簧

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> 
    <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>com.phoenix.config.ApplicationConfig</param-value> 
    </context-param> 

    <listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 

    <servlet> 
    <servlet-name>dispatcher</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextClass</param-name> 
     <param-value> 
     org.springframework.web.context.support.AnnotationConfigWebApplicationContext 
     </param-value> 
    </init-param> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>com.phoenix.config.MvcConfig</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> 
    <filter> 
    <filter-name>authenticationFilter</filter-name> 
    <filter-class> 
    com.phoenix.authentication.AuthenticationFilter 
    </filter-class> 
    </filter> 
    <filter> 
    <filter-name>authorizationFilter</filter-name> 
    <filter-class> 
    com.phoenix.authentication.AuthorizationFilter 
    </filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>authenticationFilter</filter-name> 
    <url-pattern>/login/*</url-pattern> 
    </filter-mapping> 
    <filter-mapping> 
    <filter-name>authorizationFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    <error-page> 
    <exception-type>java.lang.Exception</exception-type> 
    <location>/ErrorHandler</location> 
    </error-page> 

    <servlet> 
    <servlet-name>PhoenixExceptionHandler</servlet-name> 
    <servlet-class>com.phoenix.authentication.PhoenixExceptionHandler</servlet-class> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>PhoenixExceptionHandler</servlet-name> 
    <url-pattern>/ErrorHandler</url-pattern> 
    </servlet-mapping> 
</web-app> 

上下文配置類:

package com.phoenix.config; 

import java.util.Properties; 

import javax.sql.DataSource; 

import org.hibernate.SessionFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
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.core.env.Environment; 
import org.springframework.http.HttpHeaders; 
import org.springframework.jdbc.datasource.DriverManagerDataSource; 
import org.springframework.orm.hibernate5.HibernateTransactionManager; 
import org.springframework.orm.hibernate5.LocalSessionFactoryBean; 
import org.springframework.transaction.annotation.EnableTransactionManagement; 

@Configuration 
@EnableTransactionManagement 
@ComponentScan({ "com.phoenix" }) 
@PropertySource(value = { "classpath:hibernate.properties" }) 
public class ApplicationConfig { 

    @Autowired 
    private Environment environment; 

    @Bean 
    public LocalSessionFactoryBean sessionFactory() { 
     LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 
     sessionFactory.setDataSource(dataSource()); 
     sessionFactory.setPackagesToScan("com.phoenix.data.entity"); 
     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")); 
     return properties; 
    } 

    @Bean 
    @Autowired 
    public HibernateTransactionManager transactionManager(SessionFactory s) { 
     HibernateTransactionManager txManager = new HibernateTransactionManager(); 
     txManager.setSessionFactory(s); 
     return txManager; 
    } 
    @Bean 
    public HttpHeaders responseHeader(){ 
    HttpHeaders responseTypeHeader = new HttpHeaders(); 
    responseTypeHeader.add("Content-Type", "application/json; charset=utf-8"); 
    return responseTypeHeader; 
    } 
} 

調度配置類:

package com.phoenix.config; 

import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 
import org.springframework.web.servlet.view.InternalResourceViewResolver; 

@Configuration 
@EnableWebMvc 
@ComponentScan(basePackages = "com.phoenix") 
public class MvcConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void addResourceHandlers(ResourceHandlerRegistry registry) { 
     registry.addResourceHandler("/resources/**") 
     .addResourceLocations("/WEB-INF/resources/"); 
    } 

    @Override 
    public void configureViewResolvers(ViewResolverRegistry registry) { 
     InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); 
     viewResolver.setPrefix("/WEB-INF/views/"); 
     viewResolver.setSuffix(".jsp"); 
     registry.viewResolver(viewResolver); 
    } 


} 

過濾器級別:

package com.phoenix.authentication; 

import java.io.IOException; 
import java.util.List; 

import javax.persistence.Query; 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 

import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 
import org.springframework.transaction.annotation.Transactional; 

import com.phoenix.data.entity.UserInfo; 


public class AuthenticationFilter implements Filter { 

    @Autowired 
    SessionFactory sessionFactory; 



    @Override 
    public void destroy() { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException { 
    HttpServletRequest httpRequest = (HttpServletRequest) request; 
    if(httpRequest.getParameter("username") != null 
      && httpRequest.getParameter("password") != null) 
    { 
     String username = httpRequest.getParameter("username"); 
     String password = httpRequest.getParameter("password"); 
     boolean rememberMe = false; 
     if(httpRequest.getParameter("rememberMe")!= null) 
      rememberMe = httpRequest.getParameter("rememberMe").equals("on"); 

     UserInfo user = getUserInfo(username, password); 
     System.out.print(user+"\n"+rememberMe); 

    } 
    chain.doFilter(request, response); 
    } 

    @Override 
    public void init(FilterConfig arg0) throws ServletException { 

    } 

    public UserInfo getUserInfo(String username, String password) 
    { 
     UserInfo user=null; 
     Session session=sessionFactory.getCurrentSession(); 
     Query query = session.createQuery("FROM UserInfo WHERE" 
       + " UserInfo.username = :xusername AND UserInfo.password = :xpassword"); 
     query.setParameter("xusername",username); 
     query.setParameter("xpassword",password); 
     List list=query.getResultList(); 
     if (list.size()>0) 
      user=(UserInfo)list.get(0); 
     return user; 
    } 

} 

例外:

Aug 13, 2016 5:02:39 PM org.apache.catalina.core.StandardWrapperValve invoke 
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/phoenix] threw exception 
java.lang.NullPointerException 
    at com.phoenix.authentication.AuthenticationFilter.getUserInfo(AuthenticationFilter.java:65) 
    at com.phoenix.authentication.AuthenticationFilter.doFilter(AuthenticationFilter.java:50) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Unknown Source) 

我做了一些搜索和org.springframework.web.filter.DelegatingFilterProxy附帶的解決方案。但是這個解決方案對我來說有點模糊。我很感激,如果解釋。

回答

0

在你的AuthenticationFilter中不能使用@Autowired,因爲它沒有在Spring容器中實例化。它在Web應用程序容器中實例化,因此sessionFactory將始終爲空,因此NullPointerException

但是,您可以使用Spring提供的WebApplicationContextUtils.getRequiredWebApplicationContext來獲取過濾器中的WebApplicationContext。

因此,使用如下修改的AuthenticationFilter.init方法,您的過濾器應該工作。

public class AuthenticationFilter implements Filter { 

    SessionFactory sessionFactory; 

    @Override 
    public void destroy() { 
     this.sessionFactory.close(); 
     this.sessionFactory = null;  
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException { 
    HttpServletRequest httpRequest = (HttpServletRequest) request; 
    if(httpRequest.getParameter("username") != null 
      && httpRequest.getParameter("password") != null) 
    { 
     String username = httpRequest.getParameter("username"); 
     String password = httpRequest.getParameter("password"); 
     boolean rememberMe = false; 
     if(httpRequest.getParameter("rememberMe")!= null) 
      rememberMe = httpRequest.getParameter("rememberMe").equals("on"); 

     UserInfo user = getUserInfo(username, password); 
     System.out.print(user+"\n"+rememberMe); 

    } 
    chain.doFilter(request, response); 
    } 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
     WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext()); 
     this.sessionFactory = ctx.getBean(SessionFactory.class); 
    } 

    public UserInfo getUserInfo(String username, String password) 
    { 
     UserInfo user=null; 
     Session session=sessionFactory.getCurrentSession(); 
     Query query = session.createQuery("FROM UserInfo WHERE" 
       + " UserInfo.username = :xusername AND UserInfo.password = :xpassword"); 
     query.setParameter("xusername",username); 
     query.setParameter("xpassword",password); 
     List list=query.getResultList(); 
     if (list.size()>0) 
      user=(UserInfo)list.get(0); 
     return user; 
    } 

} 
+0

謝謝你的回答@shazin。但沒有交易這個解決方案dosent工作。我使用getUserInfo()方法的事務註釋,但仍然不工作... 我使用Transaction tx = session.beginTransaction()和tx.commit()。但它沒有工作。在這兩種情況下,都會發生以下異常:HibernateException:無法獲取當前線程的事務同步會話 – yousef

+0

@yousef爲什麼您認爲您需要事務處理不修改任何內容的查詢? – shazin

+0

如果沒有事務並且發生此異常,則不起作用:HibernateException:無法獲取當前線程的事務同步會話。這就是爲什麼我認爲交易是getCurrentSession必不可少的... – yousef