# Spring 4 + Struts 2 + Hibernate 集成教程
> 原文: [https://howtodoinjava.com/struts2/spring-4-struts-2-hibernate-integration-tutorial/](https://howtodoinjava.com/struts2/spring-4-struts-2-hibernate-integration-tutorial/)
以前,我已经介绍了 [**Spring3 +休眠集成**](//howtodoinjava.com/spring/spring-orm/spring-3-and-hibernate-integration-tutorial-with-example/ "Spring3 and hibernate integration tutorial with example") 示例和 [**struts 2 hello world**](//howtodoinjava.com/struts-2/struts-2-hello-world-example-application/ "Struts 2 hello world example application") 示例。 在本教程中,我将讨论将 spring 框架与 Struts 和 Hibernate 结合使用时要记住的所有重要点。 另外,请注意,本教程使用了其他次要但很重要的概念,例如日志记录,TLD 的使用和事务以及已集成到本教程中。 因此,请记住还要检查其详细信息。
在本教程中,我将使用简单的功能(例如全部获取,添加和删除)来构建员工管理屏幕。 它看起来像这样:
![home screen for spring struts hibernate integration](img/6ee1537649c1d220ab78f8c9bbe88881.png)
我将按照以下步骤讨论集成过程:
```java
1) Integration Overview
2) Spring + Struts Integration
3) Spring + Hibernate Integration
4) Other Integrated Functionalities
a) Log4j
b) TLDs
c) Transactions
5) Important Points to Keep Remember
6) Database Schema Used in Tutorial
7) 下载源码
```
## 1)整合概述
在进入集成细节之前,让我们先确定一下 ***为什么我们需要此集成*** 本身。 像 Struts 一样,Spring 也可以充当 MVC 实现。 两种框架都有其优缺点,仍然有很多人会同意 **Spring 更好**,并且提供了更广泛的功能。 对我来说,只有两种情况,您需要本教程中提供的信息:
**i)**您有一个用 Struts 编写的旧应用,并且想要使用 spring 来提高应用的功能很多倍。
**ii)**您确实想根据自己的原因来学习它。
否则,我不知道为什么有人会在Spring选择支柱。 如果您知道其他一些好的理由,请与我们所有人分享。 那挺棒的。
继续,在本教程中,我将**委托从 Struts 到 Spring** 进行动作管理。 进行委派的原因是,通过 Spring 上下文实例化 Action 类时,它可以使用 spring 在其自己的 MVC 实现中为其提供的 Controller 类的所有其他功能。 因此,您将获得所有 spring 功能以及 struts Action 类,以具有包括 ActionForm 概念在内的控制器逻辑。
## 2)Spring + Struts 集成
这是核心逻辑,从在 web.xml 中注册`ContextLoaderListener`和`StrutsPrepareAndExecuteFilter`开始。 `ContextLoaderListener`带有初始化参数 ***contextConfigLocation*** ,并负责设置和启动 Spring `WebApplicationContext`。 现在,struts 将在与 Spring 相关的服务中特别是在[依赖项注入](//howtodoinjava.com/spring/spring-core/inversion-of-control-ioc-and-dependency-injection-di-patterns-in-spring-framework-and-related-interview-questions/ "Inversion of control (IoC) and dependency injection (DI) patterns in spring framework and related interview questions")中利用此上下文。
`StrutsPrepareAndExecuteFilter`在类路径中查找 ***struts.xml*** 文件,并配置 strut 的特定内容,例如动作映射,全局转发和其他在 struts.xml 文件中定义的内容。
**web.xml**
```java
Spring+Struts+Hibernate Integration Example/WEB-INF/index.jspcontextConfigLocationclasspath:beans.xmlorg.springframework.web.context.ContextLoaderListenerstruts2org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterdebug0detail0struts2/*/tags/struts-bean/WEB-INF/struts-bean.tld/tags/struts-html/WEB-INF/struts-html.tld/tags/struts-logic/WEB-INF/struts-logic.tld/tags/struts-nested/WEB-INF/struts-nested.tld
```
第二步,将在 **struts.xml** 文件中创建操作映射,如下所示:
**struts.xml**
```java
/view/editEmployeeList.jsp/list
{1}
/list/view/editEmployeeList.jsp
```
In strut’s alone application we would have full Action Class with it’s package information in “class” attribute. Here we have given the class name as editEmployeeAction. Where is it defined? We will ask Spring to lookup for us.
Spring 上下文文件 **beans.xml** 是典型的 Spring 单独上下文文件,具有 Web 应用运行所需的所有内容,其中包括 struts 正在寻找的 bean 定义`editEmployeeAction`。
**beans.xml**
```java
classpath:hibernate.cfg.xmlorg.hibernate.cfg.AnnotationConfiguration${jdbc.dialect}true
```
这是我们要做的**将支撑架与 spring** 框架集成在一起的所有步骤。 现在,您的动作类如下所示:
**EditEmployeeAction.java**
```java
package com.howtodoinjava.controller;
import java.util.List;
import org.apache.log4j.Logger;
import com.howtodoinjava.entity.EmployeeEntity;
import com.howtodoinjava.service.EmployeeManager;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
public class EditEmployeeAction extends ActionSupport implements Preparable
{
private static final long serialVersionUID = 1L;
//Logger configured using log4j
private static final Logger logger = Logger.getLogger(EditEmployeeAction.class);
//List of employees; Setter and Getter are below
private List employees;
//Employee object to be added; Setter and Getter are below
private EmployeeEntity employee;
//Employee manager injected by spring context; This is cool !!
private EmployeeManager employeeManager;
//This method return list of employees in database
public String listEmployees() {
logger.info("listEmployees method called");
employees = employeeManager.getAllEmployees();
return SUCCESS;
}
//This method will be called when a employee object is added
public String addEmployee() {
logger.info("addEmployee method called");
employeeManager.addEmployee(employee);
return SUCCESS;
}
//Deletes a employee by it's id passed in path parameter
public String deleteEmployee() {
logger.info("deleteEmployee method called");
employeeManager.deleteEmployee(employee.getId());
return SUCCESS;
}
//This method will be called before any of Action method is invoked;
//So some pre-processing if required.
@Override
public void prepare() throws Exception {
employee = null;
}
//Getters and Setters hidden
}
```
Spring 还将 DAO 引用注入到 Manager 类。
**EmployeeManagerImpl.java**
```java
package com.howtodoinjava.service;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import com.howtodoinjava.dao.EmployeeDAO;
import com.howtodoinjava.entity.EmployeeEntity;
public class EmployeeManagerImpl implements EmployeeManager
{
//Employee dao injected by Spring context
private EmployeeDAO employeeDAO;
//This method will be called when a employee object is added
@Override
@Transactional
public void addEmployee(EmployeeEntity employee) {
employeeDAO.addEmployee(employee);
}
//This method return list of employees in database
@Override
@Transactional
public List getAllEmployees() {
return employeeDAO.getAllEmployees();
}
//Deletes a employee by it's id
@Override
@Transactional
public void deleteEmployee(Integer employeeId) {
employeeDAO.deleteEmployee(employeeId);
}
//This setter will be used by Spring context to inject the dao's instance
public void setEmployeeDAO(EmployeeDAO employeeDAO) {
this.employeeDAO = employeeDAO;
}
}
```
## 3)Spring + Hibernate 集成
现在我们必须将休眠集成到应用中。 最好的地方是利用 Spring 的强大功能进行集成,以充分利用依赖注入来与不同的 ORM 一起使用。
上面 **beans.xml** 文件中已经给出了 Spring 所需的休眠依赖关系。 您将需要的其他文件是:
**hibernate.cfg.xml**
```java
```
**jdbc.properties**
```java
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseurl=jdbc:mysql://127.0.0.1:3306/test
jdbc.username=root
jdbc.password=password
```
**EmployeeDaoImpl.java**
```java
package com.howtodoinjava.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;
import com.howtodoinjava.entity.EmployeeEntity;
@Repository
public class EmployeeDaoImpl implements EmployeeDAO
{
//Session factory injected by spring context
private SessionFactory sessionFactory;
//This method will be called when a employee object is added
@Override
public void addEmployee(EmployeeEntity employee) {
this.sessionFactory.getCurrentSession().save(employee);
}
//This method return list of employees in database
@SuppressWarnings("unchecked")
@Override
public List getAllEmployees() {
return this.sessionFactory.getCurrentSession().createQuery("from EmployeeEntity").list();
}
//Deletes a employee by it's id
@Override
public void deleteEmployee(Integer employeeId) {
EmployeeEntity employee = (EmployeeEntity) sessionFactory.getCurrentSession()
.load(EmployeeEntity.class, employeeId);
if (null != employee) {
this.sessionFactory.getCurrentSession().delete(employee);
}
}
//This setter will be used by Spring context to inject the sessionFactory instance
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
```
供您参考,EmployeeEntity 类如下所示:
**EmployeeEntity.java**
```java
package com.howtodoinjava.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="EMPLOYEE")
public class EmployeeEntity {
@Id
@Column(name="ID")
@GeneratedValue
private Integer id;
@Column(name="FIRSTNAME")
private String firstname;
@Column(name="LASTNAME")
private String lastname;
@Column(name="EMAIL")
private String email;
@Column(name="TELEPHONE")
private String telephone;
//Setters and Getters
}
```
## 4)其他集成功能
除了 struts + spring + hibernate,我们还使用以下组件来构建应用。
#### a)Log4j
Spring 通过扫描类路径中的`log4j`自动配置日志记录。 我们使用`pom.xml`文件添加了 log4j 依赖项。 现在,您只需要在类路径中放置一个 log4j.xml 或 log4j.properties 文件。
**log4j.properties**
```java
log4j.rootLogger=info, stdout, R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=c:/log/demo.log
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
```
#### b)顶级域名
如果您查看`web.xml`文件,我们在其中包含了一些 TLD。 我们可以随时在视图层中使用它们,如下所示:
**editEmployeeList.jsp**
```java
<%@ taglib prefix="s" uri="/struts-tags"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
Spring-4 + Struts-3 + Hibernate Integration Demo