将Hibernate和Struts进行完美结合
关键词:
将Hibernate和Struts进行配合, 以节省开发时间和成本. 经过再三考虑,发现通过JavaScript生成XML发送到后台Servlet 利用Hibernate再写入数据库的方法并不可取,此方案只能用于简单操作.当数据库的结构发生变更的时候,则对网站代码需要进行五次修改: 1.修改Hibernate映射;2.修改Servlet中对XML的解析;3.修改JavaScript中生成的XML结构;4.修改HTML表单验证;5.修改HTML表单.而通过Struts直接将Form表单递交给Hibernate这种方法则灵活性很强. 当数据库的结构发生变更时,我们做三次修改即可达到上述效果:1.修改Hibernate映射;2.修改HTML表单验证;3.修改HTML表单验证. 因为我们的控制层是直接将表单交给Beans,再通过Hibernate写入数据库的,中间层的代码除了验证外非常小. 因此,通过Struts可以减少很多代码,并且,当数据模型的变更时,修改起来相对简单! 这就是使用Struts+Hibernate的好处之一吧! 下面就让我们来看一下整个操作的过程:
1. 准备工作.
新建 J2EE工程,加入Struts及Hibernate. 设定好MySQL连接驱动, 打开MyEclipse Database Explorer 视图,新建连接Stulib,并将数据库的结构通过Hibernate映射成JavaBeans
2. 新建一个From,一个Action,一个ActionFrom.其结构图如下:
上图是Struts的struts-config.xml配置图,其配置源码如下:
xml version="1.0" encoding="UTF-8"?>
DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "">
<struts-config>
<data-sources />
<form-beans>
<form-bean name="UserReg" type="wills.Username" />
form-beans>
<global-exceptions />
<global-forwards />
<action-mappings>
<action input="/UserReg.jsp" path="/UserReg" name="UserReg" scope="request" type="wills.UserReg" />
action-mappings>
<message-resources parameter="wills.struts.ApplicationResources" />
struts-config>
这里有三个重点需要说明: 1.form-beans配置,其名称首先对应于通过Hibernate映射成的JavaBeans名称,其次要与action-mappings 中的action 中的name的名称一致.
2.action的说明 input 是指是哪个网页提交过来的Form;path 是指在URL中显示的一个路径;name是指此表单对应于哪个JavaBeans ,这个JavaBeans必需继承ActionFrom类;scope 表示此表单的作用域;type 则是对应于哪个Servlet 来处理这个表单. 3. struts-config.xml中所出现的的type中对应的字符串实际上是表示对应于项目中的哪个Beans或Servlet.
下面是UserReg.jsp中的代码: 请注意突出代码.
<body>
<html:form action="/UserReg" method="post" focus="login">
<table border="0">
<tr>
<td>Login:td>
<td><html:text property="name" />td>
tr>
<tr>
<td>Password:td>
<td><html:password property="pwd" />td>
tr>
<tr>
<td colspan="2" align="center"><html:submit />td>
tr>
table>
html:form>
body>
下面是wills.UserReg的代码:
package wills;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class UserReg extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// 这条语句就将相对应的From交给JavaBeans了.
Username ws = (Username) form;
// 经过测度,我们可以正确地取出JavaBeans中的值.
System.out.print(ws.getName());
// TODO Auto-generated method stub
return null;
}
}
下面是对Hibernate生成的抽象类的修改. AbstractUsername.java 代码如下:
我们可以与Hibernate生成的代码比较发现只是多了 extends ActionFrom, 当然,我们也可以在AbstractUsername.java中添加 reset(), validate(),…等方法.
public abstract class AbstractUsername extends ActionForm implements
Serializable {
private int Id;
private String name;
…..
Public void setName(String)
{
…
}
}
其总体结构如上图所示.
3. 总结: 通过这种方式进行网站应用开发,当需求发生改更时有一定的优势,而它的缺点就是配置非常麻烦.不过借助于Eclipse 开发工具,工作变得相对简单.但是,当配置更改时还是需要特别注意.
到今天为止,已完成了以下的工作:
1. Apache 与Tomcat的整合.
2. 数据库的建模及Hibernate的配置.
3. JavaScript与Servlet之间的通讯.
4. Struts与Hibernate 之间的整合.
有以上的基础,下面的开发将变得透明而又简单. 这是因为:第一,对数据库的操作逻辑是固定的,无论数据库的模型是否发生变理;第二,对在什么时候使用JavaScript通过XMLHTTP与Servlet进行通讯有一定的了解;第三,对Struts与Hibernate的配合操作有一定的了解.
2006年1月19日 星期四 22时0分31秒
在Hibernate3 中发现了一个不能查询与插入中文字符的问题,通过网上查阅资源,原来是Hibernate3中的一个Bug, 最后没有办法,在JSP2.0技术手册中看到可以通过Filter来解决中文问题,将其代码摘录下来,结果发现,不仅HTML传过来的表单没有了任何中文问题,而且Hibernate的中文问题也解决了.下面就将整个过程描述如下:
因为Filter 的是起过滤的作用,它运行于Servlet 的 Service()之前,所以,在表单还没有到达Service()之前会执行Filter. 添加Filter 的方法和我们添加Servlet 的方法是一样的. 都要配置Web.xml, 下面是解决中文问题的Web.xml配置:
<filter>
<filter-name>setCharacterEncodingfilter-name>
<filter-class>wills.servlet.SetCharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>gb2312param-value>
init-param>
filter>
<filter-mapping>
<filter-name>setCharacterEncodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
上面的配置说明了: 1.定义了一个Filter setCharacterEncoding 它的执行路径是: wills.servlet.SetCharaterEncodingFilter 初始化参数是: encoding 和 gb2312等下我们来看它们是什么意思. 2. 定义了对于哪些文件通过的时候执行setCharacterEncoding 上面我们可以看出所有的相关Jsp也好,Serlet也好等等,都执行setCharacterEncoding. 下面是setCharacterEncoding.java
package wills.servlet;
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;
public class SetCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = true;
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
// Pass control on to the next filter
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}
此方法基本解决了通讯中的中文问题,但是在JavaScript与XML中行不通,解决的办法是: 在Servlet的第一行添加语句request.setCharacterEncoding("utf-8"); 原因可能是Filter对Stream流的信息也进行了编码,所以必须将编码变成UTF-8.
2006年2月2日 星期四 18时42分47秒
在Structs-config.xml的forward的配置中添加redirect=”true” 要注意, redirect中重新定位,将会清除本页面范围以内的所有的变量的值. 而不用redirect则将造成表单重复递交,解决的办法是,可以在后台将表单清除.