技术开发 频道

Webwork+Hibrnate开发


IT168技术文档】 
    快速搭建起基于Webwork与Hibernate的web应用. 

    主要是一下几个文件完成了我们将Hibernate的Session与Webwork的Action绑定从而快速搭建web应用的关键: 

    通用类: 
    HibernateSessionFactoryImp.java 
    HibernateSession.java 
    HibernateSessionImp.java 
    AbstractAction.java 

    拦截器: 
    HibernateInterceptor.jva 

    此外还需要在配置文件中加入相应的申明和相关的资源文件,下面一一介绍. 

    一.通用类 

    1.HibernateSessionFactory.java中主要封装了Hibernate的SessionFactory实例,我们知道SessionFactory相比Session是重量级别,所以生成相当耗费资源,而一个应用也只能生成一个SessionFactory实例.
public class HibernateSessionFactory implements Initializable, Disposable, Serializable { private static final Log LOG = LogFactory.getLog(SessionFactoryService.class); private SessionFactory sf; //返回SessionFactory实例 public HibernateSessionFactory getSessionFactory() { return sf; } //初始化生成SessionFactory public void init() { try { sf = new Configuration().configure().buildSessionFactory(); } catch (Exception e) { LOG.error("error generate SessionFactory", e); throw new RuntimeException( e.getMessage() ); } } //关闭SessionFactory public void dispose() { try { sf.close(); } catch (Exception e) { LOG.error("error closing HibernateSession", e); } } public String getDialect() { return Environment.getProperties().getProperty(Environment.DIALECT); } }
    2.HibernateSessionFactoryImp.java是一个Interface,供HibernateSession实现,从而让webwork拦截器自动调用其中的方法.
public interface HibernateSessionFactoryImp { public void setSessionFactoryService(SessionFactoryService sfs); }
     3. HibernateSession.java封装了一个Session实例,并且实现了HibernateSessionFactoryImp接口从而在加入拦截器申明以后(后文会介绍)会通过webwork的拦截器自动调用其中的setHibernateSessionFactory()方法,从而自动将HibernateSessionFactory实例注入到了HibernateSession中,供HibernateSession调用
public class HibernateSession implements HibernateSessionFactoryImp{ private static final Log LOG = LogFactory.getLog(SessionService.class); private Session session; private Transaction transaction; private HibernateSessionFactory hsf; private boolean rollBackOnly; //返回一个Session实例,并开始一个事务 public Session getSession() throws HibernateException { if (session==null) { session = hsf.getSessionFactory().openSession(); transaction = session.beginTransaction(); } return session; } //注入HibernateSessionFactory实例 public void setHibernateSessionFactory(HibernateSessionFactory hsf) { this.hsf = hsf; } //关闭一个Session public void disposeSession() throws HibernateException { LOG.debug("disposing"); if (session==null) return; if (rollBackOnly) { try { LOG.debug("rolling back"); if (transaction!=null) transaction.rollback(); } catch (HibernateException e) { LOG.error("error during rollback", e); throw e; } finally { session.close(); session=null; transaction=null; } } else { try { LOG.debug("committing"); if (transaction!=null) transaction.commit(); } catch (HibernateException e) { LOG.error("error during commit", e); transaction.rollback(); throw e; } finally { session.close(); session=null; transaction=null; } } } //事务回滚 public boolean isRollBackOnly() { return rollBackOnly; } public void setRollBackOnly(boolean rollBackOnly) { this.rollBackOnly = rollBackOnly; } }

IT168技术文档】 
    4.同样HibernateSessionImp.java也是一个接口,供AbstractAction实现,从而使Webwork自动调用其中的setHibernateSession()方法,将HibernateSession实例注入到AbstractAction中
public interface HibernateSessionImp { public void setHibernateSession(HibernateSession hs); }
    5.让我们来看看AbstractAction.java
public abstract class AbstractAction extends ActionSupport implements HibernateSessionImp{ private static final Log LOG = LogFactory.getLog(AbstractAction.class); private HibernateSession hs; //重写Webwork的execute()方法 public String execute() throws Exception { // 如果有错返回到INPUT所指定的页面 if ( hasErrors() ) { LOG.debug("action not executed, field or action errors"); LOG.debug( "Field errors: " + getFieldErrors() ); LOG.debug( "Action errors: " + getActionErrors() ); return INPUT; } LOG.debug("executing action"); return go(); } protected abstract String go() throws HibernateException; //注入HibernateSession实例 public void setSessionService(SessionService ss) { this.ss = ss; } public SessionService getSessionService() { return ss; } //返回Session实例 protected Session getSession() throws HibernateException { return ss.getSession(); } protected void setRollbackOnly() { ss.setRollBackOnly(true); } /** * 将需要保存的对象暂存在Webwork的Session中(此Session非彼Session) */ protected Object get(String name) { return ActionContext.getContext().getSession().get(name); } /** * 从Webwork的Session(此Session非彼Session)中取出暂存的对象 */ protected void set(String name, Object value) { ActionContext.getContext().getSession().put(name, value); } }
    二.拦截器
public class HibernateInterceptor implements Interceptor { private static final Log LOG = LogFactory.getLog(HibernateInterceptor.class); public void destroy() {} public void init() {} public String intercept(ActionInvocation invocation) throws Exception { Action action = invocation.getAction(); if ( !(action instanceof AbstractAction) ) return invocation.invoke(); HibernateSession hs = ( (AbstractAction) action ).getHibernateSession(); try { return invocation.invoke(); } catch (Exception e) { ss.setRollBackOnly(true); if (e instanceof HibernateException) { LOG.error("HibernateException in execute()", e); return Action.ERROR; } else { LOG.error("Exception in execute()", e); throw e; } } finally { try { hs.disposeSession(); } catch (HibernateException e) { LOG.error("HibernateException in dispose()", e); return Action.ERROR; } } } }
    拦截器监视Action的一举一动,并随时截获异常信息,返回给页面.若无异常,则调用HibernateSession的disposeSession()方法,关闭一个Session. 

