思路就是创建一个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>