自定义OpenSessionInViewer过滤器

摘自孔浩视频 spring部分-17_spring_SSH整合02_OpenSessionInViewer的讲解


思路就是创建一个filter,这个filter在视图请求的过程中获取到Spring所管理的SessionFactory对象。 这样便解决了视图层Session无法获取的问题。

1. 首先创建一个OpenSessionFilter.java

OpenSessionFilter

package com.lj.filter;

import java.io.IOException;

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 org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class OpenSessionFilter implements Filter {
	
	
	//Spring的工厂,在init中获取
	private WebApplicationContext wac;
	private static SessionFactory factory;
	private static ThreadLocal<Session> sessionHolder=new ThreadLocal<Session>();
	
	private static void setSession(Session session){
		sessionHolder.set(session);
	}
	
	public static Session getSession(){
		return sessionHolder.get();
	}
	
	private static void removeSession(){
		sessionHolder.remove();
	}
	
	
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		 
		/**
		 * 在这里获取Spring的工厂信息,在init里面就只会执行一次
		 * 使用WebApplicationContextUtils.getWebApplicationContext(ServletContext)来获取Web中的Spring工厂。
		 * 这种手段非常重要,要熟悉
		 */
		 
		wac=WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
		//我们在beans.xml中定义的sessionFactory <bean id="sessionFactory">
		factory=(SessionFactory) wac.getBean("sessionFactory");
		
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		//开启session
		System.out.println("begin");
	    /** 要获取SessionFactory,需要先获取Spring的工厂
		 *  如果使用new ClassPathXmlApplicationContext(),就会产生一个新工厂,和Servlet初始化时的工厂是两个对象
		 *  必须通过其他方法来获取
		 *  在Spring中可以通过Web
		 */
		
		//这里不能用getCurrentSession,要用openSession()
		try {
			setSession(factory.openSession());
			chain.doFilter(req, res);
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//关闭session
		System.out.println("back");
	}

	@Override
	public void destroy() {

	}

}


2. 在web.xml中配置filter

<filter>
		<filter-name>mySessionInViewerFilter</filter-name>
		<filter-class>com.lj.filter.OpenSessionFilter</filter-class>
	</filter>
	<filter-mapping>
		
		<filter-name>mySessionInViewerFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


Note: 注意这里如果使用的是struts2, 那么struts2的url-pattern也是/*,所有的请求都会被struts2的拦截器拦截, 这个filter也就不会起作用了。
因此必须要将这个filter的配置放在Struts2的前面,才能正常使用。



这时就可以在Dao层调用这个类来获取Session,例如:
	public List<Group> list() {
		// TODO Auto-generated method stub
		//return this.getSession().createQuery("from Group").list();
		return OpenSessionFilter.getSession().createQuery("from Group").list();
	}


这样web容器便会在视图层中获取Session,并执行相应的Session操作。





==========================
Spring已经提供了OpenSessionInViewerFilter, 一般直接配置Spring的就可以了。
 
	<filter>
		<filter-name>openSessionInViewerFilter</filter-name>
		<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>openSessionInViewerFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping> 

猜你喜欢

转载自alleni123.iteye.com/blog/1988036