Spring3.x_Struts2.x_Hibernate3.x整合之OpenSessionInView的实现

由于Hibernate存在延迟加载的问题,当Dao的事物提交之后,session就关闭此时如果到显示层就没有办法获取对象,使用OpenSessionInViewer是解决延迟加载问题的方案。
解决的思路:
1.在表示层开启session
    需要早表示层获取Spring的工厂,以此获取hibernate的SessionFactory
2.在Dao层获取表示层的session
    如果希望在Dao层获取表示层的数据,一个将要获取的数据存储到ThreadLocal
3.当整个过程执行完闭之后再关闭session
需要通过filter来解决问题
1.创建一个filter
//以下方法用来获取Spring的工厂和hibernate的SessionFactory

@Override
public void init(FilterConfig config) throws ServletException {
    /**
     * 使用WebApplicationContextUtils.getWebApplicationContext()来获取Spring的工厂
     * 这种手段非常重要,一定要熟悉
     */
    wac = WebApplicationContextUtils.getWebApplicationContext(config
            .getServletContext());
    factory = (SessionFactory) wac.getBean("sessionFactory");
}


2.通过ThreadLocal来处理session
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();
}


在web.xml中配置filter
<!-- 如果把这个filter放在struts2的filter之后,所有的请求都会被struts2给控制,所以这个filter就不起作用了,
	 必须将这个filter放在struts2的filter之前-->
<filter>
	<filter-name>OpenSessionInViewFilter</filter-name>
	<filter-class>org.oms.spring.filter.OpenSessionFilter</filter-class>
</filter>
	
<filter-mapping>
	<filter-name>OpenSessionInViewFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

OpenSessionFilter过滤器具体代码:

package org.oms.spring.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.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 static 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 destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("begin");
		// 开启session
		/**
		 * 需要获取Spring工厂 如果使用new
		 * ClassPathXmlApplicationContext()这种方式来获取Spring的工厂,
		 * 和Spring在web.xml中得不兼容。 必须通过其他方法来获取 在Spring中可以通过Web
		 */
		try {
			//设置session
			setSession(factory.openSession());
			chain.doFilter(request, response);
		}finally{
			System.out.println("back");
			// 关闭session
			removeSession();
		}
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		/**
		 * 使用WebApplicationContextUtils.getWebApplicationContext()来获取Spring的工厂
		 * 这种手段非常重要,一定要熟悉
		 */
		wac = WebApplicationContextUtils.getWebApplicationContext(config
				.getServletContext());
		factory = (SessionFactory) wac.getBean("sessionFactory");
	}

}

BaseDao中得load方法修改:
@Override
public T load(int id) {
//如果使用了自定义的OpenSessionFilter,需要按照如下方法来获取
//	return (T)OpenSessionFilter.getSession().load(getClz(), id);
	/**
	 * 如果使用了Spring提供的OpenSessionInViewFilter就按照整合的方法处理即可
	 */
        return  this.getHibernateTemplate().load(getClz(), id);
}


这样就有效的解决了我们的延迟加载的问题!


当然在Spring中提供了OpenSessionInViewFilter的过滤器,以此我们只需要在web.xml中配置OpenSessionInViewFilter的过滤器,在load方法中继续使用HibernateTemplate的load方法!


个人备忘笔记~~~呵呵~~!





你可能感兴趣的:(spring,Hibernate,struts2,filter,SSH整合)