Struts2 and Hibernate both are widely used frameworks in their respective area. Today we will learn how to integrate Struts2 Web application framework with Hibernate ORM framework.
Struts2和Hibernate都是各自领域中广泛使用的框架。 今天,我们将学习如何将Struts2 Web应用程序框架与Hibernate ORM框架集成在一起。
Struts2Hibernate (Struts2 Hibernate)
Unlike Spring Hibernate Integration, there are no plugins provided by Struts2 framework that we can use. So we would need to use the Servlet Listener to manage the Hibernate SessionFactory.
与Spring Hibernate Integration不同,Struts2框架没有提供可使用的插件。 因此,我们需要使用Servlet Listener来管理Hibernate SessionFactory 。
Let’s see how to integrate Struts2 with Hibernate with a simple web application example.
让我们看看如何通过一个简单的Web应用程序示例将Struts2与Hibernate集成。
Our final project structure will look like below image, we will look into each of the component one by one. Start with creating a “Dynamic Web Project” in Eclipse and then convert it to maven project to get the basic skeleton ready for our web application.
我们的最终项目结构将如下图所示,我们将逐一研究每个组件。 首先在Eclipse中创建一个“动态Web项目”,然后将其转换为maven项目,以便为我们的Web应用程序准备好基本框架。
Struts2Hibernate示例数据库设置 (Struts2 Hibernate Example Database Setup)
We will create a login application, after authentication user will be present to the welcome page where all his information will be displayed. Below SQL script will create the required table and insert data that we will use for authentication.
在身份验证用户出现在欢迎页面后,我们将创建一个登录应用程序,其中将显示他的所有信息。 下面SQL脚本将创建所需的表并插入我们将用于身份验证的数据。
setup.sql
setup.sql
CREATE TABLE `User` (
`user_id` varchar(10) NOT NULL DEFAULT '',
`password` varchar(40) NOT NULL DEFAULT '',
`name` varchar(40) NOT NULL DEFAULT '',
`email` varchar(40) NOT NULL DEFAULT '',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `User` (`user_id`, `password`, `name`, `email`)
VALUES
('pankaj', 'pankaj123', 'Pankaj Kumar', 'pankaj@journaldev.com');
Struts2,Hibernate和MySQL Maven依赖关系 (Struts2, Hibernate and MySQL Maven Dependencies)
We need to add Struts2, Hibernate and MySQL maven dependencies in pom.xml file, final pom.xml file looks like below.
我们需要在pom.xml文件中添加Struts2,Hibernate和MySQL maven依赖项,最终的pom.xml文件如下所示。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Struts2Hibernate</groupId>
<artifactId>Struts2Hibernate</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.15.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
</project>
We are using Hibernate 4 for our example, however same code will work with Hibernate 3 too. Although you might need to do some configuration hibernate 3 specific changes.
我们在示例中使用的是Hibernate 4,但是相同的代码也可以在Hibernate 3中使用。 尽管您可能需要进行一些配置,但Hibernate3的特定更改。
Struts2 Hibernate示例部署描述符 (Struts2 Hibernate Example Deployment Descriptor)
We need to plugin Struts2 framework in our web application by applying StrutsPrepareAndExecuteFilter
in deployment descriptor.
我们需要通过在部署描述符中应用StrutsPrepareAndExecuteFilter
在我们的Web应用程序中插入Struts2框架。
web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Struts2Hibernate</display-name>
<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>
<listener>
<listener-class>com.journaldev.struts2hibernate.listener.HibernateServletContextListener</listener-class>
</listener>
</web-app>
Notice that HibernateServletContextListener
will be used to manage Hibernate SessionFactory, we will look it’s code later on.
注意, HibernateServletContextListener
将用于管理Hibernate SessionFactory,稍后我们将看它的代码。
实体豆 (Entity Bean)
Our entity bean will also work as the struts2 action class model bean, it looks like below.
我们的实体Bean还将用作struts2动作类模型Bean,如下所示。
User.java
User.java
package com.journaldev.struts2hibernate.model;
public class User {
private String id;
private String name;
private String pwd;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString(){
return "Name= "+name+", Email= "+email;
}
}
I am using XML based mappings, but we can also use JPA annotations based mapping for our entity bean.
我正在使用基于XML的映射,但是我们也可以为我们的实体bean使用基于JPA批注的映射。
Hibernate DAO实现类 (Hibernate DAO Implementation Classes)
Our UserDAO interface declares the method that will be exposed for User entity bean.
我们的UserDAO接口声明了将为User实体bean公开的方法。
UserDAO.java
UserDAO.java
package com.journaldev.struts2hibernate.dao;
import com.journaldev.struts2hibernate.model.User;
public interface UserDAO {
User getUserByCredentials(String userId, String password);
}
Hibernate specific DAO implementation looks like below.
Hibernate特定的DAO实现如下所示。
UserDAOImpl.java
UserDAOImpl.java
package com.journaldev.struts2hibernate.dao;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.struts2hibernate.model.User;
public class UserDAOImpl implements UserDAO {
private SessionFactory sf;
public UserDAOImpl(SessionFactory sf){
this.sf = sf;
}
@Override
public User getUserByCredentials(String userId, String password) {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from User where id=:id and pwd=:pwd");
query.setString("id", userId); query.setString("pwd", password);
User user = (User) query.uniqueResult();
if(user != null){
System.out.println("User Retrieved from DB::"+user);
}
tx.commit();session.close();
return user;
}
}
Servlet上下文侦听器 (Servlet Context Listener)
We will initialize Hibernate SessionFactory
in the ServletContextListener
implementation, when application will be stopped, we will destroy the SessionFactory
.
我们将在ServletContextListener
实现中初始化Hibernate SessionFactory
,当应用程序停止时,我们将销毁SessionFactory
。
HibernateServletContextListener.java
HibernateServletContextListener.java
package com.journaldev.struts2hibernate.listener;
import java.net.URL;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateServletContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sce) {
SessionFactory sf = (SessionFactory) sce.getServletContext().getAttribute("SessionFactory");
sf.close();
}
@Override
public void contextInitialized(ServletContextEvent sce) {
URL url = HibernateServletContextListener.class.getResource("/hibernate.cfg.xml");
Configuration config = new Configuration();
config.configure(url);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(config.getProperties()).build();
SessionFactory sf = config.buildSessionFactory(serviceRegistry);
sce.getServletContext().setAttribute("SessionFactory", sf);
}
}
Struts2动作类 (Struts2 Action Class)
Our hibernate specific setup is ready, let’s move on to Struts2 action class.
Hibernate特定的设置已经准备好,让我们继续Struts2动作类。
LoginAction.java
LoginAction.java
package com.journaldev.struts2hibernate.action;
import javax.servlet.ServletContext;
import org.apache.struts2.util.ServletContextAware;
import org.hibernate.SessionFactory;
import com.journaldev.struts2hibernate.dao.UserDAO;
import com.journaldev.struts2hibernate.dao.UserDAOImpl;
import com.journaldev.struts2hibernate.model.User;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ModelDriven;
public class LoginAction implements Action, ModelDriven<User>, ServletContextAware {
@Override
public String execute() throws Exception {
SessionFactory sf = (SessionFactory) ctx.getAttribute("SessionFactory");
UserDAO userDAO = new UserDAOImpl(sf);
User userDB = userDAO.getUserByCredentials(user.getId(), user.getPwd());
if(userDB == null) return ERROR;
else {
user.setEmail(userDB.getEmail());
user.setName(userDB.getName());
return SUCCESS;
}
}
@Override
public User getModel() {
return user;
}
private User user = new User();
private ServletContext ctx;
@Override
public void setServletContext(ServletContext sc) {
this.ctx = sc;
}
}
Struts2,Hibernate配置和Hibernate映射XML (Struts2, Hibernate Configuration and Hibernate Mapping XML)
We have following URI configurations in Struts2 configuration file.
我们在Struts2配置文件中具有以下URI配置。
struts.xml
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"https://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true"></constant>
<constant name="struts.convention.result.path" value="/"></constant>
<package name="user" namespace="/User" extends="struts-default">
<action name="home">
<result>/login.jsp</result>
</action>
<action name="login" class="com.journaldev.struts2hibernate.action.LoginAction">
<result name="success">/welcome.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
</struts>
Hibernate Configuration File looks like below.
Hibernate配置文件如下所示。
hibernate.cfg.xml
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection properties - Driver, URL, user, password -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property>
<property name="hibernate.connection.username">pankaj</property>
<property name="hibernate.connection.password">pankaj123</property>
<!-- Connection Pool Size -->
<property name="hibernate.connection.pool_size">1</property>
<!-- org.hibernate.HibernateException: No CurrentSessionContext configured! -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Outputs the SQL queries, should be disabled in Production -->
<property name="hibernate.show_sql">true</property>
<!-- Dialect is required to let Hibernate know the Database Type, MySQL, Oracle etc
Hibernate 4 automatically figure out Dialect from Database Connection Metadata -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- mapping file, we can use Bean annotations too -->
<mapping resource="User.hbm.xml" />
</session-factory>
</hibernate-configuration>
Hibernate Mapping XML file looks like below.
Hibernate Mapping XML文件如下所示。
User.hbm.xml
User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.journaldev.struts2hibernate.model.User" table="USER">
<id name="id" type="java.lang.String">
<column name="USER_ID" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="pwd" type="java.lang.String">
<column name="PASSWORD" />
</property>
<property name="email" type="java.lang.String">
<column name="EMAIL" />
</property>
</class>
</hibernate-mapping>
Struts2查看页面 (Struts2 View Pages)
As you can see from struts2 configuration file, we have three view pages. They are simple pages and looks like below.
从struts2配置文件中可以看到,我们有三个视图页面。 它们是简单的页面,如下所示。
login.jsp
login.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<%-- Using Struts2 Tags in JSP --%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Login Page</title>
</head>
<body>
<h3>Welcome User, please login below</h3>
<s:form action="login">
<s:textfield name="id" label="User ID"></s:textfield>
<s:textfield name="pwd" label="Password" type="password"></s:textfield>
<s:submit value="Login"></s:submit>
</s:form>
</body>
</html>
welcome.jsp
welcome.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Welcome Page</title>
</head>
<body>
<h3>Welcome <s:property value="name"></s:property></h3>
<h3>Your id is <s:property value="id"></s:property></h3>
<h3>Your password is <s:property value="pwd"></s:property></h3>
<h3>Your email id is <s:property value="email"></s:property></h3>
</body>
</html>
error.jsp
error.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Error Page</title>
</head>
<body>
<h4>User Name or Password is wrong</h4>
<s:include value="login.jsp"></s:include>
</body>
</html>
Struts2Hibernate应用测试 (Struts2 Hibernate Application Test)
Our application is ready, build and deploy it into your favorite servlet container and you should get response pages like below images.
我们的应用程序已准备就绪,将其构建并部署到您喜欢的servlet容器中,您将获得如下图所示的响应页面。
Struts2Hibernate登录页面 (Struts2 Hibernate Login Page)
Struts2Hibernate欢迎页面 (Struts2 Hibernate Welcome Page)
Struts2Hibernate登录错误页面 (Struts2 Hibernate Login Error Page)
You will also notice hibernate queries and other logs in the server log file.
您还将在服务器日志文件中注意到Hibernate查询和其他日志。
Hibernate: select user0_.USER_ID as USER_ID1_0_, user0_.NAME as NAME2_0_, user0_.PASSWORD as PASSWORD3_0_, user0_.EMAIL as EMAIL4_0_ from USER user0_ where user0_.USER_ID=? and user0_.PASSWORD=?
User Retrieved from DB::Name= Pankaj Kumar, Email= pankaj@journaldev.com
Struts2 Hibernate集成摘要 (Struts2 Hibernate Integration Summary)
This tutorial was aimed to provide details about Struts2 and Hibernate integration, so that you can get started. As you can see that Servlet Context Listener makes it very easy to integrate. You can download the final project from below link.
本教程旨在提供有关Struts2和Hibernate集成的详细信息,以便您可以开始使用。 如您所见,Servlet Context Listener使集成变得非常容易。 您可以从下面的链接下载最终项目。
翻译自: https://www.journaldev.com/3557/struts2-hibernate-integration-example-tutorial