本文将介绍Struts2与Hibernate的整合,两东西的整合并不需要用到Spring,完全可以各司其职,Struts2完成Java文件与Jsp页面交互,Hibernate完成数据库到Java文件的交互。
一、基本目标
还是那张在Mysql中已经用烂的Testtable表。
在index.jsp点击查询之后,能够把这张表的所有内容输出出来。而且表格是梅花间竹的不同颜色。当然这个例子已经很多书籍上说过了。
目录结构如下,严格按照MVC思想。
二、基本准备
1、这里就不再多说了,在Eclipse for Javaee新建一个Web工程之后,把Struts2必备的包,具体可以参考《【Struts2】Struts2纯手工安装、配置以及Helloworld,以最新版struts 2.3.20 GA做例子》(点击打开链接)与Hibernate必要的包,具体可以参考《【Hibernate】Hibernate的在Eclipse+Mysql的配置、安装,纯Java,利用Annotation与HQL完成数据库的增删改查》(点击打开链接)放到WEB-INF文件夹下的lib目录。最后lib文件夹如下图:
2、之后在web.xml只需要配好Struts2就可以了,Hibernate是一个Java插件来的,有包就可以用了。无须配置,具体如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
三、制作过程
1、首先先写好持久层M吧。在src根目录下的hibernate.cfg.xml与《【Hibernate】Hibernate的层次划分,Hibernate4.3的初始化的新写法》(点击打开链接)唯一的区别就是最后一行指明Test表的映射Java是test.model.TestTable.java。而不是根目录下的TestTable.java:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!--所用的数据库驱动 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!--所用的数据库登陆密码 --> <property name="hibernate.connection.password">root</property> <!--所用的数据库名称为test,根据实际更改 --> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property> <!--所用的数据库用户名 --> <property name="hibernate.connection.username">root</property> <!--所用的数据库方言,与所用数据库驱动一样,可以在网上查到,这里是mysql --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> <property name="hibernate.format_sql">true</property> <!--如果是update表明Hibernate将保留原来的数据记录,插入时把新记录添加到已有的表,--> <!--如果是create,则总是创建新的表,如果原来数据库已有的这个表,则这个表的记录会被全部清洗 --> <property name="hibernate.hbm2ddl.auto">update</property> <!--罗列Testtable表与Java文件的映射,这里就Testtable.java的一张表,所以就写一个Testtable.java --> <mapping class="test.model.Testtable" /> </session-factory> </hibernate-configuration>
至于TestTable.java则一字未改,TestTable还是那个TestTable.java,只是因为这里是在Web工程的test.model包中,所以打头多了一个包名。
package test.model; import javax.persistence.*; @Entity @Table(name = "testtable") public class Testtable { private int id; private String username; private String number; // 表示主键与自动生成项 @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } @Column(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Column(name = "number") public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } @Override public String toString() { return id + "," + username + "," + number; } }
2、同样一直未改的还有数据库服务类dbDAO.java,数据库服务完全通过hql语句操作,以后要搞直接使用本类中的方法就可以了。再也不用管Hibernate中奇奇怪怪的执行事务的Session初始化问题,不用再也一堆语句,就为了初始化那个Session。
package test.model; import org.hibernate.*; import org.hibernate.cfg.*; import org.hibernate.service.*; import org.hibernate.boot.registry.*; public class dbDAO { private Session session; // 构造函数,初始化Session,相当于连接数据库 public dbDAO() { //这里使用了Hibernate4.3.8的写法,这里Hibernate又把初始化的方法修改了,非常蛋疼 Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()).build(); SessionFactory sessionFactory = cfg .buildSessionFactory(serviceRegistry); this.session = sessionFactory.openSession(); } // 执行查询 public Query query(String hql){ return session.createQuery(hql); } // 执行插入、修改 public void save(Object object){ Transaction transaction=session.beginTransaction(); session.save(object); transaction.commit(); } // 执行删除 public void delete(Object object){ Transaction transaction=session.beginTransaction(); session.delete(object); transaction.commit(); } // 析构函数,中断Session,相当于中断数据库的连接 protected void finalize() throws Exception { if (session.isConnected() || session != null) { session.close(); } } }
3、之后再来写C层。首先在src新建并配置好Struts.xml,指明query这个Action的执行方法是test.action.query.java
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <!-- 在test包里面 --> <package name="test" extends="struts-default"> <!-- action为query的执行方法就是test包中的action包query.java中的run方法 --> <action name="query" class="test.action.query" method="run"> <result name="success">/index.jsp</result> </action> </package> </struts>
4、query.java是本WEB工程中C层的唯一Action类当然也是核心Action类。无须从起来要来任何数据。直接像《【Hibernate】Hibernate的层次划分,Hibernate4.3的初始化的新写法》(点击打开链接)的HQL.java,Java与数据库的交互一样,引入test.model中整个包,里面包含Testtable类与数据库业务逻辑dbDAO.java,直接用HQL语句对Testtable类进行查询取出整张Testtable表。并且把它压入一个存放Testtable类的List动态数组testtableList里面,用getter方法推向前台。当然setter方法完全可以不要,只是利用Eclipse顺带生成而已。
package test.action; import test.model.*; import java.util.*; //这是Struts2必要的支持 import com.opensymphony.xwork2.ActionSupport; //防止报序列号警告 @SuppressWarnings("serial") // Struts2必须继承这个类 public class query extends ActionSupport { private List<Testtable> testtableList; //防止JDK1.5的泛型警告 @SuppressWarnings("unchecked") public String run() { dbDAO db = new dbDAO(); testtableList = db.query("from Testtable").list(); return "success"; } //eclipse自动生成 public List<Testtable> getTesttableList() { return testtableList; } public void setTesttableList(List<Testtable> testtableList) { this.testtableList = testtableList; } }
5、最后是V层,就一个index.jsp,运用到ognl表达式,注意在打头引入s标签,这东西与JSTL表达式也就是c标签《【Servlet】利用Servlet3.0标准与JSTL表达式实现文件上传系统,支持图片上传后显示》(点击打开链接)没有区别,但注意在相当于<c:if>的<s:if>中不兼容EL表达式《【Filter】利用过滤器Filter解决post传递的编码问题与利用EL表达式简化参数传递》(点击打开链接),里面只能是<s:if>自己的东西,其它s标签才可以。先是判断testtableList是否有值,因为在用户没有点查询超级链接的时候,根本不应该输出testtableList这张表。之后利用到相当于<c:foreach>的<s:iterator>输出整张表。输出的过程中判断是否是单行,如果是,则此列背景颜色是灰色。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>查询</title> </head> <body> <a href="./query">查询</a><br /> <s:if test="testtableList"> testTable表如下: <table border="1"> <s:iterator value="testtableList" id="testtable" status="st"> <s:if test="#st.odd"><tr style="background-color: #cccccc"></s:if> <s:else><tr></s:else> <td>${testtable.id}</td> <td>${testtable.username}</td> <td>${testtable.number}</td> </tr> </s:iterator> </table> </s:if> </body> </html>
四、总结与展望
Struts2+Hibernate4整个开发流程中运用到的MVC思想其实与《【Servlet】根据MVC思想设计用户登陆、用户注册、修改密码系统》(点击打开链接)是一模一样的,正如jQuery是JavaScript的框架一样。Struts2+Hibernate4能做到的事情Jsp/JSTL+Servlet+JDBC也能够做到。