struts2作为一个很传统的mvc框架,在一些项目中,仍然发挥着重要的作用,另外hibernate和spring的结合也是很常见的,这里介绍struts2+hibernate5+spring4的整合,因为struts2支持最高的spring是4版本,所以这里采用的是spring4。整合的思路比较简单,可以从struts2+spring整合,然后接着整合hibernate+spring。也可以反过来,这里我们先整合hibernate与spring,让系统产生一些数据。然后把struts2整合进来,就有了页面,这样,数据有了,页面就可以动起来了。
先给出一个动图,这就是我们最后整合的简单示例:
工程最后的结构图:
搭建maven工程,引入相关的依赖:
4.0.0
com.xxx
ssh
war
0.0.1-SNAPSHOT
ssh Maven Webapp
http://maven.apache.org
1.8
1.8
2.5.16
4.3.13.RELEASE
1.7.25
5.2.17.Final
2.9.6
junit
junit
4.12
test
org.apache.struts
struts2-core
${struts2.version}
org.apache.struts
struts2-convention-plugin
${struts2.version}
org.apache.logging.log4j
log4j-core
2.10.0
org.slf4j
slf4j-log4j12
${slf4j.version}
com.fasterxml.jackson.core
jackson-databind
${jackson.version}
org.springframework
spring-orm
${spring.version}
org.springframework
spring-test
${spring.version}
org.springframework.security
spring-security-web
4.2.10.RELEASE
org.springframework.security
spring-security-config
4.2.10.RELEASE
org.springframework.security
spring-security-taglibs
4.2.10.RELEASE
org.apache.struts
struts2-spring-plugin
${struts2.version}
org.hibernate
hibernate-core
${hibernate.version}
mysql
mysql-connector-java
5.1.46
com.zaxxer
HikariCP
2.7.9
org.aspectj
aspectjweaver
1.8.13
javax.servlet
javax.servlet-api
3.1.0
org.springframework.session
spring-session-data-redis
1.3.5.RELEASE
commons-codec
commons-codec
1.10
ssh
org.eclipse.jetty
jetty-maven-plugin
9.4.7.v20170914
/${project.build.finalName}
CTRL+C
8999
10
src/main/webapp/WEB-INF/webapp.xml
项目中使用了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 findById(Serializable key);
void save(T entity);
void update(T entity);
void delete(Serializable key);
List 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 implements BaseDao {
public abstract Class 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 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 {
}
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 implements UserDao {
@Override
public Class 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 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 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
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
spring-database.xml
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
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 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 users) {
this.users = users;
}
public List 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
regex:.*
/index.html
web.xml
ssh
contextConfigLocation
classpath:spring*.xml
org.springframework.web.context.ContextLoaderListener
ssh
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
ssh
/*
页面部分:
index.html
ssh
welcome to ssh.
用户列表
user_detail.ftl
用户列表
欢迎来到用户详情页
welcome you,${user.username}.
user_list.ftl
用户列表
欢迎来到用户列表页
-
id
用户名
电话
年龄
创建日期
状态
操作
<#list users as user>
-
${user.id}
${user.username}
${user.mobile}
${user.age}
${user.createDate}
${user.status?string("yes","no")}
用户详情
#list>
这里为什么index.html页面是html,而user_detail.ftl和user_list.ftl页面是freemarker,其实html页面完全可以作为freemarker模板的,但是ftl模板页面,在struts.xml配置文件中不用指定
至此,整合就基本结束了,运行项目,访问http://127.0.0.1:8080/ssh,就可以看到开始那个动图的效果了。
项目配置里面补充log4j2.xml配置文件,这样,我们启动项目,可以看到相关日志,另外,也可以看到sql打印信息,在开发阶段非常有意义。
打印的日志: