找回密码
 注册
搜索

:::Eclipse中struts+spring+Hibernate框架的搭建:::

 楼主| 郎心勾妃 2008-8-14 12:51 显示全部楼层 来自: LAN
struts表单校验失败后的整数重显问题假设ActionFormBean中有一个整数类型的属性,如果将其类型定义为int,这个属性的默认值是0;在表单页面中用一个文本框来输入这个属性的值,当文本框中没有填写任何内容时,发送到WEB服务器的参数值为一空字符串"";当ActionFormBean中的其它属性校验失败时,回到表单页面重新显示,这时,与整数字段对应的文本框中显示的内容为0,而不是最初的那样(没有任何内容)。
为此,我们想到了在SpringMVC中所采用的办法:将整数类型的属性定义为Integer类型,这样,该属性的默认值为null,借助<html:property>可将null显示为空字符串,但是,实际运行发现,ActionFormBean中的其它属性校验失败回到表单页面重新显示时,与Integer类型的属性对应的文本框中显示的内容仍然为0。这说明struts在将请求参数组装进ActionFormBean对象中时、它也会将内容为空字符串""的请求参数(文本框中不填写任何内容时即会出现这种情况)装配到ActionFormBean中,并且将空字符串""转变成0值的Integer数据。对于这种情况,我们想到了将原本属于整数的属性设计成String类型的妥协解决办法,但觉得不是很理想,想知道各位有经验的朋友对这种情况是如何处理的?特向各位朋友请教。下面是问题的完整描述:
假设有一个注册课程的表单,其中包含有“课程名”、“学分”等字段信息,显然“课程名”是String类型,“学分”是整数类型,与这个表单对应的ActionForm可以设计成如下形式:
public class RegisterCourseForm extends ActionForm
{
    private String name;  
    public String getName()
    {        return name;
    } 字串3
    public void setName(String name) {
       this.name = name;
    }
   
    private Integer score; 字串6
    public Integer getScore()
    {
       return score;
    }
    public void setScore(Integer score)
    {
       this.score = score;
    }
     public ActionErrors validate(ActionMapping mapping,HttpServletRequest request)
    {
        if("".equals(name))
        {
            ActionErrors errors = new ActionErrors();
            errors.add("name",new ActionMessage("required.name"));
            return errors;
        }
        return null;
    }
   
}
注册课程的表单页面的主要内容如下:
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>

<html:form action="/registerCourse">
     name : <html:text property="name"/><html:errors property="name"/><br/>
     score : <html:text property="score"/><html:errors property="score"/><br/>
     <html:submit/>
</html:form>  
为了让这个用例能够运行,同时又简化整个程序的代码,我们直接使用Struts提供的ForwardAction,大家也可以使用MyEclipse自动为我们创建的没有任何业务逻辑的Action。在struts-config.xml文件中的配置片段如下:
   <form-bean name="registerCourseForm" type="cn.itcast.form.RegisterCourseForm" />
......
    <action parameter="/WEB-INF/jsp/registerCourse.jsp"
            path="/index" type="org.apache.struts.actions.ForwardAction"/>
  
    <action
      input="/WEB-INF/jsp/registerCourse.jsp"
      name="registerCourseForm"
      path="/registerCourse"
      scope="request"
      type="org.apache.struts.actions.ForwardAction"
       parameter="/WEB-INF/jsp/registerCourse.jsp"     
    />  
(1)首先在浏览器地址栏中输入:8080/CourseManager/index.do,请求交给第一个Action处理,浏览器中显示出registerCourse.jsp页面;
(2)在注册课程的表单页面不填写任何内容,直接提交表单,这时候表单校验失败(即RegisterCourseForm.validate方法返回ActionErrors对象),浏览器重新显示registerCourse.jsp页面。registerCourse.jsp页面除了显示出错误描述信息之外,还在表单中显示出上次输入的内容,现在遇到的问题是:我们上次提交表单时,并没有在学分(score)文本框中输入任何内容,但这次重显表单时,在学分(score)文本框中添入了一个0。
回复 支持 反对

使用道具 举报

 楼主| 郎心勾妃 2008-8-14 12:52 显示全部楼层 来自: LAN
我猜想这是因为struts在将请求参数组装进RegisterCourseForm对象中时、将空字符串""的请求参数(文本框中不填写任何内容时即会出现这种情况)转变成了0值的Integer数据。查看struts的源代码,了解到请求参数组装到FormBean中的方法调用过程如下:
ActionServlet.doGet/doPost-->ActionServlet.process-->RequestProcessor.process-->
RequestProcessor.processActionForm,RequestProcessor.processPopulate-->RequestUtils.populate-->
BeanUtils.populate-->BeanUtilsBean.setProperty(Object bean, String name, Object value) 字串4 可见,将请求参数组装成FormBean的属性时,最终调用的是BeanUtilsBean.setProperty方法,可能的原因就是BeanUtilsBean.setProperty方法在为JavaBean的整数类型的属性进行赋值时,会将空字符串""转换成0。BeanUtilsBean类位于apache的commons-beanutils包中,大家从struts安装包的lib目录中能够找到commons-beanutils.jar包及相关的依赖包。我安排王涛写了一个程序,来验证这种效果:
package com.tony;
public class TestInteger {
  public static void main(String[] args) {
  
  Student student = new Student();
  try {
   BeanUtilsBean.getInstance().setProperty(student,"name","Tony");
   BeanUtilsBean.getInstance().setProperty(student,"age","");
   System.out.print(student);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
}
} 字串1
package com.tony;
public class Student {
private String name;
private Integer age;
public Integer getAge() {
  return age;
}
public void setAge(Integer age) {
  this.age = age;
}
public String getName() {
  return name;
}
public void setName(String name) {
  this.name = name;
}
public String toString()
{
  return this.name + ":" + this.age;
}
}
程序最后打印出来的结果为Tony:0,这说明BeanUtilsBean.setProperty方法确实将空字符串""转换成了整数类型的0。
回复 支持 反对

使用道具 举报

 楼主| 郎心勾妃 2008-8-14 12:55 显示全部楼层 来自: LAN
hibernate的jar包的作用说明

Hibernate一共包括了23个jar包,令人眼花缭乱。本文将详细讲解Hibernate每个jar包的作用,便于你在应用中根据自己的需要进行取舍。

下载Hibernate,例如2.0.3稳定版本,解压缩,可以看到一个hibernate2.jar和lib目录下有22个jar包:

hibernate2.jar:

Hibernate的库,没有什么可说的,必须使用的jar包

cglib-asm.jar:

CGLIB库,Hibernate用它来实现PO字节码的动态生成,非常核心的库,必须使用的jar包

dom4j.jar:

dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的。dom4j是一个非常非常优秀的Java XMLAPI,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBMdeveloperWorks上面可以找到一篇文章,对主流的Java XMLAPI进行的性能、功能和易用性的评测,dom4j无论在那个方面都是非常出色的。我早在将近两年之前就开始使用dom4j,直到现在。如今你可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这是必须使用的jar包,Hibernate用它来读写配置文件。

odmg.jar:

ODMG是一个ORM的规范,Hibernate实现了ODMG规范,这是一个核心的库,必须使用的jar包。  

commons-collections.jar:

Apache Commons包中的一个,包含了一些Apache开发的集合类,功能比java.util.*强大。必须使用的jar包。

commons-beanutils.jar:

Apache Commons包中的一个,包含了一些Bean工具类类。必须使用的jar包。

commons-lang.jar:

Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。

commons-logging.jar:

ApacheCommons包中的一个,包含了日志功能,必须使用的jar包。这个包本身包含了一个SimpleLogger,但是功能很弱。在运行的时候它会先在CLASSPATH找log4j,如果有,就使用log4j,如果没有,就找JDK1.4带的java.util.logging,如果也找不到就用SimpleLogger。commons-logging.jar的出现是一个历史的的遗留的遗憾,当初Apache极力游说Sun把log4j加入JDK1.4,然而JDK1.4项目小组已经接近发布JDK1.4产品的时间了,因此拒绝了Apache的要求,使用自己的java.util.logging,这个包的功能比log4j差的很远,性能也一般。

后来Apache就开发出来了commons-logging.jar用来兼容两个logger。因此用commons-logging.jar写的log程序,底层的Logger是可以切换的,你可以选择log4j,java.util.logging或者它自带的SimpleLogger。不过我仍然强烈建议使用log4j,因为log4j性能很高,log输出信息时间几乎等于System.out,而处理一条log平均只需要5us。你可以在Hibernate的src目录下找到Hibernate已经为你准备好了的log4j的配置文件,你只需要到Apache 网站去下载log4j就可以了。commons-logging.jar也是必须的jar包。   

使用Hibernate必须的jar包就是以上的这几个,剩下的都是可选的。

ant.jar:

Ant编译工具的jar包,用来编译Hibernate源代码的。如果你不准备修改和编译Hibernate源代码,那么就没有什么用,可选的jar包

optional.jar:

Ant的一个辅助包。

c3p0.jar:

C3PO是一个数据库连接池,Hibernate可以配置为使用C3PO连接池。如果你准备用这个连接池,就需要这个jar包。

proxool.jar:

也是一个连接池,同上。

commons-pool.jar, commons-dbcp.jar:

DBCP数据库连接池,Apache的Jakarta组织开发的,Tomcat4的连接池也是DBCP。

实际上Hibernate自己也实现了一个非常非常简单的数据库连接池,加上上面3个,你实际上可以在Hibernate上选择4种不同的数据库连接池,选择哪一个看个人的偏好,不过DBCP可能更通用一些。另外强调一点,如果在EJB中使用Hibernate,一定要用AppServer的连接池,不要用以上4种连接池,否则容器管理事务不起作用。

connector.jar:

JCA 规范,如果你在App Server上把Hibernate配置为Connector的话,就需要这个jar。不过实际上一般App Server肯定会带上这个包,所以实际上是多余的包。  字串7

jaas.jar:

JAAS是用来进行权限验证的,已经包含在JDK1.4里面了。所以实际上是多余的包。

jcs.jar:

如果你准备在Hibernate中使用JCS的话,那么必须包括它,否则就不用。

jdbc2_0-stdext.jar:

JDBC2.0的扩展包,一般来说数据库连接池会用上它。不过App Server都会带上,所以也是多余的。

jta.jar:

JTA规范,当Hibernate使用JTA的时候需要,不过App Server都会带上,所以也是多余的。

junit.jar:

Junit包,当你运行Hibernate自带的测试代码的时候需要,否则就不用。

xalan.jar, xerces.jar, xml-apis.jar:

Xerces是XML解析器,Xalan是格式化器,xml-apis实际上是JAXP。一般AppServer都会带上,JDK1.4也包含了解析器,不过不是Xerces,是Crimson,效率比较差,不过Hibernate用XML只不过是读取配置文件,性能没什么紧要的,所以也是多余的。

[ 本帖最后由 郎心勾妃 于 2008-8-14 12:59 编辑 ]
回复 支持 反对

使用道具 举报

