最近给一个非常好学却找不到方向的朋友讲struts和hibernate框架的基础入门,突然发现自己对这两个框架有些生疏了。这一年来的工作中都没有使用过struts和hibernate做开发,所以在给他讲解的同时也是自己复习和加深印象的过程,有些技术细节确实需要用心记忆。
今天去面试,收获了3点感想:
- 在学习技术的过程中,博学是好事,但专精更加重要。
- 不要过于依赖搜索引擎和API手册,这样会使自己对任何事情都拿不准主意,总是模棱两可,而且会养成惰性,养成不愿意记忆的坏毛病。
- 加强对技术细节的掌握,只有对技术细节有着精准的掌握之后再在此基础上进行更高层次的扩展和延伸,才能成为一个优秀的架构师。
下面把给朋友讲的struts和hibernate框架的基本使用的代码贴上来,主要是贴代码,需要注意的地方会另外文字说明。
参考了北大青鸟的教材《开发基于Struts/Spring/Hibernate/Ajax的网上信息发布平台》一书中的示例项目,在此我做了精简。
主要功能就是会员登陆、注册,还对有房屋信息的CRUD操作。
需要用的lib有这些:
antlr-2.7.6.jar
c3p0-0.9.1.jar
commons-beanutils.jar
commons-collections-3.1.jar
commons-digester.jar
commons-fileupload.jar
commons-logging.jar
commons-validator.jar
dom4j-1.6.1.jar
hibernate3.jar
jakarta-oro.jar
javassist-3.9.0.GA.jar
jta-1.1.jar
log4j-1.2.15.jar
mysql-connector-java-5.0.4-bin.jar
slf4j-api-1.5.8.jar
slf4j-log4j12-1.5.6.jar
struts.jar
数据库SQL脚本(MySQL):
1CREATE DATABASE IF NOT EXISTS house DEFAULT CHARACTER SET = 'utf8'; 2USE house; 3 4CREATE TABLE IF NOT EXISTS member 5( 6 id INT UNSIGNED AUTO_INCREMENT NOT NULL, 7 login_id VARCHAR(32) NOT NULL, 8 login_pwd VARCHAR(32) NOT NULL, 9 PRIMARY KEY (id) 10) ENGINE = 'InnoDB' CHARACTER SET 'utf8'; 11 12CREATE TABLE IF NOT EXISTS house_type 13( 14 id INT UNSIGNED AUTO_INCREMENT NOT NULL, 15 type_name VARCHAR(32) NOT NULL, 16 PRIMARY KEY (id) 17) ENGINE = 'InnoDB' CHARACTER SET = 'utf8'; 18 19CREATE TABLE IF NOT EXISTS house_info 20( 21 id INT UNSIGNED AUTO_INCREMENT NOT NULL, 22 member_id INT UNSIGNED NOT NULL, 23 type_id INT UNSIGNED NOT NULL, 24 living_room INT UNSIGNED NOT NULL, 25 bedroom INT UNSIGNED NOT NULL, 26 information VARCHAR(500) NOT NULL, 27 rent DECIMAL(10, 4) NOT NULL, 28 title VARCHAR(200) NOT NULL, 29 post_date DATETIME NOT NULL, 30 telephone VARCHAR(11) NOT NULL, 31 real_name VARCHAR(20) NOT NULL, 32 PRIMARY KEY (id), 33 FOREIGN KEY (member_id) REFERENCES member(id), 34 FOREIGN KEY (type_id) REFERENCES house_type(id) 35) ENGINE = 'InnoDB' CHARACTER SET 'utf8';
Hibernate.cfg.xml的配置:
1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5<hibernate-configuration> 6 <session-factory> 7 <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 8 <property name="connection.url"> 9 <![CDATA[ 10 jdbc:mysql://127.0.0.1/house?useUnicode=true&characterEncoding=utf-8 11 ]]> 12 </property> 13 <property name="connection.username">root</property> 14 <property name="connection.password">root</property> 15 <property name="c3p0.min_size">5</property> 16 <property name="c3p0.max_size">20</property> 17 <property name="c3p0.timeout">300</property> 18 <property name="c3p0.max_statements">50</property> 19 <property name="c3p0.idle_test_period">3000</property> 20 <property name="show_sql">true</property> 21 <property name="format_sql">true</property> 22 <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 23 <property name="current_session_context_class">thread</property> 24 25 <mapping resource="com/house/entity/HouseInfo.hbm.xml" /> 26 <mapping resource="com/house/entity/HouseType.hbm.xml" /> 27 <mapping resource="com/house/entity/Member.hbm.xml" /> 28 </session-factory> 29</hibernate-configuration>
Hibernate的SessionFactory工具类,代码来自《Hibernate实战 第2版 (Java Persistence with Hibernate)》:
1package com.house.util; 2 3import org.hibernate.HibernateException; 4import org.hibernate.SessionFactory; 5import org.hibernate.cfg.Configuration; 6 7public class HibernateUtil { 8 9 private static SessionFactory sessionFactory; 10 static { 11 try { 12 sessionFactory = new Configuration().configure() 13 .buildSessionFactory(); 14 } catch (HibernateException e) { 15 e.printStackTrace(); 16 } 17 } 18 19 public static SessionFactory getSessionFactory() { 20 return sessionFactory; 21 } 22 23 public static void shutdown() { 24 getSessionFactory().close(); 25 } 26}
下面是HouseInfo.hbm.xml映射文件的代码,其它的映射文件省略:
1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5<hibernate-mapping package="com.house.entity"> 6 <class name="HouseInfo" table="house_info"> 7 <id name="id" column="id" type="integer"> 8 <generator class="identity" /> 9 </id> 10 <property name="livingRoom" column="living_room" not-null="true" 11 type="integer" /> 12 <property name="bedroom" column="bedroom" not-null="true" 13 type="integer" /> 14 <property name="information" column="information" not-null="true" 15 type="string" /> 16 <property name="rent" column="rent" not-null="true" type="big_decimal" /> 17 <property name="title" column="title" not-null="true" type="string" /> 18 <property name="postDate" column="post_date" not-null="true" 19 type="date" /> 20 <property name="telephone" column="telephone" not-null="true" 21 type="string" /> 22 <property name="realName" column="real_name" not-null="true" 23 type="string" /> 24 25 <many-to-one name="member" column="member_id" not-null="true" 26 class="Member" lazy="false" /> 27 <many-to-one name="houseType" column="type_id" not-null="true" 28 class="HouseType" lazy="false" /> 29 </class> 30</hibernate-mapping>
InitUpdateAction代码,这步是更新初始化的操作。
我们需要先进行查询将值放入其对应的form中,然后JSP页面中就可以使用struts标签来显示form中的值。
1package com.house.action.house; 2 3import java.util.List; 4import javax.servlet.http.HttpServletRequest; 5import javax.servlet.http.HttpServletResponse; 6import org.apache.struts.action.Action; 7import org.apache.struts.action.ActionForm; 8import org.apache.struts.action.ActionForward; 9import org.apache.struts.action.ActionMapping; 10import com.house.dao.HouseInfoDao; 11import com.house.dao.HouseTypeDao; 12import com.house.entity.HouseInfo; 13import com.house.entity.HouseType; 14import com.house.form.UpdateHouseForm; 15 16public class InitUpdateAction extends Action { 17 18 private HouseInfoDao houseInfoDao; 19 private HouseTypeDao houseTypeDao; 20 21 public InitUpdateAction() { 22 houseInfoDao = new HouseInfoDao(); 23 houseTypeDao = new HouseTypeDao(); 24 } 25 26 @Override 27 public ActionForward execute(ActionMapping mapping, ActionForm form, 28 HttpServletRequest request, HttpServletResponse response) 29 throws Exception { 30 Integer id = Integer.valueOf(request.getParameter("id")); 31 // initialize houseInfo 32 HouseInfo houseInfo = houseInfoDao.searchHouseInfo(id); 33 UpdateHouseForm updateHouseForm = (UpdateHouseForm) form; 34 // initialize houseInfo form 35 updateHouseForm.setId(id); 36 updateHouseForm.setMember(houseInfo.getMember()); 37 updateHouseForm.setHouseType(houseInfo.getHouseType()); 38 updateHouseForm.setLivingRoom(houseInfo.getLivingRoom()); 39 updateHouseForm.setBedroom(houseInfo.getBedroom()); 40 updateHouseForm.setInformation(houseInfo.getInformation()); 41 updateHouseForm.setRent(houseInfo.getRent()); 42 updateHouseForm.setTitle(houseInfo.getTitle()); 43 updateHouseForm.setTelephone(houseInfo.getTelephone()); 44 updateHouseForm.setRealName(houseInfo.getRealName()); 45 // initialize houseType 46 List<HouseType> houseTypeList = houseTypeDao.searchAllHouseType(); 47 request.setAttribute("houseTypeList", houseTypeList); 48 return mapping.findForward("update"); 49 } 50 51}
上面的Action所对应的UpdateHouseForm代码如下:
1package com.house.form; 2 3import java.math.BigDecimal; 4import java.util.Date; 5import org.apache.struts.action.ActionForm; 6import com.house.entity.HouseType; 7import com.house.entity.Member; 8 9public class UpdateHouseForm extends ActionForm { 10 11 private static final long serialVersionUID = 1L; 12 13 private Integer id; 14 private Member member = new Member(); 15 private HouseType houseType = new HouseType(); 16 private Integer livingRoom; 17 private Integer bedroom; 18 private String information; 19 private BigDecimal rent; 20 private String title; 21 private Date postDate; 22 private String telephone; 23 private String realName; 24 25 public Integer getId() { 26 return id; 27 } 28 29 public void setId(Integer id) { 30 this.id = id; 31 } 32 33 public Member getMember() { 34 return member; 35 } 36 37 public void setMember(Member member) { 38 this.member = member; 39 } 40 41 public HouseType getHouseType() { 42 return houseType; 43 } 44 45 public void setHouseType(HouseType houseType) { 46 this.houseType = houseType; 47 } 48 49 public Integer getLivingRoom() { 50 return livingRoom; 51 } 52 53 public void setLivingRoom(Integer livingRoom) { 54 this.livingRoom = livingRoom; 55 } 56 57 public Integer getBedroom() { 58 return bedroom; 59 } 60 61 public void setBedroom(Integer bedroom) { 62 this.bedroom = bedroom; 63 } 64 65 public String getInformation() { 66 return information; 67 } 68 69 public void setInformation(String information) { 70 this.information = information; 71 } 72 73 public BigDecimal getRent() { 74 return rent; 75 } 76 77 public void setRent(BigDecimal rent) { 78 this.rent = rent; 79 } 80 81 public String getTitle() { 82 return title; 83 } 84 85 public void setTitle(String title) { 86 this.title = title; 87 } 88 89 public Date getPostDate() { 90 return postDate; 91 } 92 93 public void setPostDate(Date postDate) { 94 this.postDate = postDate; 95 } 96 97 public String getTelephone() { 98 return telephone; 99 } 100 101 public void setTelephone(String telephone) { 102 this.telephone = telephone; 103 } 104 105 public String getRealName() { 106 return realName; 107 } 108 109 public void setRealName(String realName) { 110 this.realName = realName; 111 } 112 113}
注意上面的UpdateHouseForm,里面的包含有其它类型的对象,但在这个地方被初始化了。其目的是因为在更新操作的form提交时,若表单中包含有类似以member.loginId的元素,则其对应的form中的member必须是被实例化,否则会引发异常。
下面是Struts标签库中的html标签的基本实用,这里实现了表单元素的value值的初始化。
1<%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> 4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 5 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 6<html xmlns="http://www.w3.org/1999/xhtml"> 7<head> 8<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 9<meta http-equiv="Expires" content="0" /> 10<link type="text/css" href="https://my.oschina.net/house/style/style.css" rel="stylesheet" /> 11<script type="text/javascript"> 12function validateForm() { 13 var inputs = document.getElementsByTagName('input'); 14 for (var i = 0; i < inputs.length; i++) { 15 if (inputs[i].value == "") { 16 alert("请将表单信息补充完整!"); 17 return false; 18 } 19 } 20 return true; 21} 22</script> 23<title>编辑房屋信息</title> 24</head> 25 26<body> 27<h1>欢迎使用房屋信息管理系统</h1> 28<html:form action="/updateHouseInfo" method="post" 29 onsubmit="return validateForm();"> 30 <table border="0" cellspacing="1" cellpadding="0" class="detail"> 31 <tr> 32 <th colspan="2"><h2>编辑房屋信息</h2></th> 33 </tr> 34 <tr> 35 <th>编号</th> 36 <td><html:text property="id" readonly="true" /></td> 37 </tr> 38 <tr> 39 <th>发布者</th> 40 <td> 41 <html:text property="member.loginId" readonly="true" /> 42 <html:hidden property="member.id" /> 43 </td> 44 </tr> 45 <tr> 46 <th>类型</th> 47 <td> 48 <html:select property="houseType.id"> 49 <html:optionsCollection name="houseTypeList" 50 label="typeName" value="id" /> 51 </html:select> 52 </td> 53 </tr> 54 <tr> 55 <th>厅</th> 56 <td><html:text property="livingRoom" /></td> 57 </tr> 58 <tr> 59 <th>室</th> 60 <td><html:text property="bedroom" /></td> 61 </tr> 62 <tr> 63 <th>描述</th> 64 <td><html:text property="information" /></td> 65 </tr> 66 <tr> 67 <th>租金</th> 68 <td><html:text property="rent" /></td> 69 </tr> 70 <tr> 71 <th>标题</th> 72 <td><html:text property="title" /></td> 73 </tr> 74 <tr> 75 <th>电话</th> 76 <td><html:text property="telephone" /></td> 77 </tr> 78 <tr> 79 <th>联系人</th> 80 <td><html:text property="realName" /></td> 81 </tr> 82 <tr> 83 <th colspan="2" style="text-align: right;"> 84 <input type="submit" value="更新" /> 85 <input type="button" value="返回" /> 86 </th> 87 </tr> 88 </table> 89</html:form> 90</body> 91</html>
页面效果如下图(表单元素都已经有默认值):

内容很基础,不啰嗦了,明天还要上班。