【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实例.
2.HibernateSessionFactoryImp.java是一个Interface,供HibernateSession实现,从而让webwork拦截器自动调用其中的方法.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);
}
![]()
}
3. HibernateSession.java封装了一个Session实例,并且实现了HibernateSessionFactoryImp接口从而在加入拦截器申明以后(后文会介绍)会通过webwork的拦截器自动调用其中的setHibernateSessionFactory()方法,从而自动将HibernateSessionFactory实例注入到了HibernateSession中,供HibernateSession调用public interface HibernateSessionFactoryImp ...{
public void setSessionFactoryService(SessionFactoryService sfs);
}
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中
5.让我们来看看AbstractAction.javapublic interface HibernateSessionImp ...{
public void setHibernateSession(HibernateSession hs);
}
二.拦截器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);
![]()
}
![]()
}
拦截器监视Action的一举一动,并随时截获异常信息,返回给页面.若无异常,则调用HibernateSession的disposeSession()方法,关闭一个Session.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;
}
}
}
}
好了,所有具体的代码告一段落,在以上文件加入我们到的开发所定义的包之后,还需要在配置文件中加以定义.
【IT168技术文档】
三.配置文件
1.components.xml
只要components.xml放在WEB-INF目录下,并确认webwork-default.xml中有如下声明(当然你也可以定义自己的xml文件,并让xwork.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>
用到了日志,所以在WEB-INF目录下还要加入log4j.properties文件,该文件在Demo中有,几乎不要改动.<interceptor name="component" class="com.opensymphony.xwork.interceptor.
component.ComponentInterceptor"/><interceptor name="hibernate" class="你存放HibernateInterceptor文件的包名.
HibernateInterceptor"/>
3.在xwork.xml中加入对webwork-default.xml的引用.
到这里我们快速搭建基于Webwork+Hibernate的Web应用已经完成,看看我们编写Action是多么方便吧.
在web应用中,一般我们对一个用例建立一个对应的Action,从而是整个应用结构清晰.
每一个Action都必须继承AbstractAction,并覆写go()方法即可.在go()方法中要取得session实例,只要用getSession()方法就可以了.试想我们要是在每一个Action中都载入Hibernate配置文件,生成Session Factory和Session实例是多么烦人啊!public class myAction extends AbstractAction...{
![]()
public myAction()...{}
![]()
![]()
public String go() throws HibernateException...{
![]()
//取得Session实例
getSession().save(某个对象);
![]()
rerurn SUCCESS;
![]()
}
}
要想保存用户信息,只要用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实例!