    好了,所有具体的代码告一段落,在以上文件加入我们到的开发所定义的包之后,还需要在配置文件中加以定义.



IT168技术文档】 
    三.配置文件 
    1.components.xml
<components> <component> <scope>request</scope> <class>com.sunbay.util.SessionService</class> <enabler>com.sunbay.util.SessionServiceInterface</enabler> </component> <component> <scope>application</scope> <class>com.sunbay.util.SessionFactoryService</class> <enabler>com.sunbay.util.SessionFactoryServiceInterface</enabler> </component> </components>
    只要components.xml放在WEB-INF目录下,并确认webwork-default.xml中有如下声明(当然你也可以定义自己的xml文件,并让xwork.xml包括进来):
<interceptor name="component" class="com.opensymphony.xwork.interceptor.
component.ComponentInterceptor
"/> <interceptor name="hibernate" class="你存放HibernateInterceptor文件的包名.
HibernateInterceptor
"/>
    用到了日志,所以在WEB-INF目录下还要加入log4j.properties文件,该文件在Demo中有,几乎不要改动. 

    3.在xwork.xml中加入对webwork-default.xml的引用. 
    
    到这里我们快速搭建基于Webwork+Hibernate的Web应用已经完成,看看我们编写Action是多么方便吧. 

    在web应用中,一般我们对一个用例建立一个对应的Action,从而是整个应用结构清晰.
public class myAction extends AbstractAction{ public myAction(){} public String go() throws HibernateException{ //取得Session实例 getSession().save(某个对象); rerurn SUCCESS; } }
    每一个Action都必须继承AbstractAction,并覆写go()方法即可.在go()方法中要取得session实例,只要用getSession()方法就可以了.试想我们要是在每一个Action中都载入Hibernate配置文件,生成Session Factory和Session实例是多么烦人啊! 

    要想保存用户信息,只要用set()方法保存,要用时用get()方法取出就可以 

    在wen应用一开始,在xwork.xml文件中由于加入了对webwork-default.xml的引用,所以webwork又找到webwork-default.xml,通过其中的 
    <interceptor name="component" class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>webwork又找到了
components.xml,于是,通用类的四个文件都被加入webwork的视线.拦截器自动调用HibernateSessionFactoryImp.java和HibernateSessionImp.java中的set方法,先将HibernateSessionFactory实例注入到HibernateSession中,然后当在调用Action的候,又将HibernateSession的实例注入到了AbstractAction中,从而使继承AbstractAction的每一个Action实例都有了HibernateSession实例,只要在go()中调用getSession()方法我们就有了session实例!
0
相关文章