最近老师带一个网上商城的SSH项目,自己想把项目的过程记录下来。一希望自己能将做项目中的一些BUG的解决方法分享给大家,二来可以帮助那些期末做课设的同学。本项目的SSH是指Spring4+Struts2+Hibernate5,项目中需要的jar包我会放在本章的百度网盘链接中。如果后续还需要添加jar包我会在需要添加的地方加以说明并会附上百度网盘链接。
开发环境说明
- 网上商城项目SSH项目开发环境,部分辅助软件不做陈述。
- MySQL 5
- Eclipse EE
- Java 1.8
- Tomcat 9.0
下载需要的jar
我已经将将搭建环境的jar包进行了初步的整理,先把文件下载下来。
SSH整合Jar百度网盘地址
1
https://pan.baidu.com/s/1Fv0JBF7p7DEqVjBKSCF9Eg
下载解压后的文件应该如下图所示,红框文件夹里的jar应该有49个。
搭建Spring4环境
在Eclipse里创建Dynamic Web Project项目。
- 项目名我这里起为SshTest。Tomcat 9.0也在这里设置,web.xml的版本设置为3.1。第一个页面设置完成后不要直接点Finish,请点Next。具体设置如下图。
- 点击Next两次到下图这个界面把Generate web.xml deploayment descriptor勾选上,然后再点击Finish。
- 项目名我这里起为SshTest。Tomcat 9.0也在这里设置,web.xml的版本设置为3.1。第一个页面设置完成后不要直接点Finish,请点Next。具体设置如下图。
将“全部的jar包”中49个jar包复制到项目/WebContent/WEB-INF/lib文件中。然后将bin所有jar添加项目依赖中。
在Java Resources下的src中创建beans.xml,内容如下所示。
1
2
3
4
5
6
7
8
9
10
11<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:annotation-config />
<bean id="date" class="java.util.Date" />
</beans>配置spring监听器和log4j2监听器,编辑/WebContent/WEB-INF/web.xml,写入内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>SshTest</display-name>
<!-- 1、添加log4j监听器,log4j监听器要放在前面 -->
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/WEB-INF/classes/log4j2.xml</param-value>
</context-param>
<!-- log4j监听器配置结束,在Servlet3.0以上且Tomcat7.0以上的版本中,log4j不需要额外的配置了 -->
<!-- 2、添加spring监听器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- spring监听器配置结束 -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>在Java Resources下的src中创建log4j2.xml,内容如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<Configuration status="off" monitorInterval="1800">
<properties>
<property name="LOG_HOME">/opt/logs/Test/log4j2Demo/logs</property>
<property name="ERROR_LOG_FILE_NAME">error</property>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p (%F:%L) - %m%n" />
</Console>
<RollingRandomAccessFile name="ErrorLog"
fileName="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log"
filePattern="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log.%d{yyyy-MM-dd}.gz">
<PatternLayout
pattern="%d %-5p (%F:%L) - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<DefaultRolloverStrategy max="20"/>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core" level="info">
</logger>
<logger name="org.springframework.beans" level="info">
</logger>
<logger name="org.springframework.context" level="info">
</logger>
<logger name="org.springframework.web" level="info">
</logger>
<logger name="com.hafiz.www.controller" level="error" includeLocation="true" additivity="false">
<appender-ref ref="ErrorLog"/>
<appender-ref ref="Console"/>
</logger>
<root level="info" includeLocation="true">
<appender-ref ref="Console"/>
</root>
</Loggers>
</Configuration>创建cn.hncj.test包,并在包中创建Test类。
Test.java中写入的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package cn.hncj.test;
import java.util.Date;
import org.junit.runner.RunWith;
import javax.annotation.Resource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:beans.xml")
public class Test {
@Resource
private Date date;
@org.junit.Test//测试spring的IOC环境
public void spingioc(){
System.out.println(date);
}
}在Test.java中鼠标右键Run As>Junit Test,如果控制台显示当前时间则说明spring环境配置成功。
搭建Hibernate环境
在Mysql中创建shop数据库,在shop中创建category数据表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/*如果存在shop数据库则删除shop数据库 */
DROP DATABASE
IF EXISTS shop;
/*创建shop数据库并设置编码方式为utf-8*/
CREATE DATABASE shop DEFAULT CHARACTER
SET utf8;
/*创建shop数据库*/
USE shop;
/*如果存在category数据表则删除category数据表 */
DROP TABLE
IF EXISTS category;
/*创建category数据表*/
CREATE TABLE category (
/* 类别编号,自动增长 */
id INT NOT NULL auto_increment,
/* 类别名称 */
type VARCHAR (20),
/* 类别是否为热点类别,热点类别才有可能显示在首页*/
hot bool DEFAULT FALSE,
/* 设置类别编号为主键*/
PRIMARY KEY (id)
);- category数据表格式如下。
id type hot 1 music 1
- category数据表格式如下。
创建xml映射文件
- 在Java Resources下的src中创建hibernate.cfg.xml,特别注意的是代码块中的A和B。hibernate.cfg.xml内容如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36<?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 元素用于配置Hibernate中的属性 键:值 -->
<!-- hibernate.connection.driver_class : 连接数据库的驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- hibernate.connection.username : 连接数据库的用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- hibernate.connection.password : 连接数据库的密码 -->
<property name="hibernate.connection.password">123456</property>
<!-- A 下边的hibernate.connection.url是连接数据库的地址,路径,我这里的是本地路径,账号为root,密码是123456 -->
<property name="hibernate.connection.url">jdbc:mysql:///shop?useUnicode=true&characterEncoding=utf-8</property>
<!-- ====================以上配置和Spring整合后可以删除================================ -->
<!-- 操作数据库时,会 向控制台打印sql语句 -->
<property name="show_sql">true</property>
<!--============================================================================ -->
<!-- 打印sql语句前,会将sql语句先格式化 -->
<property name="format_sql">true</property>
<!--============================================================================ -->
<!-- hbm2ddl.auto: 生成表结构的策略配置 update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构. 如果存在表结构,并且表结构与实体一致,那么不做修改 如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列. create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常. -->
<property name="hbm2ddl.auto">update</property>
<!--============================================================================ -->
<!-- 数据库方言配置 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!--============================================================================ -->
<!-- 事务自动提交 -->
<property name="hibernate.connection.autocommit">true</property>
<!-- B 这是引入ORM的映射文件将下文你创建的实体类的路径替换掉resourcez中的字符串 -->
<mapping resource="cn/hncj/entity/Category.hbm.xml" />
</session-factory>
</hibernate-configuration>
- 在Java Resources下的src中创建hibernate.cfg.xml,特别注意的是代码块中的A和B。hibernate.cfg.xml内容如下所示。
创建cn.hncj.entity包,并在包中创建Category类,写入的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41package cn.hncj.entity;
public class Category {
private Integer id;
private String type;
private Boolean hot;
public Category() {
}
public Category(String type, Boolean hot) {
super();
this.type = type;
this.hot = hot;
}
public Category(Integer id, String type, Boolean hot) {
super();
this.id = id;
this.type = type;
this.hot = hot;
}
@Override
public String toString() {
return "Category [id=" + id + ", type=" + type + ", hot=" + hot + "]";
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public Boolean getHot() {
return this.hot;
}
public void setHot(Boolean hot) {
this.hot = hot;
}
}在cn.hncj.entity包中创建Category.hbm.xml文件,写入的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.hncj.entity.Category" table="category">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<property name="type" type="java.lang.String">
<column name="type" />
</property>
<property name="hot" type="java.lang.Boolean">
<column name="hot" />
</property>
</class>
</hibernate-mapping>创建cn.hncj.util包,并在包中创建HibernateSessionFactory类,写入的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package cn.hncj.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateSessionFactory {
private static final Configuration config;
private static final SessionFactory factory;
static {
config = new Configuration().configure();
factory = config.buildSessionFactory();
}
public static Session getSession() {
return factory.openSession();
}
}创建cn.hncj.service包,并在包中创建CategoryService接口类,写入的内容如下。
1
2
3
4
5package cn.hncj.service;
import cn.hncj.entity.Category;
public interface CategoryService {
public void save(Category category); //用来测试Hibernate环境
}在cn.hncj.service包中创建CategoryServiceImpl接口实现类用来实现CategoryService接口类未实现的方法,写入的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package cn.hncj.service;
import org.hibernate.Session;
import cn.hncj.entity.Category;
import cn.hncj.util.HibernateSessionFactory;
public class CategoryServiceImpl implements CategoryService{
@Override
public void save(Category category) {
// 通过刚刚生成的sessionFactory获取session
Session session = HibernateSessionFactory.getSession();
try {
// 手动事务
session.getTransaction().begin();
// 执行业务逻辑
session.save(category);
// 手动提交
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
throw new RuntimeException(e);
} finally {
session.close();
}
}
}重新编写cn.hncj.test包中的Test.java测试类如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package cn.hncj.test;
import java.util.Date;
import org.junit.runner.RunWith;
import javax.annotation.Resource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.hncj.entity.Category;
import cn.hncj.service.CategoryService;
import cn.hncj.service.CategoryServiceImpl;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:beans.xml")
public class Test {
@Resource
private Date date;
@org.junit.Test//测试spring的IOC环境
public void spingioc(){
System.out.println(date);
}
@org.junit.Test//测试Hibernate的开发环境,因为没有整合,可以直接new
public void hihernate() {
CategoryService categoryService = new CategoryServiceImpl();
Category category = new Category("mantype", true);
categoryService.save(category);
}
}- 在Test.java中鼠标右键Run As>Junit Test,如果控制台显示如下则说明hibernate环境可能配置成功。
- 如果shop数据库category数据表中插入下边的数据,则hibernate环境配置成功。
id type hot 1 mantype 1
- 在Test.java中鼠标右键Run As>Junit Test,如果控制台显示如下则说明hibernate环境可能配置成功。
整合Spring4和Hibernate5
在Java Resources下的src中创建jdbc.properties,将数据库的链接信息单独提取出来便于后期优化,内容如下所示。
1
2
3
4jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://***.**.**.**:3306/shop?useSSL=false
jdbc.username = ****
jdbc.password = ******整合spring和hibernate需要在beans.xml添加配置如下。
配置数据源dataSource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<!--连接池中保留的最小连接数。 -->
<property name="minPoolSize">
<value>5</value>
</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">
<value>30</value>
</property>
<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">
<value>10</value>
</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">
<value>60</value>
</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">
<value>5</value>
</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
<property name="maxStatements">
<value>0</value>
</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">
<value>60</value>
</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">
<value>30</value>
</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
<property name="breakAfterAcquireFailure">
<value>true</value>
</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">
<value>false</value>
</property>
</bean>在beans.xml配置数据源dataSource后,需要将hibernate.cfg.xml中链接数据库的配置删除。具体文件的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27<?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>
<!-- 操作数据库时,会 向控制台打印sql语句 -->
<property name="show_sql">true</property>
<!--============================================================================ -->
<!-- 打印sql语句前,会将sql语句先格式化 -->
<property name="format_sql">true</property>
<!--============================================================================ -->
<!-- hbm2ddl.auto: 生成表结构的策略配置 update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构.
如果存在表结构,并且表结构与实体一致,那么不做修改 如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列. create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常. -->
<property name="hbm2ddl.auto">update</property>
<!--============================================================================ -->
<!-- 数据库方言配置 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!--============================================================================ -->
<!-- 事务自动提交 -->
<property name="hibernate.connection.autocommit">true</property>
<!-- B 这是引入ORM的映射文件将下文你创建的实体类的路径替换掉resourcez中的字符串 -->
<mapping resource="cn/hncj/entity/Category.hbm.xml" />
</session-factory>
</hibernate-configuration>配置sessionFactory
1
2
3
4
5<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>配置spring的事务管理器
1
2
3
4<!-- 配置spring事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>配置advice
1
2
3
4
5
6
7
8
9<!-- 配置advice(通知) -->
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>配置AOP切面(需要足以的是expression中service的路径,这个需要根据自己在hibernate中写的service路径来写)
1
2
3
4
5
6
7
8<!-- 配置AOP切面 -->
<aop:config>
<!-- 配置哪些包的类要切入事务 -->
<aop:pointcut id="pointcut" expression="execution(* cn.hncj.service.*.*(..))" />
<aop:advisor advice-ref="advice" pointcut-ref="pointcut" />
<!-- 连接了上面的advice和上面的pointcut -->
<!-- aop:pointcut要写在aop:advisor上面,否则会报错 -->
</aop:config>
由于要测试spring和hibernate的整合需要重写cn.hncj.service包中的CategoryService接口类,写入的内容如下。
1
2
3
4
5
6package cn.hncj.service;
import cn.hncj.entity.Category;
public interface CategoryService {
public void save(Category category); //用来测试Hibernate环境
public void update(Category category); //用来测试Spring和Hibernate整合后
}由于我们重写了cn.hncj.service包中的CategoryService接口类,我们添加的update接口方法需要在CategoryServiceImlp中实现。CategoryServiceImlp.java写入的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package cn.hncj.service;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import cn.hncj.entity.Category;
public class CategoryServiceImpl implements CategoryService{
private SessionFactory sessionFactory;
// 当需要使用sessoinFactory的时候,Spring会将sessionFactory注入进来
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected Session getSession() {
// 从当前线程获取session,如果没有则创建一个新的session
return sessionFactory.getCurrentSession();
}
@Override
public void save(Category category) {
getSession().save(category);
}
@Override
public void update(Category category) {
getSession().update(category);
}
}在Spring的配置文件beans.xml中配一下这个CategoryService。
1
2
3
4
5<!-- 测试spring与hibernate整合结果 -->
<bean id="categoryService" class="cn.hncj.service.CategoryServiceImpl">
<property name="sessionFactory" ref="sessionFactory" />
<!-- 依赖的sessionFactory用我们之前配好的sessionFactory -->
</bean>重新Java Resources下的src的beans.xml,内容如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:annotation-config />
<bean id="date" class="java.util.Date" />
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<!--连接池中保留的最小连接数。 -->
<property name="minPoolSize">
<value>5</value>
</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">
<value>30</value>
</property>
<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">
<value>10</value>
</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">
<value>60</value>
</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">
<value>5</value>
</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
<property name="maxStatements">
<value>0</value>
</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">
<value>60</value>
</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">
<value>30</value>
</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
<property name="breakAfterAcquireFailure">
<value>true</value>
</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">
<value>false</value>
</property>
</bean>
<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
<!-- 配置spring事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置advice(通知) -->
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
<!-- 配置AOP切面 -->
<aop:config>
<!-- 配置哪些包的类要切入事务 -->
<aop:pointcut id="pointcut" expression="execution(* cn.hncj.service.*.*(..))" />
<aop:advisor advice-ref="advice" pointcut-ref="pointcut" />
<!-- 连接了上面的advice和上面的pointcut -->
<!-- aop:pointcut要写在aop:advisor上面,否则会报错 -->
</aop:config>
<!-- 测试spring与hibernate整合结果 -->
<bean id="categoryService" class="cn.hncj.service.CategoryServiceImpl">
<property name="sessionFactory" ref="sessionFactory" />
<!-- 依赖的sessionFactory用我们之前配好的sessionFactory -->
</bean>
</beans>重新编写cn.hncj.test包中的Test.java测试类如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package cn.hncj.test;
import java.util.Date;
import org.junit.runner.RunWith;
import javax.annotation.Resource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.hncj.entity.Category;
import cn.hncj.service.CategoryService;
import cn.hncj.service.CategoryServiceImpl;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:beans.xml")
public class Test {
@Resource
private Date date;
@org.junit.Test//测试spring的IOC环境
public void spingioc(){
System.out.println(date);
}
// @org.junit.Test//测试Hibernate的开发环境,因为没有整合,可以直接new
// public void hihernate() {
// CategoryService categoryService = new CategoryServiceImpl();
// Category category = new Category("mantype", true);
// categoryService.save(category);
// }
@Resource
private CategoryService categoryService;
@org.junit.Test // 测试Hibernate和Spring整合后
public void hibernateAndSpring() {
categoryService.update(new Category(1, "girltype", true)); // categoryService通过Spring从上面注入进来的
}
}- 在Test.java中鼠标右键Run As>Junit Test,如果控制台显示如下则说明spring和hibernate整合可能成功。
- 如果shop数据库category数据表中插入下边的数据,则说明spring和hibernate整合成功。
id type hot 1 girltype 1
- 在Test.java中鼠标右键Run As>Junit Test,如果控制台显示如下则说明spring和hibernate整合可能成功。
搭建Struts2环境并整合Spring4
在web.xml文件对Struts2进行配置,web.xml配置如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>SshTest</display-name>
<!-- 1、添加log4j监听器,log4j监听器要放在前面 -->
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/WEB-INF/classes/log4j2.xml</param-value>
</context-param>
<!-- log4j监听器配置结束,在Servlet3.0以上且Tomcat7.0以上的版本中,log4j不需要额外的配置了 -->
<!-- 2、添加spring监听器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- spring监听器配置结束 -->
<!-- 6、添加Struts2的核心过滤器。注意对应的是2.5.16版本 -->
<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>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>创建cn.hncj.action包,并在包中创建CategoryAction类,写入的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package cn.hncj.action;
import com.opensymphony.xwork2.ActionSupport;
import cn.hncj.entity.Category;
import cn.hncj.service.CategoryService;
public class CategoryAction extends ActionSupport{
private static final long serialVersionUID = 1L;
private CategoryService categoryService;
// 设置categoryService是为了很直观的看出与Spring整合前后的不同
private Category category;
// 设置一个私有成员变量接收url带过来的参数,注意下面要写好get和set方法
public void setCategoryService(CategoryService categoryService) {
this.categoryService = categoryService;
}
public String update() {
System.out.println("----update----");
System.out.println(categoryService);// 由于已经和Spring整合,所以可以拿到这个categoryService了,打印出来就不是null了
categoryService.update(category);
// 新加一条语句,来更新数据库
return "index";
}
public String save() {
System.out.println("----save----");
System.out.println(categoryService);// 整合前后输出不同
categoryService.save(category);
return "index";
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
}在Java Resources下的src中创建struts.xml文件,内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13<?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>
<package name="test" namespace="/" extends="struts-default">
<global-allowed-methods>execute,input,back,cancel,browse,update,save,delete,list,index</global-allowed-methods>
<!-- class对应的是Spring中配置该Action的id值,因为要交给Spring管理 -->
<action name="category_*" class="cn.hncj.action.CategoryAction" method="{1}">
<result name="index">/index.jsp</result>
</action>
</package>
</struts>在beans.xml文件中添加categoryaction配置。
1
2
3
4
5<!-- 把CategoryAction和它的依赖交给Spring管理 -->
<bean id="categoryAction" class="cn.hncj.action.CategoryAction" scope="prototype">
<property name="categoryService" ref="categoryService" />
<!-- 依赖的categoryService用上面和Hibernate整合时配置好的categoryService -->
</bean>完整的web.xml文件信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:annotation-config />
<bean id="date" class="java.util.Date" />
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<!--连接池中保留的最小连接数。 -->
<property name="minPoolSize">
<value>5</value>
</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">
<value>30</value>
</property>
<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">
<value>10</value>
</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">
<value>60</value>
</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">
<value>5</value>
</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
<property name="maxStatements">
<value>0</value>
</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">
<value>60</value>
</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">
<value>30</value>
</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
<property name="breakAfterAcquireFailure">
<value>true</value>
</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">
<value>false</value>
</property>
</bean>
<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
<!-- 配置spring事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置advice(通知) -->
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
<!-- 配置AOP切面 -->
<aop:config>
<!-- 配置哪些包的类要切入事务 -->
<aop:pointcut id="pointcut" expression="execution(* cn.hncj.service.*.*(..))" />
<aop:advisor advice-ref="advice" pointcut-ref="pointcut" />
<!-- 连接了上面的advice和上面的pointcut -->
<!-- aop:pointcut要写在aop:advisor上面,否则会报错 -->
</aop:config>
<!-- 测试spring与hibernate整合结果 -->
<bean id="categoryService" class="cn.hncj.service.CategoryServiceImpl">
<property name="sessionFactory" ref="sessionFactory" />
<!-- 依赖的sessionFactory用我们之前配好的sessionFactory -->
</bean>
<!-- 把CategoryAction和它的依赖交给Spring管理 -->
<bean id="categoryAction" class="cn.hncj.action.CategoryAction" scope="prototype">
<property name="categoryService" ref="categoryService" />
<!-- 依赖的categoryService用上面和Hibernate整合时配置好的categoryService -->
</bean>
</beans>在WebContent文件夹下创建index.jsp用来测试struts2和Spring4整合的环境。inde.jsp的内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Spring和Struts整合测试</title>
</head>
<body>
<a href="category_update.action?category.id=9&category.type=gcl&category.hot=true">访问update</a><br>
<a href="category_save.action?category.type=gcl&category.hot=true">访问save</a>
</body>
</html>在tomcat9.0服务器上运行index.jsp,点击两个链接输出结果如下图所示。并且数据库有数据的更新和添加则struts2和spring4的整合成功了。
- 如果有报错请先检查你的数据库中是否有id=9的数据信息,因为我在index.jsp中设定了category.id=9。
提示说明
- 本章的SSH整合项目的目录结构如下图所示。
- 本章的SSH整合项目我已经上传到百度网盘了,链接放到下边。
1
https://pan.baidu.com/s/12xlczc_sTbVxnmxuJHESpA
本文作者: Jade
版权声明: 未经授权禁止使用,转载请注明出处!