 楼主| 郎心勾妃 2008-8-14 12:59 显示全部楼层 来自: LAN
Hibernate 工作原理图

回复 支持 反对

使用道具 举报

 楼主| 郎心勾妃 2008-8-14 13:01 显示全部楼层 来自: LAN
Hibernate基本配置文件学习笔记ibernate的基本配置文件有两种:hibernate.cfg.xml和.hbm.xml文件。前者包含了Hibernate与数据库的基本连接信息,在Hibernate工作的初始阶段,这些信息被先后加载到Configuration和SessionFactory实例;后者包含了Hibernate的基本映射信息,即系统中每一个类与其对应的数据库表之间的关联信息,在Hibernate工作的初始阶段,这些信息通过hibernate.cfg.xml的mapping节点被加载到Configuration和SessionFactory实例。这两种文件信息包含了Hibernate的所有运行期参数。下面我们用详细的例子来说明这两种文件的基本结构和内容。
一、hibernate.cfg.xml文件:
     <!--该文件的开头信息,对Hibernate而言,该类文件基本都这么开头:)-->
     <?xml version='1.0' encoding='UTF-8'?>
     <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  字串2
     <!-- 正文开始 -->
     <hibernate-configuration>
     <!--下面是数据库的基本连接信息,对一个应用来说,设置一个session-factory节点就够了,除非我们中间使用了多个数据库-->
     <session-factory>
     <!--用户名 -->
     <property name="connection.username">root</property>
     <!--url信息 -->
     <property name="connection.url">jdbc:mysql://localhost:3306/webases</property>
     <!--数据库方言信息-->
     <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
     <!--密码 -->   
     <property name="connection.password">274507</property>
     <!--数据库驱动信息 -->
     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
     <!--指定Hibernate映射文件路径 -->
     <mapping resource="com/Hibernate/test_products.hbm.xml" />
     </session-factory>
     </hibernate-configuration>
