struts2+spring4+hibernate5整合实例

struts2作为一个很传统的mvc框架,在一些项目中,仍然发挥着重要的作用,另外hibernate和spring的结合也是很常见的,这里介绍struts2+hibernate5+spring4的整合,因为struts2支持最高的spring是4版本,所以这里采用的是spring4。整合的思路比较简单,可以从struts2+spring整合,然后接着整合hibernate+spring。也可以反过来,这里我们先整合hibernate与spring,让系统产生一些数据。然后把struts2整合进来,就有了页面,这样,数据有了,页面就可以动起来了。

先给出一个动图,这就是我们最后整合的简单示例:

工程最后的结构图:

搭建maven工程,引入相关的依赖:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xxx</groupId>
  <artifactId>ssh</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>ssh Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <properties>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
      <struts2.version>2.5.16</struts2.version>
      <spring.version>4.3.13.RELEASE</spring.version>
      <slf4j.version>1.7.25</slf4j.version>
      <hibernate.version>5.2.17.Final</hibernate.version>
      <jackson.version>2.9.6</jackson.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-core</artifactId>
      <version>${struts2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-convention-plugin</artifactId>
      <version>${struts2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.10.0</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-web</artifactId>
    	<version>4.2.10.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-config</artifactId>
    	<version>4.2.10.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-taglibs</artifactId>
    	<version>4.2.10.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-spring-plugin</artifactId>
      <version>${struts2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>${hibernate.version}</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.46</version>
    </dependency>
    <dependency>
      <groupId>com.zaxxer</groupId>
      <artifactId>HikariCP</artifactId>
      <version>2.7.9</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.13</version>
    </dependency>
    <dependency>
    	<groupId>javax.servlet</groupId>
    	<artifactId>javax.servlet-api</artifactId>
    	<version>3.1.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
        <version>1.3.5.RELEASE</version>
    </dependency>
    <dependency>
       <groupId>commons-codec</groupId>
       <artifactId>commons-codec</artifactId>
       <version>1.10</version>
    </dependency>
    
  </dependencies>
  <build>
    <finalName>ssh</finalName>
    <plugins>
        <plugin>
              <groupId>org.eclipse.jetty</groupId>
              <artifactId>jetty-maven-plugin</artifactId>
              <version>9.4.7.v20170914</version>
              <configuration>
                  <webApp>
                      <contextPath>/${project.build.finalName}</contextPath>
                  </webApp>
                  <stopKey>CTRL+C</stopKey>
                  <stopPort>8999</stopPort>
                  <scanIntervalSeconds>10</scanIntervalSeconds>
                  <scanTargets>
                      <scanTarget>src/main/webapp/WEB-INF/webapp.xml</scanTarget>
                  </scanTargets>
              </configuration>
        </plugin>
    </plugins>
  </build>
</project>

项目中使用了jetty-maven-plugin插件,这样,我们最后启动项目直接右键pom.xml运行run as -> run configuration ,然后配置maven build->jetty run,就可以启动web项目了,而不用额外通过tomcat来启动。方便,快捷。

第一部分:

java代码部分:

BaseEntity.java

package com.xxx.ssh.web.domain;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public class BaseEntity {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	protected Integer id;
	@Column(name="createdate")
	protected Date createDate;
	@Column(name="modifydate")
	protected Date modifyDate;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	public Date getModifyDate() {
		return modifyDate;
	}
	public void setModifyDate(Date modifyDate) {
		this.modifyDate = modifyDate;
	}
	
}

User.java

package com.xxx.ssh.web.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name="xx_user")
public class User extends BaseEntity {
	private String username;
	private String password;
	@Column(length=11)
	private String mobile;
	private int age;
	private boolean status;
	@Override
	public String toString() {
		return "User [username=" + username + ", age=" + age + ", status=" + status + ", id=" + id + "]";
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getMobile() {
		return mobile;
	}
	public void setMobile(String mobile) {
		this.mobile = mobile;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public boolean isStatus() {
		return status;
	}
	public void setStatus(boolean status) {
		this.status = status;
	}
	
}

BaseDao.java

package com.xxx.ssh.web.dao;
import java.io.Serializable;
import java.util.List;
public interface BaseDao<T> {
	T findById(Serializable key);
	void save(T entity);
	void update(T entity);
	void delete(Serializable key);
	List<T> findAll();
}

BaseDaoImpl.java

package com.xxx.ssh.web.dao.impl;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;

import com.xxx.ssh.web.dao.BaseDao;
public abstract class BaseDaoImpl<T> implements BaseDao<T> {
	public abstract Class<T> getEntityClass();
	@Autowired
	private SessionFactory sessionFactory;
	
	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}
	
	@Override
	public void save(T entity) {
		getSession().persist(entity);
	}
	
	@Override
	public void update(T entity) {
		getSession().update(entity);
	}
	
	@Override
	public T findById(Serializable key) {
		return getSession().get(getEntityClass(), key);
	}
	
	@Override
	public void delete(Serializable key) {
		getSession().delete(findById(key));
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public List<T> findAll() {
		String hql = "from "+getEntityClass().getName();
		Query query = getSession().createQuery(hql);
		return query.list();
	}
}

UserDao.java

package com.xxx.ssh.web.dao;

import com.xxx.ssh.web.domain.User;

public interface UserDao extends BaseDao<User> {

}

UserDaoImpl.java 

package com.xxx.ssh.web.dao.impl;
import org.springframework.stereotype.Repository;

import com.xxx.ssh.web.dao.UserDao;
import com.xxx.ssh.web.domain.User;
@Repository
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {
	@Override
	public Class<User> getEntityClass() {
		return User.class;
	}
}

 UserService.java

package com.xxx.ssh.web.service;
import java.util.List;
import com.xxx.ssh.web.domain.User;
public interface UserService {
	void save(User entity);
	void update(User entity);
	void delete(Integer id);
	User findById(Integer id);
	List<User> findAll();
}

UserServiceImpl.java

package com.xxx.ssh.web.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xxx.ssh.web.dao.UserDao;
import com.xxx.ssh.web.domain.User;
import com.xxx.ssh.web.service.UserService;
@Service
public class UserServiceImpl implements UserService {
	@Autowired
	private UserDao userDao;
	@Override
	public void save(User entity) {
		userDao.save(entity);
	}

	@Override
	public void update(User entity) {
		userDao.update(entity);
	}

	@Override
	public void delete(Integer id) {
		userDao.delete(id);
	}

	@Override
	public User findById(Integer id) {
		return userDao.findById(id);
	}

	@Override
	public List<User> findAll() {
		return userDao.findAll();
	}

}

    MyEntityInterceptor.java

package com.xxx.ssh.web.config;
import java.io.Serializable;
import java.util.Date;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
public class MyEntityInterceptor extends EmptyInterceptor {

	private static final long serialVersionUID = 1L;
	private static final String CREATE_DATE="createDate";
	private static final String MODIFY_DATE="modifyDate";
	
	@Override
	public boolean onFlushDirty(Object entity, Serializable id,
			Object[] currentState, Object[] previousState,
			String[] propertyNames, Type[] types) {
		for(int i=0;i<propertyNames.length;i++){
			if(MODIFY_DATE.equals(propertyNames[i])){		
				currentState[i] = new Date();
			}
		}
		return true;
	}

	@Override
	public boolean onSave(Object entity, Serializable id, Object[] state,
			String[] propertyNames, Type[] types) {
		for(int i=0;i<propertyNames.length;i++){
			if(CREATE_DATE.equals(propertyNames[i]) || MODIFY_DATE.equals(propertyNames[i])){		
				state[i] = new Date();
			}
		}
		return true;
	}

}

    MD5Utils.java

package com.xxx.ssh.web.util;
import org.apache.commons.codec.digest.DigestUtils;
public class MD5Utils {
	public static String md5(String source) {
		return DigestUtils.md5Hex(source);
	}
}

配置文件部分:

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <context:component-scan base-package="com.xxx.ssh.web" />
    <import resource="spring-database.xml"/>
</beans>

spring-database.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
     </bean>
     <bean id="myEntityInterceptor" class="com.xxx.ssh.web.config.MyEntityInterceptor"/>
     <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="entityInterceptor" ref="myEntityInterceptor"></property>
        <property name="hibernateProperties">
             <value>
                 hibernate.dialect=${hibernate.dialect}
                 hibernate.show_sql=${hibernate.show_sql}
                 hibernate.format_sql=${hibernate.format_sql}
                 hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto}
                 hibernate.cache.use_second_level_cache=false
                 hibernate.cache.use_query_cache=false
                 hibernate.jdbc.fetch_size=50
                 hibernate.jdbc.batch_size=50
                 hibernate.connection.release_mode=auto
      			 hibernate.connection.autocommit=true
      			 hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
             </value>
        </property>
        <property name="packagesToScan" value="com.xxx.ssh.web.domain"></property>
     </bean>
     <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
         <property name="sessionFactory" ref="sessionFactory"></property>
     </bean>
     <tx:advice id="txAdvice" transaction-manager="transactionManager">
         <tx:attributes>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="save*" propagation="REQUIRED"/>   
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>    
            <tx:method name="transfer*" propagation="REQUIRED"/>
         </tx:attributes>
     </tx:advice>
     
     <aop:config>
         <aop:pointcut expression="execution( * com.xxx.ssh.web.service.*.*(..))" id="tx-pointcut"/>
         <aop:advisor advice-ref="txAdvice" pointcut-ref="tx-pointcut"/>
     </aop:config>
</beans>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///ssh?useUnicode=true&useSSL=false&characterEncoding=UTF-8
jdbc.username=hadoop
jdbc.password=hadoop
hibernate.maxPoolSize=50
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update

单元测试类:

package com.xxx.ssh.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.xxx.ssh.web.domain.User;
import com.xxx.ssh.web.service.UserService;
import com.xxx.ssh.web.util.MD5Utils;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:spring.xml"})
public class UserTest {
	@Autowired
	private UserService userService;
	@Test
	public void save() {
		User user = new User();
		user.setUsername("hadoop");
		user.setPassword(MD5Utils.md5("123456"));
		user.setAge(22);
		user.setMobile("13800138001");
		user.setStatus(true);
		userService.save(user);
	}
	
	@Test
	public void update() {
		User user = userService.findById(1);
		user.setStatus(true);
		userService.update(user);
	}
}

利用save()方法,可以像数据库中增加几条数据,至此,第一部分整合完毕。

第二部分:

java代码部分:

UserAction.java

package com.xxx.ssh.web.action.admin;
import java.util.List;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.ssh.web.domain.User;
import com.xxx.ssh.web.service.UserService;
@ParentPackage("ssh")
public class UserAction {
	@Autowired
	private UserService userService;
	
	private List<User> users;
	private Integer id;
	private User user;
	
	public String detail() {
		System.out.println(id);
		user = userService.findById(id);
		return "detail";
	}
	
	public String list() {
		users = userService.findAll();
		return "list";
	}
	
	public void setUsers(List<User> users) {
		this.users = users;
	}
	
	public List<User> getUsers() {
		return users;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Integer getId() {
		return id;
	}
	
	public void setUser(User user) {
		this.user = user;
	}
	public User getUser() {
		return user;
	}
}

配置文件部分:

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
    "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
	<constant name="struts.devMode" value="true"/>
	<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
	<constant name="struts.convention.action.mapAllMatches" value="true"/>
	<constant name="struts.convention.package.locators" value="action"/>
	<constant name="struts.objectFactory" value="spring"/>
	<constant name="struts.convention.relative.result.types" value="freemarker"/>
	<package name="ssh" extends="struts-default">
	     <global-allowed-methods>regex:.*</global-allowed-methods>
	     <action name="index">
	        <result type="freemarker">/index.html</result>
	     </action>
	</package>
</struts>

web.xml

<?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">
  <display-name>ssh</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring*.xml</param-value>
	</context-param>

	<!-- Bootstraps the root web application context before servlet initialization -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
  <filter>
      	<filter-name>ssh</filter-name>
      	<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
   </filter>
   <filter-mapping>
      	<filter-name>ssh</filter-name>
      	<url-pattern>/*</url-pattern>
  	</filter-mapping>
</web-app>

页面部分:

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ssh</title>
</head>
<body>
    <h2>welcome to ssh.</h2>
    <a href="admin/user!list.action">用户列表</a>
</body>
</html>

user_detail.ftl

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
     <h2>欢迎来到用户详情页</h2>
     <h2>welcome you,${user.username}.</h2>
</body>
</html>

user_list.ftl

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户列表</title>
<style type="text/css">
   ul li span{display:inline-block;width:100px;}
</style>
</head>
<body>
     <h2>欢迎来到用户列表页</h2>
     <ul>
         <li>
             <span>id</span>
	         <span>用户名</span>
	         <span>电话</span>
	         <span>年龄</span>
	         <span>创建日期</span>
	         <span>状态</span>
	         <span>操作</span>
         </li>
         <#list users as user>
         <li>
            <span>${user.id}</span>
            <span>${user.username}</span>
            <span>${user.mobile}</span>
            <span>${user.age}</span>
            <span>${user.createDate}</span>
            <span>${user.status?string("yes","no")}</span>
            <span><a href="${base}/admin/user!detail.action?id=${user.id}">用户详情</a></span>
         </li>
         </#list>
     </ul>
</body>
</html>

这里为什么index.html页面是html,而user_detail.ftl和user_list.ftl页面是freemarker,其实html页面完全可以作为freemarker模板的,但是ftl模板页面,在struts.xml配置文件中不用指定<result type="freemarker"></result>就可以,因为struts默认指定的模板就是freemarker。

至此,整合就基本结束了,运行项目,访问http://127.0.0.1:8080/ssh,就可以看到开始那个动图的效果了。 

项目配置里面补充log4j2.xml配置文件,这样,我们启动项目,可以看到相关日志,另外,也可以看到sql打印信息,在开发阶段非常有意义。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
   <Appenders>
       <Console name="Console" target="SYSTEM_OUT">
          <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%-5p] %c %m%n"/> 
       </Console>
   </Appenders>
   <Loggers>
       <Logger name="com.opensymphony.xwork2" level="warn"/>
       <Logger name="org.apache.struts2" level="info"/>
       <Root level="info">
           <appender-ref ref="Console"/>
       </Root>
   </Loggers>
</Configuration>

打印的日志: 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值