我如何在 spring 的 servlet 过滤器中使用 @Transactional 和 sessionFactory bean

how can i use @Transactional and sessionFactory bean in servlet filter with spring

web.xml:

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

上下文配置class:

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

调度程序配置class:

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);
    }


}

过滤器class:

    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。但是这个解决方案对我来说有点模糊。如有说明,不胜感激

您不能在 AuthenticationFilter 中使用 @Autowired,因为它未在 Spring 容器中实例化。它在 Web 应用程序容器中实例化,因此 sessionFactory 将始终为 null,因此 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;
    }

}