Hibernate和Struts进行完美结合

来源:互联网 发布:淘宝卖家评价语长段 编辑:程序博客网 时间:2024/05/29 18:36

 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" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<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>setCharacterEncoding</filter-name>
<filter-class>wills.servlet.SetCharacterEncodingFilter</filter-class>
<init-param>
       <param-name>encoding</param-name>
       <param-value>gb2312</param-value>
</init-param>
       </filter>
       <filter-mapping>
        <filter-name>setCharacterEncoding</filter-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.



在Structs-config.xml的forward的配置中添加redirect=”true” 要注意, redirect中重新定位,将会清除本页面范围以内的所有的变量的值. 而不用redirect则将造成表单重复递交,解决的办法是,可以在后台将表单清除