java WEB开发中Struts2+Spring+Hibernate 设计模式
一、 Struts2技术
Struts2是一个典型的MVC架构,给软件开发带来很大的方便。
MVC是一种设计模式,它强制性地使应用程序的输入、处理和输出分开。使用MVC模式,应用程序被分成三个核心部件:模型(Model,即M)、视图(View,即V)、控制器(Controller,即C)。它们各自处理自己的任务。
在Struts2中,其中M(业务层)用Java程序(业务类)来实现,V(表示层)用JSP来实现,C用Action类来实现。
1.浏览器发出的请求可以用下列方式:
1) 提交HTML网页form表单
<form action="login" method="GET">
name: <input type="text" name="name"><br>
pass: <input type="password" name="pass"><br>
<input type="submit" value="submit">
</form>
2) 直接在地址栏输入
http://localhost:8080/login?name=abc&pass=123
3) 点击超链接
<html><body>
<a href="login?name=abc&pass=123">test</a>
</body></html>
在struts2编程中login只是请求的逻辑名字,而不是具体的jsp或servlet。
2.过滤器根据请求和Struts.xml配置文件去调用对应的Action
Strtuts2本质上是一个过滤器,所以需要在web.xml中配置一个Struts2的过滤器。具体配置如下:
<filter>
<filter-name>struts2</filter-nam<filter-class>org.apache.struts2.dispatcher.n.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
struts.xml是Struts2非常重要的配置文件,在项目的src下创建一个文件struts.xml,其内容如下:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0 //EN"
"resources/struts-2.1.7.dtd">
<struts>
<constant name="struts.i18n.encoding" value="gbk"></constant>
<package name="team" extends="struts-default">
<action name="login" class="Longin">
<result name="success">/Success.jsp</result>
<result name="error">/Fail.jsp</result>
</action>
</package>
</struts>
请求Action的逻辑名字与Action类的对应关系在这里设定,如:login是逻辑名,Longin是处理请求的实际的Action类名,Struts2过滤器根据请求的逻辑名和struts.xml配置文件调用对应的Action类, Action类中必须有一个execute()方法。
浏览器发出的请求首先经过Struts2过滤器,Struts2过滤器根据请求和Struts2的配置文件调用对应的Action,Action调用执行业务类的方法,然后转发到JSP页面向客户端显示结果。
3.调用业务类
Action类只负责处理请求,通常不处理事务,在Action类的execute()方法中可以调用业务类的方法,业务类负责处理事务,如访问数据库等等。
4.转发
Action类也不显示结果,在Action类的execute()方法返回一个字符串,这个字符串可以是success或error,Struts2过滤器根据success或error转发到指定的JSP页面。
5.应答
JSP负责页面向客户端显示结果。
二、 Spring技术
Spring技术的核心是反向控制(IoC,Inverse of Control),也称为依赖注入(DI,Dependence Injection)。
反向控制(IoC),就是由容器控制程序之间的关系,而不是由程序代码直接操控。控制权从应用代码转到了外部容器,控制权的转移,就是反向控制。
依赖注入(DI),是这种设计理念的另一种描述。依赖注入是指组件间的依赖关系由容器在运行期决定,即由容器动态地将某种依赖关系注入到组件之中。
Spring本质上是一个监听器,所以需要在web.xml中配置一个Spring监听器。具体配置如下:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
在Struts2中,在Action类的execute()方法中可以调用业务类的方法,业务类负责处理事务,当需要更换业务类时,Action类也必须随之修改,这是一件麻烦事。
利用Spring技术在Action类的execute()方法中不是直接调用业务类的方法,而是调用业务接口方法,也就是在Action类中使用的是接口,当需要更换业务类时,只要新业务类实现这个接口,然后在Spring的applicationContext.xml配置文件中,添加一个<bean />标签,其中属性id的值是接口,属性class的值是实现这个接口的类,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="teamService" class="business.TeamBusinessHibernate" />
<bean id="adminService" class="business.AdminBusiness" />
</beans>
applicationContext.xml是Spring的配置文件,在程序运行时根据这个配置文件注入相应的组件。
在Action类中创建ApplicationContext对象读取applicationContext.xml内容:
ApplicationContext ctx =
new ClassPathXmlApplicationContext("applicationContext.xml");
再用这个对象获取实现这个接口的类的实际对象。
teamService =(TeamService)ctx.getBean("teamService");
这样利用Spring技术可以在更换业务类时,不再需要修改Action类。
三、 Hibernate
Hibernate就是一种提供了对象关系映射(Object Relational Mapping)解决方案,就是将关系数据库中的表映射成为对象,把对数据库的操作转化为对象的操作,访问数据库不需要再使用SQL语句。
1. 添加jar文件
打开前面我们做的小组管理系统的项目,把Hibernate软件包里的hibernate3.jar添加到项目里。
2. 映射文件
每个和数据库的表对应的Java类都要有一个映射文件,指定类和表的对应关系,以及类的属性和表的列的对应关系。
在包bean里为Team类建立一个映射文件Team.hbm.xml,内容如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="bean">
<class name="Team" table="team">
<id name="id" column="id">
<generator class="identity"/>
</id>
<property name="name"/>
<property name="leader"/>
<property name="slogan"/>
</class>
</hibernate-mapping>
其中<class name="Team" table="team">指定了类和表的对应关系。
id元素是对类的标识符属性的声明,<id name="id" column="id">声明了类的标识符属性及其对应的数据库中表的列。generator元素指定了标识符的生成策略,<generator class="identity"/>指定了标识符由数据库自动生成。
property元素声明了类的属性及其对应的数据库中表的列,如果没有用column明确声明数据库中表的列,意味着数据库中表的列与类的属性同名。<property name="leader"/>声明了类Team的属性leader,对应数据库表team的列leader。
3. Hibernate配置文件
Hibernate项目需要一个配置文件,用来设置数据库的连接信息以及其他一些全局的信息。
在src下创建一个文件hibernate.cfg.xml,内容如下:
<?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">
<hibernate-configuration>
<!-- 产生操作数据库的session的工厂 -->
<session-factory>
<!-- 连接数据库的URL -->
<property name="connection.url">jdbc:odbc:un</property>
<!-- 连接本机数据库用户名 -->
<!-- 连接数据库的驱动类 -->
<property name="connection.driver_class">sun.jdbc.odbc.JdbcOdbcDriver</property>
<!-- 数据库方言 -->
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
<!-- 类与表的映射文件在这里注册 -->
<mapping resource="bean/Team.hbm.xml" />
</session-factory>
</hibernate-configuration>
4. 创建辅助类
Hibernate需要一个全局的SessionFactory对象,SessionFactory对象可以创建并打开新的Session对象。一个Session对象代表一个单线程的单元操作。SessionFactory是一个线程安全的全局对象,只需要被实例化一次。
我们创建一个包util,在包util里创建一个辅助类HibernateUtil,创建SessionFactory对象,并提供获取SessionFactory对象的方法,内容如下:
package util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
//根据hibernate.cfg.xml创建SessionFactory
return new Configuration().configure().buildSessionFactory();
}
catch(Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
这个辅助类在静态的初始化过程产生全局的SessionFactory对象,并提供了获取SessionFactory对象的方法getSessionFactory。
5. 用Hibernate实现增、删、改、查
在包business里创建一个类TeamBusinessHibernate,实现接口TeamService,内容如下:
package business;
import java.util.Collection;
import java.util.List;
import org.hibernate.*;
import bean.Team;
import service.TeamService;
import util.HibernateUtil;
public class TeamBusinessHibernate implements TeamService {
private Session session;
public TeamBusinessHibernate() {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
}
@Override
public void addTeam(Team team) throws Exception {
Transaction trans = session.beginTransaction();
session.save(team);
trans.commit();
}
@Override
public Collection<Team> allTeams() throws Exception {
session.clear();
String hql = "from Team";
Query query = session.createQuery(hql);
List<Team> teams = query.list();
return teams;
}
@Override
public void deleteTeam(Team team) throws Exception {
Transaction trans = session.beginTransaction();
String hql = "delete Team where id=?";
Query query = session.createQuery(hql);
query.setInteger(0, team.getId());
query.executeUpdate();
trans.commit();
}
@Override
public Team getTeamById(int id) throws Exception {
session.clear();
Team team = null;
String hql = "from Team where id=?";
Query query = session.createQuery(hql);
query.setInteger(0, id);
team = (Team)query.uniqueResult();
return team;
}
@Override
public Team getTeamByName(String name) throws Exception {
session.clear();
Team team = null;
String hql = "from Team where name=?";
Query query = session.createQuery(hql);
query.setString(0, name);
team = (Team)query.uniqueResult();
return team;
}
@Override
public void modifyTeam(Team team) throws Exception {
Transaction trans = session.beginTransaction();
String hql = "update Team set name=?,leader=?,slogan=? where id=?";
Query query = session.createQuery(hql);
query.setString(0, team.getName());
query.setString(1, team.getLeader());
query.setString(2, team.getSlogan());
query.setInteger(3, team.getId());
query.executeUpdate();
trans.commit();
}
}
这个类定义了一个属性session,用来进行各种操作。