1.整合原理
使用struts好处:
struts2将应用分层,使产品结构清晰,能够减少代码的维护量,同时能够使开发人员分层实现,也就是说Java程序员可以只专注于业务逻辑的实现
项目开源,使用及扩展方便
提供了强大的全局异常处理机制;
Result方式的页面导航,通过 Result 标签很方便的实现重定向和页面跳转;
通过简单、集中的配置来调度业务类,使得配置和修改都非常容易;
提供简单、统一的表达式语言来访问所有可供访问的数据(OGNL);
提供标准、强大的验证框架和国际化框架;
提供多种表现层的技术支持和页面标签,大大简化开发;
拥有简单的插件,只需要放入响应的 jar 包,任何人都可以扩展 Struts2 框架,比如:
自定义拦截器、自定义结果类型、自定义标签等,为 Struts2 定制需要的功能,不需要什么特殊的配置,并且可以发布给其他人使用。
拥有智能的默认设置,不需要另外进行繁琐的设置。使用默认设置就可以完成大多数项目程序开发所需的功能。
struts就是负责action对象,对应用层的jsp页面进行统一调度。
hibernate负责将类实体与数据库连接,实现方便的建表,和对数据的更改功能。
spring负责对所有的对象进行管理。
ssh就是指spring与struts2,struts将action对象交给spring来创建,spring与hibernate进行整合。
2.配置spring容器。
为使spring在web启动时就能开启,而不是你想用的时候开始,在web.xml中设置监听器。并配置文件位置参数,会自动在src目录下寻找applicationContext.xm文件。
<!-- 让spring随web启动而创建的监听器 -->
<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>
3.单独配置struts2.
配置struts2的核心过滤器,对每一个web访问都必须先经过过滤器。
<!-- struts2核心过滤器 -->
<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>
在struts.xml中配置-:
package:将Action配置封装.就是可以在Package中配置很多action.
name属性: 给包起个名字,起到标识作用.随便起.不能其他包名重复.
namespace属性:给action的访问路径中定义一个命名空间
method={1}就是和前面的适配符相对应。
<package name="crm" namespace="/" extends="struts-default" >
<action name="UserAction_*" class="cn.lzm.web.action.UserAction" method="{1}" >
<result name="success" >/success.jsp</result>
</action>
public class UserAction extends ActionSupport{
@Test
public String login() throws Exception {
// TODO Auto-generated method stub
userService.test();
System.out.println(userService);
return "success";
}
}
当你在浏览器中输入如下地址,会首先经过web.xml,发现有struts2核心过滤器,转到struts.xml文件下,寻找name=UserAction_login,然后转到 cn.lzm.web.action.UserAction在访问方法,因为返回success, 根据配置转到相应的jsp页面/success.jsp
4.整合struts2和spring
首先要进行常量配置,也就是告诉struts他的action交给spring来处理了。
struts.xml中配置:
<constant name="struts.objectFactory" value="spring"></constant>
applicationContext.xml中配置:此时我也在userAction中注入userService
<bean name="userAction" class="cn.lzm.web.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
<bean name="userService" class="cn.lzm.service.Implement.UserServiceImplement" scope="prototype"></bean>
userService中代码:
public class UserServiceImplement implements UserService {
@Override
public void test() {
System.out.println("测试成功");
// TODO Auto-generated method stub
}
通过在上面的配置在struts不再需要自己来管理action的生成了,注意此时的class=“userAction” 与上面bean中的name=“userAction” 要相对应。这样struts就去找spring要相应的action类。
<action name="UserAction_*" class="userAction" method="{1}" >
<result name="success" >/success.jsp</result>
</action>
通过访问http://localhost:8080/ssh/UserAction_login
最后控制台显示
流程:
web中的struts2中的核心过滤器——sturts2.xml发现class=“userAction”,因为struts与spring整合,所以到spring中找到bean name=“userAction”,注意要与struts2中的名字相匹配。——然后到该类下访问login方法,class=“cn.lzm.web.action.UserAction” 。——因为返回success,就到相应的jsp页面下。
5.单独配置hibernate
实体类
public class User {
/*
* CREATE TABLE `sys_user` (
`user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`user_code` varchar(32) NOT NULL COMMENT '用户账号',
`user_name` varchar(64) NOT NULL COMMENT '用户名称',
`user_password` varchar(32) NOT NULL COMMENT '用户密码',
`user_state` char(1) NOT NULL COMMENT '1:正常,0:暂停',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
*/
private Long user_id;
private String user_code;
private String user_name;
private String user_password;
private Character user_state;
public Long getUser_id() {
return user_id;
}
public void setUser_id(Long user_id) {
this.user_id = user_id;
}
public String getUser_code() {
return user_code;
}
public void setUser_code(String user_code) {
this.user_code = user_code;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getUser_password() {
return user_password;
}
public void setUser_password(String user_password) {
this.user_password = user_password;
}
public Character getUser_state() {
return user_state;
}
public void setUser_state(Character user_state) {
this.user_state = user_state;
}
@Override
public String toString() {
return "User [user_id=" + user_id + ", user_code=" + user_code + ", user_name=" + user_name + ", user_password="
+ user_password + "]";
}
}
配置文件:实现类与数据库中的表相对应。
<?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="cn.lzm.domain" >
<class name="User" table="sys_user" >
<!-- id元素:配置主键映射的属性
name: 填写主键对应属性名
column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
每个类型有三种填法: java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
-->
<id name="user_id" >
<generator class="native"></generator>
</id>
<!-- property元素:除id之外的普通属性映射
name: 填写属性名
column(可选): 填写列名
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
每个类型有三种填法: java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
-->
<property name="user_code" ></property>
<property name="user_name" ></property>
<property name="user_password" ></property>
<property name="user_state" ></property>
</class>
</hibernate-mapping>
在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</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="cn/lzm/domain/Customer.hbm.xml" />
<mapping resource="cn/lzm/domain/LinkMan.hbm.xml" />
<mapping resource="cn/lzm/domain/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
##6. spring整合hibernate
整合原理:将实例化session的工厂sessionFactory对象交给spring容器管理。
在spring中配置sessionFactory和数据库等信息
<!-- 将实例化session的工厂交给spring来打理 -->
<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</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:cn/lzm/domain" ></property>
</bean>
测试:此时用的是注解,用名称注入,@RunWith(SpringJUnit4ClassRunner.class)就是让junit4能够拿到spring中的容器对象并且能对注解有效,在其他类中,如果需要注入对象,用set注入,或者在spring中指定扫描包下的所有类中的注解.
注意:扫描包时.会扫描指定报下的所有子孙包
<context:component-scan base-package=“cn.itcast.bean”></context:component-scan>
//为了让测试在Spring容器环境下执行。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class test {
@Resource(name="sessionFactory")
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Test
public void test1()
{
// Configuration configuration=new Configuration().configure();
// sFactory=configuration.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
User user=new User();
user.setUser_code("lzm");
user.setUser_name("ts");
user.setUser_password("ss");
session.save(user);
transaction.commit();
session.close();
sessionFactory.close();
}
调试不成功的时候记得clean一下工程
6.spring整合c3p0数据库连接池
在applicationContext.xml中的sessionFactory注入连接池,hibernate就会通过连接池获取session.
<property name="dataSource" ref="dataSource" ></property>
applicationContext.xml中配置c3p0连接池并且读取db.properties文件
<!-- 读取db.properties文件 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 配置c3p0连接池 -->
<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.user}" ></property>
<property name="password" value="${jdbc.password}" ></property>
</bean>
db.properties
jdbc.jdbcUrl=jdbc:mysql:///ssh
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=123456
7.spring整合hibernate整合数据库操作
dao层 继承HibernateDaoSupport,该数据库支持层封装了模板操作,该模板依赖sessionFactory来对数据库进行crud操作。
//为HibernateDaoSupport注入sessionFactory,该类中封装了模板。
public class UserDaoImplement extends HibernateDaoSupport implements UserDao
通过模板中封装的excute方法对数据库进行hql查询操作
@Override
public User getByUserCode(final String Usercode) {
//hql
return getHibernateTemplate().execute(new HibernateCallback<User>() {
@Override
public User doInHibernate(Session session) throws HibernateException {
// TODO Auto-generated method stub
String hql="from User where user_code=?";
Query query=session.createQuery(hql);
query.setParameter(0, Usercode);
User user = (User) query.uniqueResult();
return user;
}
});
在spring当中配置Userdao
<bean name="userdao" class="cn.lzm.dao.Implement.UserDaoImplement">
<!-- 注入sessionfactory,封装模板也需要sessfactory -->
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
测试:
@Resource(name="userdao")
private UserDao ud;
@Test
//测试dao管理heibernate模板,模板中封装了sessionfactory
public void test2()
{
User user = ud.getByUserCode("lzm");
System.out.println(user);
}
8.aop事务操作
配置核心事务管理器,该事务管理器依赖于sessionFactory来管理session.
<!-- 核心事务管理器 -->
<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" >
<property name="sessionFactory" ref="sessionFactory" ></property>
</bean>
配置aop事务
配置通知:事务管理器来管理相应的方法能够进行什么样的操作如只读还是只写,隔离级别等。 isolation:隔离级别,propagation:传播行为,read-only:是否只读
<!-- 配置通知 -->
<!-- <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:attributes>
</tx:advice> -->
现在就要对那些方法即目标对象运行事务,目标对象即切点,将通知应用到切点的操作叫织入,切点和通知构成切面,spring来管理切面。
对返回值,前缀名,类中的方法,参数等配置通知。
* cn.lzm.service.impl.*ServiceImpl.*(..)
<!-- 配置将通知织入目标对象
配置切点
配置切面 -->
<aop:config>
<aop:pointcut expression="execution(* cn.itcast.service.impl.*ServiceImpl.*(..))" id="txPc"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
</aop:config>
测试
@Resource(name="userService")
private UserService us;
//测试事务
@Test
public void test3()
{
User user=new User();
user.setUser_code("lzms");
user.setUser_name("ts");
user.setUser_password("ss");
us.saveUser(user);
}
另外注解方法
<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
在相应的service类上
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true)
9.扩大session作用范围
为避免使用懒加载时出现no-session问题,需要扩大session的作用范围。
filter有调用顺序
注意: 任何filter一定要在struts的filter之前调用
<!-- 扩大session作用范围
注意: 任何filter一定要在struts的filter之前调用
-->
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Struts2中的ModelDriven机制及其运用
https://blog.csdn.net/li_tengfei/article/details/6098145
Action接口和ActionSupport基类
https://blog.csdn.net/Titilover/article/details/6792854