导入依赖包:
除了导入Struts2和Spring的核心库之外,还要导入commons-logging和struts2-spring-plugin包。(PS:Struts2是主导,把spring嵌到struts2中。)
配置:
通过配置ContextLoaderListener监听器,使容器启动时,自动加载applicationContext配置,因为它实现了ServletContextListener这个接口,容器启动时会自动执行它实现的方法。
1
2
3
|
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
|
默认情况下,会加载WEB-INF/applicationContext.xml这个文件,我们可以通过配置contextConfigLocation参数改变配置文件的路径。
1
2
3
4
|
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
|
以上配置均在web.xml文件的<web-app></web-app>区域。
Spring和Struts2的整合:
在web.xml中完成加载WebApplicationContext之后,接下来就可以做到Spring和Struts2的整合了。整合有两种方法,分别叙述如下:
第一种实现方法–把Action配置在beans.xml里,利用Spring初始化Action的bean:
1) 将Struts的业务逻辑控制器类(action)配置在Spring的配置文件中(由spring容器负责生成action),业务逻辑控制器中引用的业务类一并注入。注意,必须将业务逻辑控制器类配置为scope=”prototype”!
示例如下:
1
2
3
|
<bean id=”LoginAction” class=”yaso.struts.action.LoginAction”>
<property name=”loginDao” ref=”LoginDao”/>
</bean>
|
2) 在struts.xml或者等效的Struts2配置文件中配置Action时,指定<action>的class属性为Spring配置文件中相应bean的id或者name值。
示例如下:
1
2
3
|
<action name=”LoginAction” class=”LoginAction”>
<result name=”success”>/index.jsp</result>
</action>
|
第二种实现方法–不需要在beans.xml里配置Action,利用Struts-Spring_Plugin插件自动初始化Action:
1) 业务类在Spring配置文件中配置,业务逻辑控制器类(action)不需要配置,Struts2的Action像没有整合Spring之前一样配置,<action>的class属性指定业务逻辑控制器类的全限定名。
2) 业务逻辑控制器类中引用的业务类不需要自己去初始化,Struts2的Spring插件会使用bean的自动装配将业务类注入进来,其实业务逻辑控制器类也不是Struts2创建的,而是Struts2的Spring插件创建的。默认情况下,插件使用by name的方式装配,可以通过增加Struts2常量来修改匹配方式:设置方式为:struts.objectFactory.spring.autoWire = typeName,可选的装配参数如下:
- a) name:等价于Spring配置中的autowire=”byName”,这是缺省值。
- b) type:等价于Spring配置中的autowire=”byType”。
- c) auto:等价于Spring配置中的autowire=”autodetect”。
- d) constructor:等价于Spring配置中的autowire=” constructor”。
简述OpenSessionInViewFilter:
OpenSessionInViewFilter是Spring提供的一个针对Hibernate的一个支持类,其主要意思是在发起一个页面请求时打开Hibernate的Session,一直保持这个Session,直到这个请求结束,具体是通过一个Filter来实现的。 由于Hibernate引入了Lazy Load特性,使得脱离Hibernate的Session周期的对象如果再想通过getter方法取到其关联对象的值,Hibernate会抛出一个LazyLoad的Exception。所以为了解决这个问题,Spring引入了这个Filter,使得Hibernate的Session的生命周期变长。
配置:
1
2
3
4
5
|
<!-- openSessionInView(请求结束后,才关闭session):注意配置的顺序,责任连,函数调用 -->
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
|
PS:因为是过滤器,一定要注意它的位置,要将它放在配置struts2的前面。
我的第一个SSH示例:
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
|
<?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">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
<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>
<!-- 默认加载:WEB-INF/applicationContext.xml -->
</listener>
<!-- openSessionInView(请求结束后,才关闭session):注意配置的顺序,责任连,函数调用 -->
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
</web-app>
|
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
|
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd " >
<context:component-scan base-package="net.zmcheng"/>
<!-- 设置数据源:提供了一个标准化的取得数据库连接的方式,一看到property我们就应该有一个意识,那就是这个类当中有这个属性的setter方法来进行注入 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/BSWS?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<!-- 整合Hibernate -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 使用注解的方式
<property name="annotatedClasses">
<list><value>net.zmcheng.model.NlUser</value></list>
</property>
-->
<property name="mappingResources">
<list>
<value>net/zmcheng/model/NlUser.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- 声明式事务 -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 采用@Transactional注解方式使用事务
<tx:annotation-driven transaction-manager="txManager"/>-->
<bean id=" logInterceptor" class="net.zmcheng.aop.LogInterceptor"/>
<aop:config>
<aop:pointcut expression="execution(public * net.zmcheng.serviceImpl..*.*(..))" id="servicePointCut"/>
<aop:advisor pointcut-ref="servicePointCut" advice-ref="txAdvice"/>
<aop:aspect id="logAspect" ref=" logInterceptor">
<aop:before method="before" pointcut-ref="servicePointCut"/>
<aop:around method="aroundMethod" pointcut-ref="servicePointCut"/>
</aop:aspect>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
</beans>
|
struts2.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 静态变量配置区域 -->
<!-- 执行动态编译 ,在开发完成之后要修改为false-->
<constant name="struts.devMode" value="true"></constant>
<!-- 支持ognl表达式访问静态方法 -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
<!-- 配置视图编码方式为UTF-8-->
<constant name="struts-i18n.encoding" value="UTF-8"></constant>
<package name="zmc2" namespace="/user" extends="struts-default">
<action name="login" class="net.zmcheng.action.LoginRegisterAction">
<result>/demo.jsp</result>
</action>
</package>
</struts>
|
action:
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
|
package net.zmcheng.action;
import com.opensymphony.xwork2.ActionSupport;
import net.zmcheng.service.UserService;
public class LoginRegisterAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String name;
private String psw;
public UserService getUserServiceImpl() {
return userServiceImpl;
}
public void setUserServiceImpl(UserService userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
private UserService userServiceImpl;
public String execute() throws Exception{
userServiceImpl.add();
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
}
|
PS:DAO层,业务层之前博客有,在此不在缀余,业务层没写什么内容也就不粘了。