SSH整合
Spring和Struct2整合就是将Action对象交给Spring容器负责创建。Spring和Hibernate整合就是将SessionFactory交给Spring来负责维护。
同时Spring还可以负责session维护以及AOP事务管理。
首先创建Maven项目,作如下勾选:
创建完成后只是一个空项目,接下来创建相应的目录结构即可。
然后创建相应的数据库:
use ssh_db;
CREATE TABLE `user`
(
`user_id` bigint(20) unsigned NOT NULL auto_increment COMMENT 'ID',
`user_name` varchar(40) character set utf8 NOT NULL COMMENT '用户名',
`user_password` varchar(40) collate utf8_unicode_ci NOT NULL COMMENT '密码',
`nick_name` varchar(40) character set utf8 COMMENT '昵称',
PRIMARY KEY (`user_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8
COLLATE = utf8_unicode_ci COMMENT ='用户信息表';
框架配置
依赖文件
在pom.xml中添加如下依赖:
<dependencies>
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<!-- spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<!--spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<!-- spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<!-- aop面向切面依赖的jar包 -->
<!-- aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.1</version>
</dependency>
<!-- aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
<!-- hibernate依赖 -->
<!-- hibernate核心依赖 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.17.Final</version>
</dependency>
<!-- mysql数据库驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- c3p0连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- struts2依赖 -->
<!-- struts2 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.35</version>
</dependency>
<!-- struts2-spring-plugin整合spring和struts2 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.35</version>
</dependency>
<!-- servlet api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
<scope>provided</scope>
</dependency>
<!-- jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
Spring配置
1、创建一个Action,这里取名为UserAction
public class UserAction extends ActionSupport{
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public String login() throws Exception {
System.out.println(userService);
return super.execute();
}
}
2、创建一个Service层的类,其中包括接口UserService和UserServiceImp类
// UserService
public interface UserService {
User getUserByCodePassword(User user);
}
// UserServiceImp
public class UserServiceImp implements UserService{
@Override
public User getUserByCodePassword(User user) {
System.out.println("111111111111");
return null;
}
}
3、在项目的resources下创建applicationContext.xml配置文件,然后将Action和Service托管给Spring容器。
<?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.xsd">
<!--Action配置,Action对象作用范围一定是多例的,这样才符合Struct2架构-->
<bean name="userAction" class="com.legend.ssh.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
<!--Service配置-->
<bean name="userService" class="com.legend.ssh.service.imp.UserServiceImp"></bean>
</beans>
3、在web.xml中配置Spring随项目启动而启动
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--让Spring随项目启动而启动的监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置Spring配置文件参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
</web-app>
其中使用到的User.java类在domain包下:
public class User {
private Long user_id;
private String user_name;
private String user_password;
private String nick_name;
...Get & Set ..
}
Struct2配置
1、在resource下创建Struct2的配置文件,名为struts.xml的的配置文件,并配置Struct2的主配置文件,和Action建立关联。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="ssh" namespace="/" extends="struts-default">
<action name="UserAction_*" class="com.legend.ssh.action.UserAction" method="{1}">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
2、在web.xml中配置Struct2的核心过滤器
<!--Struct2核心监听器注册-->
<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>
Hibernate配置
1、添加实体配置文件User.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.legend.ssh.domain" >
<class name="User" table="user">
<id name="user_id" >
<generator class="native"></generator>
</id>
<property name="user_name"></property>
<property name="user_password"></property>
<property name="nick_name"></property>
</class>
</hibernate-mapping>
2、在resource下创建主配置文件hibernate.cfg.xml,并加入如下代码:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库url -->
<property name="hibernate.connection.url">jdbc:mysql:///ssh_db</property>
<!-- 数据库连接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库连接密码 -->
<property name="hibernate.connection.password">123456</property>
<!-- 数据库方言 注意: MYSQL在选择方言时,请选择最短的方言.-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 将hibernate生成的sql语句打印到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- 将hibernate生成的sql语句格式化(语法缩进) -->
<property name="hibernate.format_sql">true</property>
<!-- 自动导出表结构. 自动建表-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 引入实体配置文件 -->
<mapping resource="mapper/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
框架整合
Spring整合Struct2
在structs标签下添加常量配置,将action的创建交给Spring容器管理,并且让Spring负责装配依赖属性,这里有两种方案:
方案一:class属性仍然配置action完整类名,Struct2仍然创建Action,其中Spring只负责组装Action中的依赖属性(不推荐)
<struts>
<!--将action的创建交给Spring容器-->
<constant name="struts.objectFactory" value="spring"></constant>
<!--依赖Spring负责装配Action依赖属性-->
<constant name="struts.objectFactory.spring.autoWire" value="name"></constant>
<package name="ssh" namespace="/" extends="struts-default">
<!--整合方案一
class属性上仍然配置action完整类名,Struct2仍然创建Action,但是由Spring负责组装Action中的依赖属性。
这种方式不推荐,最好让Spring来管理Action的生命周期-->
<action name="UserAction_*" class="com.legend.ssh.action.UserAction" method="{1}">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
方案二:class属性上填写Spring中action对象的BeanName,完全由Spring管理生命周期,包括Action的创建,需要手动组装依赖属性
<struts>
<!--将action的创建交给Spring容器-->
<constant name="struts.objectFactory" value="spring"></constant>
<!--依赖Spring负责装配Action依赖属性-->
<constant name="struts.objectFactory.spring.autoWire" value="name"></constant>
<package name="ssh" namespace="/" extends="struts-default">
<!--整合方案二
class属性上填写Spring中action对象的BeanName,完全由Spring管理生命周期,包括Action的创建
注意:需要手动组装依赖属性-->
<action name="UserAction_*" class="userAction" method="{1}">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
所以在Struct2中配置后,还需要在Spring中去配置该Action
<?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.xsd">
<!--Action配置,Action对象作用范围一定是多例的,这样才符合Struct2架构-->
<bean name="userAction" class="com.legend.ssh.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
<!--Service配置-->
<bean name="userService" class="com.legend.ssh.service.imp.UserServiceImp"></bean>
</beans>
Spring整合Hibernate
Spring整合Hibernate的原理就是将SessionFactory对象交给Spring容器进行管理,有三种方案:
方案一:仍然使用外部的hibernate.cfg.xml配置连接信息,然后在Spring配置applicatonContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--将SessionFactory配置到Spring容器中-->
<!--加载配置方案一:仍然使用外部的hibernate.cfg.xml配置连接信息-->
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml.bat"></property>
</bean>
<!--Action配置,Action对象作用范围一定是多例的,这样才符合Struct2架构-->
<bean name="userAction" class="com.legend.ssh.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
<!--Service配置-->
<bean name="userService" class="com.legend.ssh.service.imp.UserServiceImp"></bean>
</beans>
方案二:在Spring配置文件applicatonContext.xml中放置Hibernate配置连接信息
<?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.xsd">
<!--将SessionFactory配置到Spring容器中-->
<!--加载配置方案二:在Spring配置中配置Hibernate配置连接信息-->
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!--配置hibernate基本属性信息-->
<property name="hibernateProperties">
<props>
<!--必选配置-->
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.url">jdbc:mysql:///ssh_db</prop>
<prop key="hibernate.connection.username">root</prop>
<prop key="hibernate.connection.password">123456</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!--可选配置-->
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<!--引入ORM元数据,指定ORM元数据所在包路径,Spring会自动读取包中的所有配置-->
<property name="mappingDirectoryLocations" value="classpath:com/legend/ssh/domain"></property>
</bean>
<!--Action配置,Action对象作用范围一定是多例的,这样才符合Struct2架构-->
<bean name="userAction" class="com.legend.ssh.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
<!--Service配置-->
<bean name="userService" class="com.legend.ssh.service.imp.UserServiceImp"></bean>
</beans>
然后编写测试类进行测试,这里的SessionFactory是通过Spring管理获取的。
public class HibernateTest {
@Test
public void func() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.configure().build();
SessionFactory factory = new MetadataSources( serviceRegistry ).buildMetadata().buildSessionFactory();
Session session = factory.openSession();
Transaction transaction = session.beginTransaction();
// 操作数据库
User user = new User();
user.setUser_name("神话");
user.setUser_password("123456");
user.setNick_name("神话");
session.save(user);
transaction.commit();
session.close();
}
}
- C3P0连接池
如果需要配置c3p0连接池的话,则可以通过连接的配置来配置连接信息,在resource下创建db.properties配置文件:
jdbc.jdbcUrl=jdbc:mysql:///ssh_db
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=123456
然后在Spring的配置文件applicatonContext.xml中配置c3p0连接池信息,完整代码如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 指定spring读取db.properties配置 -->
<context:property-placeholder location="classpath:db.properties" />
<!--将连接池放入Spring容器中管理-->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--将SessionFactory配置到Spring容器中-->
<!--加载配置方案二:在Spring配置中配置Hibernate配置连接信息-->
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!--配置hibernate基本属性信息-->
<property name="hibernateProperties">
<props>
<!--必选配置-->
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.url">jdbc:mysql:///ssh_db</prop>
<prop key="hibernate.connection.username">root</prop>
<prop key="hibernate.connection.password">123456</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!--可选配置-->
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<!--引入ORM元数据,指定ORM元数据所在包路径,Spring会自动读取包中的所有配置-->
<property name="mappingDirectoryLocations" value="classpath:com/legend/ssh/domain"></property>
</bean>
<!--Action配置,Action对象作用范围一定是多例的,这样才符合Struct2架构-->
<bean name="userAction" class="com.legend.ssh.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
<!--Service配置-->
<bean name="userService" class="com.legend.ssh.service.imp.UserServiceImp"></bean>
</beans>
- Dao持久层
1、编写Dao层接口和实现类,然后操作数据库
public interface UserDao {
// 根据用户登录名称查询user对象
User getByUserName(String userName);
}
2、UserDaoImp.java实现类:通过Spring整合的Hibernate模板中的HQL或Criteria的方式操作数据库
/**
* 模板操作数据库,将dao注入SessionFactory
*/
public class UserDaoImp extends HibernateDaoSupport implements UserDao {
@Override
public User getByUserName(final String userName) {
// HQL方式
/* User user = getHibernateTemplate().execute(new HibernateCallback<User>() {
@Override
public User doInHibernate(Session session) throws HibernateException {
String hql = "from User where user_name = ?";
Query query = session.createQuery(hql);
query.setParameter(0, userName);
User user = (User) query.uniqueResult();
return user;
}
});
return user;*/
// Criteria
DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
criteria.add(Restrictions.eq("user_name", userName));
List<User> userList = (List<User>) getHibernateTemplate().findByCriteria(criteria);
if (userList != null && userList.size() > 0) {
return userList.get(0);
}else {
return null;
}
}
}
3、由于Spring要整合Hibernate环境来操作数据库,则需要在Spring配置中将Dao注入到SessionFactory对象中:
<!--Dao配置-->
<bean name="userDao" class="com.legend.ssh.dao.UserDaoImp">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
4、编写测试类进行测试,其中Dao也是通过Spring进行管理获取的
@Test
public void func2() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) context.getBean("userDao");
User user = userDao.getByUserName("legend");
System.out.println(user);
}
AOP整合
1、通过SpringAOP来管理事务的话,首先在Spring配置文件中配置核心事务管理器:
<!--核心事务管理器-->
<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
核心事务管理器配置完成后,可以开始在Spring配置文件中来配置事务,有两种方式配置事务:XML配置事务 和 注解配置事务。
XML配置事务
在Spring配置文件中配置事务相关的内容:
<!--核心事务管理器-->
<bean name="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="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
<!-- 配置将通知织入目标对象 -->
<aop:config >
<!--配置切点-->
<aop:pointcut id="txPc" expression="execution(* com.legend.ssh.service.imp.UserServiceImp.*(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
注解配置事务
1、注解事务需要在Spring的配置文件中加入如下配置即可:
<!--开启注解事务-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
2、在Service层的方法中添加注解,如果所有方法都需要注解可以直接添加到Service的实现类上。
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = true)
public class UserServiceImp implements UserService{
private UserDao userDao;
@Override
public User getUserByCodePassword(User user) {
System.out.println("111111111111");
return null;
}
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false)
@Override
public void saveUser(User user) {
userDao.save(user);
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
3、Dao层的实现类UserDaoImp中添加保存用户的方法:
// 注册的方法
@Override
public void save(User user) {
getHibernateTemplate().save(user);
}
4、测试事务前,我们需要将UserDao在Spring中注入到Service对象中:
<!--Service配置-->
<bean name="userService" class="com.legend.ssh.service.imp.UserServiceImp">
<property name="userDao" ref="userDao"></property>
</bean>
<!--Dao配置-->
<bean name="userDao" class="com.legend.ssh.dao.UserDaoImp">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
5、以后我们获取Dao对象只需要将userDao当成属性,并生成SetXXX方法即可获取UserDao对象,下面我们编写测试类
@Test
public void func3() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = (UserService) context.getBean("userService");
User user = new User();
user.setUser_name("legend");
user.setUser_password("123456");
user.setNck_Name("legend");
service.saveUser(user);
}