二、.hbm.xml文件:
    由于Hibernate的关联关系包含了一对一、一对多、多对一和多对多等四种类型,因此,也就有分别与之对应的四种.hbm.xml文件。下面我们就以比较常用的双向“一对多”型关联关系为例,介绍一下.hbm.xml文件的基本结构和内容。有关Hibernate更详细的内容,请参考相关文资料。
     该例中有两张数据库表:一张为“省”表,另一张为“市”表,所用的数据库为MySQL。二者的建表语句如下:   
     CREATE TABLE IF NOT EXISTS Province
     (
        Guid                      INT               NOT NULL AUTO_INCREMENT,
        Provincename         VARCHAR(16)  NOT NULL,
        PRIMARY KEY (Guid)
     )  TYPE=InnoDB;  
     CREATE TABLE IF NOT EXISTS City
     (
        Guid                      INT               NOT NULL AUTO_INCREMENT,   
        Cityname               VARCHAR(32)  NOT NULL,
        ProvinceID              INT              NOT NULL,
        PRIMARY KEY (Guid)
     )  TYPE=InnoDB;
     ALTER TABLE City ADD CONSTRAINT CityRFProvince FOREIGN KEY (ProvinceID)
     REFERENCES Province (Guid) ON DELETE CASCADE ON UPDATE RESTRICT;
回复 支持 反对

使用道具 举报

 楼主| 郎心勾妃 2008-8-14 13:01 显示全部楼层 来自: LAN
Province表为主控方,City表为被控方,两者之间存在双向的一对多的关系。表City通过外键ProvinceID与表Province进行关联:当表Province中有记录被删除时,表City中相关记录亦被删除;当表Province中有记录被保存或者更新时,表City中相关记录无任何变化。
     将Hibernate自带工具Middlegen生成的Province.hbm.xml文件进行修改,内容如下:
     <!--该文件的开头信息,对Hibernate而言,该类文件基本都这么开头:)-->
     <?xml version="1.0"?>
     <!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"  
     >  
     <!-- 映射文件开始 -->   
     <hibernate-mapping>
     <!-- 下面的class节点定义了Province类和对应数据库表之间的关联关系 -->
     <class
        name="com.xxx.hibernate.Province"
        table="Province"
     >  
     <!-- 下面的两个节点定义了Province类中的属性和该类对应数据库表中的字段之间的关联关系,其中Guid为对应数据库表的主键 -->
     <id
        name="guid"
        type="int"
        column="Guid"  字串7
     >
     <generator class="native" />
     </id>
     <property
        name="provincename"
        type="java.lang.String"
        column="Provincename"
        not-null="true"
        length="16"
     >   
     </property>
     <!-- 下面的set节点定义了Province类和City类之间的”一对多“型关联关系 -->
     <set
        name="cities"<!-- 集合属性的名称 -->
        lazy="true"<!-- 是否允许延迟加载 -->
        inverse="true"<!-- 定义这个集合是否为双向关联关系中的方向一端 -->
        cascade="delete"<!-- 定义有关操作是否关联到子实体(此处指City类对象) -->
     >
     <key>
        <column name="ProvinceID" /><!-- 定义集合所对应的数据库表的外键 -->
     </key>
     <one-to-many
        class="com.xxx.hibernate.City"<!-- 定义集合所属的类-->
     />
     </set>  
     </class>
     </hibernate-mapping>   
     将Hibernate自带工具Middlegen生成的City.hbm.xml文件进行修改,内容如下:
     <!--该文件的开头信息,对Hibernate而言,该类文件基本都这么开头:)-->
     <?xml version="1.0"?>
     <!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"
     >
回复 支持 反对

使用道具 举报

 楼主| 郎心勾妃 2008-8-14 13:03 显示全部楼层 来自: LAN
<!-- 映射文件开始 -->   
     <hibernate-mapping>
     <!-- 下面的class节点定义了City类和对应数据库表之间的关联关系 -->
     <class
        name="com.xxx.hibernate.City"
        table="City"
     >  
     <!-- 下面的两个节点定义了City类中的属性和该类对应数据库表中的字段之间的关联关系,其中Guid为对应数据库表的主键-->
     <id
        name="guid"
        type="int"
        column="Guid"
     >
     <generator class="native" />  字串9
     </id>   
     <property
        name="cityname"
        type="java.lang.String"
        column="Cityname"
        not-null="true"
        length="32"
     >   
     </property>
     <!-- 下面的many-to-one节点定义了Province类和City类之间的”一对多“型关联关系 -->
     <many-to-one
        name="province"<!-- 属性名称 -->
        class="com.xxx.hibernate.Province"<!-- 属性所属的类 -->   
        cascade="none"<!-- 指定哪些操作会从父对象(此处指City类对象)级联到子对象(此处指Province类对象) -->
        outer-join="auto"<!-- 设置父子对象之间是否存在外连接 -->
        not-null="true"<!-- 指定该属性是否一定为非空 -->
     >
     <column name="ProvinceID" /><!-- 定义父对象(此处指City类对象)所对应的数据库表的外键 -->
     </many-to-one>
     </class>  
     </hibernate-mapping>
回复 支持 反对

使用道具 举报

 楼主| 郎心勾妃 2008-8-14 13:04 显示全部楼层 来自: LAN
spring配置文件详解
Spring有四种Bean封装机制:Bean Wrapper机制、BeanFactory机制、ApplicationContext机制、WebContext机制等,它们所对应配置文件的内容也是不同的。下面,我们就以基于BeanFactory机制实现的Spring的三种依赖注入模式为例,介绍一下Spring配置文件的基本内容。
     1、接口注入,示例代码如下:
public interface InterfaceB{
public Object doIt();
}public class ClassC implements InterfaceB{
String str1;
public ClassC(String str1){
This. str1= str1;
}
public Object doIt(){
return "Hello,"+ strl+"!";
}
}
public class ClassA {
private InterfaceB clzB;
public Object doSomething(InterfaceB b) {
clzB = b;
return clzB.doIt();
}
………
}
该情况下的Spring配置文件:bean.xml的内容大致如下:
<beans>
<description>Interface Injection Sample</description>
<bean id="ClassC" <!--ClassC类的别名 -->
class="net.liyb.spring.qs.ClassC"> <!--ClassC类的别名所对应的类 -->
<property name="str1"> <!-- 该属性名对应ClassC类的属性(名称一致) -->
<value>liyb</value> <!-- 该属性值将被绑定到ClassC类的对应属性(str1)上 -->
</property>
</bean>
<bean id="ClassA" <!-- ClassA类的别名 -->
class="net.liyb.spring.qs.ClassA"> <!--ClassA类的别名所对应的类 -->
<property name="clzB"> <!-- 该属性名对应ClassA类的属性(名称一致) -->
<ref local="ClassC"/> <!-- 该属性值将被绑定到ClassA类的对应属性(clzB)上,此处的属性值即"别名"为ClassC所对应的类的实例 -->
</property>
</bean>
</beans>
     2、设值注入,示例代码如下:
public class DIByConstructor {
private final DataSource dataSource;
private final String message;
………  
public setDataSource(DataSource ds) {
this.dataSource = ds;
}
public setmessage(String msg) {
this.message = msg;
}
public getDataSource() {
return this.dataSource;
}
public getmessage() {
return this.message;
}
………
}
该情况下的Spring配置文件:bean.xml的内容大致如下:
<beans>
<description>Values Injection Sample</description>
<bean id="dataSource" <!-- JndiObjectFactoryBean类的别名 -->
class="org.springframework.jndi.JndiObjectFactoryBean"> <!-- JndiObjectFactoryBean类的别名所对应的类 -->
<property name="jndiName"> <!-- 该属性名对应JndiObjectFactoryBean类的属性(名称一致) -->
<value>java:comp/env/jdbc/sample</value> <!-- 该属性值将被绑定到JndiObjectFactoryBean类的对应属性(jndiName)上 -->
</property>
</bean>
<bean id="DIByConstructor" <!--DIByConstructor类的别名 -->  
class="net.liyb.spring.qs.DIByConstructor"> <!--DIByConstructor类的别名所对应的类 -->
<property name="message"> <!-- 该属性名对应DIByConstructor类的属性(名称一致) -->
<value>HeLLo</value> <!-- 该属性值将被绑定到DIByConstructor类的对应属性(message)上-->
</property>
</bean>
<bean id="DIByConstructor" <!--DIByConstructor类的别名 -->
class="net.liyb.spring.qs.DIByConstructor"> <!--DIByConstructor类的别名所对应的类 -->
<property name="dataSource"> <!-- 该属性名对应DIByConstructor类的属性(名称一致) -->
<ref local="dataSource"/> <!-- 该属性值将被绑定到DIByConstructor类的对应属性(dataSource)上,此处的属性值即"别名"为dataSource所对应的类的实例-->
</property>
</bean>
</beans>
     3、构造子注入,示例代码见日志:"Spring核心技术学习总结"中的1.2.3节。此时对应的配置文件同"2、设值注入"中的配置文件是一样的,所以具体内容在此省略。

回复 支持 反对

使用道具 举报

萬歲爺 2008-8-14 21:45 显示全部楼层 来自: 中国辽宁大连
我有这视频..:lol:
回复 支持 反对

使用道具 举报

 楼主| 郎心勾妃 2008-8-15 00:26 显示全部楼层 来自: 中国辽宁大连

回复 #39 萬歲爺 的帖子

晕,不早说阿
啥时候传给我
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

  • 0 关注
  • 3 粉丝
  • 10 帖子
 

天健社区APP