一导入相关包 pom
1.1 hibernate相关(5.2.12.Final)
hibernate-core
hibernate-c3p0(数据库连接池)
hibernate-ehcache
mysql-connector-java(5.1.44)
1.2 spring相关(5.0.1.RELEASE)
spring-context
spring-orm
spring-web
spring-aspects
1.3 struts2相关(2.5.13)
struts2-core
struts2-spring-plugin
struts2与spring集成的插件
将action配置到spring中,struts的action标签的class属性填写spring中bean的名字或id
1.4 log配置
1.4.1 log4j(1.X版)
不建议使用
1.4.2 log4j2(2.9.1)
log4j-core
log4j-api
log4j-web
不建议使用
1.4.3 log4j2 + slf4j(使用ehcache开启hibernate二级缓存必须使用第二种方式配置日志)
注1:本章使用第三种方式配置日志,即log4j2 + slf4j
1.5 other
junit(4.12)
javax.servlet-api(4.0.0)
1.6 jstl
jstl(1.2)
standard(1.1.2)
1.7 jsp自定义标签依赖(必须与tomcat的版本一致)
tomcat-jsp-api
注1:如何解决项目中不支持EL表达式的问题?将web.xml的DTD的版本由2.3升级到3.0即可。因为web2.3是不支持EL表达式的
二. SSH集成
2.1 导入ehcache.xml
2.2 导入log4j2.xml
2.3spring 集成hibenate
2.3.1 注入数据库配置文件
2.3.2 配置c3p0连接池
2.3.3 注册LocalSessionFactoryBean
2.3.4 spring声明式事物
声明式事务配置
-
必须先修改spring配置文件的声明部分,添加对aop标签和tx标签的支持
-
配置SessionFactory(spring和hibernate集成时已完成)
-
配置事务管理器
HibernateTransactionManager -
配置事务的传播特性(tx)
add
edit
del
load|list
事务传播特性(PROPAGATION_REQUIRED|readOnly) -
配置自动代理 <aop:aspectj-autoproxy />
静态代理:一个代理对应一个目标对象
动态代理:一个代理对应多个目标对象a) 引用环绕通知txAdvice
b) 定义一个切入点
execution(* *…Biz.(…))
a:返回值不限 b:包名不限 c:接口名以Biz结尾 d:方法名及参数不限
*** 自动代理的原理***
在spring上下文初始化完成以后,自动代理会逐个检查spring上下文中JavaBean实现的接口是否满足自动代理的条件,如果满足条件,则将此bean和通知结合生成一个代理对象,并以此代理对象替换spring上下文中的bean,之后你访问的就是代理对象了
2.3.5 注册HibernateTemplate
2.3.6 注册Base模块
spring-hibernate.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/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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!--1.注册数据库连接信息 -->
<context:property-placeholder location="classpath:db.properties"/>
<!--2.配置C3P0数据库池 (作用:节省获取连接和关闭连接的时间)-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${db.username}"></property>
<property name="password" value="${db.password}"></property>
<property name="driverClass" value="${db.driverClass}"></property>
<property name="jdbcUrl" value="${db.jdbcUrl}"></property>
<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize" value="${db.initialPoolSize}"></property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize" value="${db.maxPoolSize}"></property>
<!--连接池中保留的最小连接数。 -->
<property name="minPoolSize" value="${db.minPoolSize}" />
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime" value="${db.maxIdleTime}" />
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement" value="${db.acquireIncrement}" />
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。
所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:
0 -->
<property name="maxStatements" value="${db.maxStatements}" />
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod" value="${db.idleConnectionTestPeriod}" />
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts" value="${db.acquireRetryAttempts}" />
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。
如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
<property name="breakAfterAcquireFailure" value="${db.breakAfterAcquireFailure}" />
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod
或automaticTestTable 等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout" value="${db.breakAfterAcquireFailure}" />
</bean>
<!--3.配置sessionFactory 相关信息-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource">
<ref bean="dataSource" />
</property>
<!-- hibernate相关属性 -->
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.MySQLDialect</prop>
<!--spring与Hibernate集成无法显示sql语句问题,请见集成后hibernate无法显示sql语句.txt-->
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<!-- 实体映射文件 -->
<property name="mappingResources">
<list>
<value>com/zking/book/entity/Book.hbm.xml</value>
</list>
</property>
</bean>
<!--4.配置事务 -->
<!--声明式事务配置开始 -->
<!-- 4.1开启自动代理 -->
<aop:aspectj-autoproxy />
<!-- 4.2配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 4.3.通知 配置事务的传播特性(tx)-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="list*" propagation="REQUIRED" read-only="true" />
<tx:method name="select*" propagation="REQUIRED" read-only="true" />
<tx:method name="query*" propagation="REQUIRED" read-only="true" />
<tx:method name="do*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 4.4 定义切入点-->
<aop:config>
<!-- pointcut属性用来定义一个切入点,分成四个部分理解 [* ][*..][*Biz][.*(..)] -->
<!-- A: 返回类型,*表示返回类型不限 -->
<!-- B: 包名,*..表示包名不限 -->
<!-- C: 类或接口名,*Biz表示类或接口必须以Biz结尾 -->
<!-- D: 方法名和参数,*(..)表示方法名不限,参数类型和个数不限 -->
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* *..*Biz.*(..))" />
</aop:config>
<!--5.使用HibernateTemplate(相当于session) -->
<bean class="org.springframework.orm.hibernate5.HibernateTemplate" id="HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--6.整合整个开发团队所需要的base模块 -->
<bean class="com.zking.base.entity.BaseEntity" abstract="true" id="BaseEntity"></bean>
<bean class="com.zking.base.dao.BaseDao" abstract="true" id="BaseDao">
<property name="hibernateTemplate" ref="HibernateTemplate"></property><!--相当于session -->
</bean>
<bean class="com.zking.base.biz.BaseBiz" abstract="true" id="BaseBiz"></bean>
<bean class="com.zking.base.web.BaseAction" abstract="true" id="BaseAction" ></bean>
</beans>
三. 程序代码的分层 分模块开发 (整合base模块)
新建
/base
/action
/biz
/dao
/entity
/book
/action
/biz
/dao
/entity
配置HibernateTemplate
配置Base模块
四. 整合案例演示
4.1 entity
package com.zking.book.entity;
import com.zking.base.entity.BaseEntity;
public class Book extends BaseEntity{
private static final long serialVersionUID = 1L;
private Integer bid;
private String bname;
private float price;
public Integer getBid() {
return bid;
}
public void setBid(Integer bid) {
this.bid = bid;
}
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public Book(Integer bid, String bname, float price) {
super();
this.bid = bid;
this.bname = bname;
this.price = price;
}
public Book() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]";
}
}
book.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>
<class table="t_mvc_book" name="com.zking.book.entity.Book">
<id name="bid" type="java.lang.Integer" column="bid">
<generator class="assigned"></generator>
</id>
<property name="bname" type="java.lang.String" column="bname"></property>
<property name="price" type="java.lang.Float" column="price"></property>
</class>
</hibernate-mapping>
4.2 dao
BookDao
package com.zking.book.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate5.HibernateCallback;
import com.zking.base.dao.BaseDao;
import com.zking.base.dao.PageBean;
import com.zking.base.dao.StringUtils;
import com.zking.book.entity.Book;
public class BookDao extends BaseDao<Book>{
private static final long serialVersionUID = 1L;
/**
* 新增书本的方法
* @param book
* @return
*/
public Integer save(Book book) {
return (Integer) this.getHibernateTemplate().save(book);
}
/**
* 查询书
* @return
*/
public List<Book> list(Book book,PageBean pageBean){
String hql="from Book where 1=1";
Map<String, Object> map=new HashMap<>();
if(StringUtils.isNotBlank(book.getBname())) {
hql+=" and bname like :bname ";
map.put("bname", "%"+book.getBname()+"%");
}
return super.executeQuery(hql, pageBean, map);
}
/**
* 删除
* @param book
*/
public void delete(Book book) {
this.getHibernateTemplate().delete(book);
}
/**
* 根据id查询
* @param book
* @return
*/
public Book getId(Book book) {
return this.getHibernateTemplate().get(Book.class, book.getBid());
}
/**
* 修改
* @param book
*/
public void update(Book book) {
this.getHibernateTemplate().update(book);
}
}
BookBiz
package com.zking.book.biz;
import java.util.List;
import com.zking.base.biz.BaseBiz;
import com.zking.base.dao.PageBean;
import com.zking.book.entity.Book;
public interface BookBiz extends BaseBiz{
public Integer save(Book book);
public List<Book> list(Book book,PageBean pagebean);
public void delete(Book book);
public void update(Book book);
public Book getId(Book book);
}
BookDaoImpl(继承HibernateDaoSupport类,方便注入HibernateTemplate)
package com.zking.book.biz.impl;
import java.util.List;
import com.zking.base.dao.PageBean;
import com.zking.book.biz.BookBiz;
import com.zking.book.dao.BookDao;
import com.zking.book.entity.Book;
public class BookBizImpl implements BookBiz{
private BookDao bookDao;
public BookDao getBookDao() {
return bookDao;
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public Integer save(Book book) {
// TODO Auto-generated method stub
return bookDao.save(book);
}
@Override
public List<Book> list(Book book, PageBean pagebean) {
// TODO Auto-generated method stub
return bookDao.list(book, pagebean);
}
@Override
public void delete(Book book) {
this.bookDao.delete(book);
}
@Override
public void update(Book book) {
this.bookDao.update(book);
}
@Override
public Book getId(Book book) {
// TODO Auto-generated method stub
return bookDao.getId(book);
}
}
BookAction
package com.zking.book.web;
import java.util.List;
import com.opensymphony.xwork2.ModelDriven;
import com.zking.base.dao.PageBean;
import com.zking.base.web.BaseAction;
import com.zking.book.biz.BookBiz;
import com.zking.book.entity.Book;
public class BookAction extends BaseAction implements ModelDriven<Book>{
private static final long serialVersionUID = 1L;
private Book book=new Book();
private BookBiz bookBiz;
private PageBean pageBean=new PageBean();
public String toAdd() {
return "toAdd";
}
public String add() {
this.bookBiz.save(book);
return "index";
}
public String booklist() {
pageBean.setRows(4);
pageBean.setRequest(req);
this.result= this.bookBiz.list(book, pageBean);
session.setAttribute("pageBean", pageBean);
return "index";
}
public String delete() {
this.bookBiz.delete(book);
return "index";
}
// 跳转到修改界面
public String toEdit() {
this.result = this.bookBiz.getId(book);
return "toEdit";
}
public String update() {
this.bookBiz.update(book);
return "index";
}
public BookBiz getBookBiz() {
return bookBiz;
}
public void setBookBiz(BookBiz bookBiz) {
this.bookBiz = bookBiz;
}
@Override
public Book getModel() {
return book;
}
}
spring-book.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/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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<bean class="com.zking.book.dao.BookDao" id="bookDao" parent="BaseDao"></bean>
<bean class="com.zking.book.biz.impl.BookBizImpl" id="bookBiz" parent="BaseBiz">
<property name="bookDao" ref="bookDao"></property>
</bean>
<bean class="com.zking.book.web.BookAction" id="bookAction" parent="BaseAction">
<property name="bookBiz" ref="bookBiz"> </property>
</bean>
</beans>
spring-context.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/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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<import resource="classpath:spring-hibernate.xml"/>
<import resource="classpath:spring-book.xml"/>
</beans>
test
package com.zking.ssh.test;
import java.util.List;
import org.apache.struts2.dispatcher.Parameter.Request;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.HttpRequest;
import com.zking.base.dao.PageBean;
import com.zking.base.web.BaseAction;
import com.zking.book.biz.BookBiz;
import com.zking.book.entity.Book;
public class SSHTest extends BaseAction{
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-context.xml");
BookBiz bookbiz = (BookBiz) applicationContext.getBean("bookBiz");
// bookbiz.save(new Book(13,"dd",33));
PageBean pageBean=new PageBean();
pageBean.setRows(5);
List<Book> list = bookbiz.list(new Book(),pageBean);
for (Book book : list) {
System.out.println(book);
}
}
}
biz的用途
1.性能更好(事物的开启以及提交次数由多次减为一次 方法在一个事务里)
2.为了事务的一致性 (转账例子)
五. web.xml配置 整合spring,struts
<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_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>Archetype Created Web Application</display-name>
<!-- 整合spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 整合strurs -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<!-- 中文乱码处理 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>