Spring4笔记12--SSH整合3--Spring与Struts2整合
SSH 框架整合技术:
3. Spring与Struts2整合(对比SpringWeb):
Spring 与 Struts2 整合的目的有两个:
(1)在 Struts2 的 Action 中,即 View 层,获取到 Service。然后就实现了在 Struts2 项目中 View 层、Service 层、Dao 层的联通。
(2)将 Action 实例交由 Spring 容器管理。
代码详解:
(1) 将 Servlet 修改成 Action:
package com.tongji.actions; import com.tongji.beans.Student;
import com.tongji.service.IStudentService; public class RegisterAction {
private String name;
private int age; //声明Service对象
private IStudentService service; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public IStudentService getService() {
return service;
} public void setService(IStudentService service) {
this.service = service;
} public String execute() {
Student student = new Student(name, age);
service.addStudent(student);
return "success";
}
}
注意:直接将Service作为Action的属性
(2) 在 Spring 配置文件中注册 Action 的 Bean
在 Spring 的配置文件中将 Action 作为一个普通 Bean 进行定义,并在配置文件中完成 Service 的注入。即添加如下代码:
<!-- 注册Action:必须指定Action的scope为prototype,因为Action是多例的 -->
<bean id="registerAction" class="com.tongji.actions.RegisterAction" scope="prototype">
<property name="service" ref="studentService"/>
</bean>
(3) Struts2 配置文件中的 class 使用伪类名
Struts2 配置文件中的<action/>标签的 class 属性值不再是 Action 的全类名了,而是个伪类名:Spring 配置文件中该 Bean 的 id 名。
<?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>
<package name="ssh" namespace="/test" extends="struts-default">
<!-- class的值是Spring容器中Action的Bean的id值,此时的class的属性值称为 伪类 -->
<action name="register" class="registerAction">
<result>/welcome.jsp</result>
</action>
</package>
</struts>
(4) 修改前端页面:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html>
<head>
<title>index</title>
</head> <body>
<form action="test/register.action" method="POST">
name:<input type="text" name="name"/><br>
age:<input type="text" name="age"/><br>
<input type="submit" value="submit"/>
</form>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html>
<head>
<title>welcome</title>
</head> <body>
welcome you!
</body>
</html>
(5) 其余代码都不变,发布运行即可。
补充问题:当将事务织入到 Service 层后,在 Dao 层通过 load()等具有延迟加载功能的方法加载实体时,会出现异常。
View 层要读取一个对象的某属性值,所以在 View 层调用了 Service 层的对象获取方法。此时 Service 层就会去调用 Dao 层,欲从 DB 中读取数据。但由于 Service 层并非是真正需要数据的一方,即 Servcie 层并非真正需要数据的详情。又由于 Dao 层使用了延迟加载技术,所以返回给 Service 层一个数据为空的代理对象。当 Service 获取到了这个对象后,马上将这个对象返回给了 View 层。Service 层认为任务完成,所以将事务进行了关闭。由于 Session 必须在事务环境下运行,且事务在提交或回滚后,会首先将Session 关闭,而后关闭事务。所以事务关闭前,Session 就已经消失。当 View 层收到 Service 层发送来的对象,并使用其详情时,发现为空。此时 View 层向 Service 层发出进行真正查询请求时,Service 层的 Session 已经不存在,所以,会报出 Session 为空的异常。
解决办法:
问题的主要原因是事务应用在业务层,而延迟加载使得对 Hibernate 的 Session 的连续使用放在了 View 层。若要 Session 不进行自动关闭,必须使其所在的事务环境不能在 Service 层就结束,所以可以将 Session 的开启放在 View 层。
只需在 web.xml 中注册一个过滤器 OpenSessionInViewFilter(开启 Session 在 View),只要用户提交请求,就会先执行该过滤器,将 Session 开启。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<!-- 指定Spring配置文件的名称及位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param> <!-- 注册监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <!-- 注册OpenSessionInViewFilter,要求其必须在Struts启动项这个Filter的前面注册 -->
<filter>
<filter-name>OpenSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
<!-- 默认OpenSessionInViewFilter加载的SessionFactory名称为sessionFactory
这里指定自己定义的SessionFactory的名称,让OpenSessionInViewFilter加载 -->
<!-- <init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>mySessionFactory</param-value>
</init-param> -->
</filter>
<filter-mapping>
<filter-name>OpenSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- 注册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> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list> </web-app>
注册过滤器时需要注意:
(1)该过滤器会自动从 Spring 配置文件中查找名称为 sessionFactory 的 Bean。若定义的不是这个名称,则需通过初始化参数<init-param/>进行指定。

(2)该过滤器应注册在 StrutsPrepareAndExecuteFilter 的前面,即在进入 Struts2 之前先执行过滤,否则还会出现noSession的问题。其注册顺序可以从 Struts2 的流程图中看出。

过滤器的执行都是通过过滤器链串起来执行的,即当前的 Filter 通过在自己的 doFilter() 方法中执行 chain.doFilter()来调用执行下一下过滤器。
查看 StrutsPrepareAndExecuteFilter 的源码可以看出,只有当没有 Action 要执行时,才可能会执行其它的过滤器,即调用 chain.doFilter()。否则,只要有 Action 能够匹配上执行,那么就没有 chain.doFilter()方法要执行了,即 Struts2 的 StrutsPrepareAndExecuteFilter 将成为最后一个被执行的 Filter。所以,只有将 OpenSessionInViewFilter 放到 Struts2 的过滤器StrutsPrepareAndExecuteFilter 的前面才会被执行到。

至此,SSH整合就结束了。
Spring4笔记12--SSH整合3--Spring与Struts2整合的更多相关文章
- Spring与Struts2整合VS Spring与Spring MVC整合
Spring与Struts2整合,struts.xml在src目录下 1.在web.xml配置监听器 web.xml <!-- 配置Spring的用于初始化ApplicationContext的 ...
- spring与struts2整合出现错误HTTP Status 500 - Unable to instantiate Action
在进行spring和struts2整合的时候因为大意遇到了一个问题,费了半天神终于找到了问题所在,故分享出来望广大博友引以为戒!! 我们都知道在spring和struts2整合时,spring接管了a ...
- SSM整合(2): spring 与 mybatis 整合
在进行完spring与springmvc整合之后, 继续 spring与mybatis的整合. 既然是操作数据库, 那必然不能缺少了连接属性 一. db.properties jdbc.driver= ...
- Spring与Struts2整合时action自动注入的问题
当Struts和Spring框架进行整合时,原本由action实例化对象的过程移交给spring来做(这个过程依赖一个叫struts2-spring-plugin的jar包,这个包主要的功能就是实现刚 ...
- Spring与Struts2整合
Spring与Struts2为什么要整合呢? 把Action实例交给Spring来管理!! 1.单独测试Struts是否添加成功(jar包和配置文件),先单独测试,不要整合之后再测试,容易出问题 we ...
- SSM整合(1): spring 与 springmvc 整合
久没有写博客了, 今年事情太多了, 也没了心思. 去深圳出差, 更重要的结婚的事情, 一茬接一茬. 好在最近闲暇一些, 就想记录一些曾经困扰过我的问题(现在用spring boot真是太方便了, 很 ...
- Spring注解与Spring与Struts2整合
@Component @Controller @Service @Repository 四大注解作用基本一样,只是表象在不同层面 @Resource @Scope Struts2与Spring整合:1 ...
- Spring和Struts2整合
目的:spring容器管理Action类,代替Servlet 步骤:主要在配置文件 Struts2: 添加支持spring的jar包, 配置<action class="Action类 ...
- spring+hibernate+Struts2 整合(全注解及注意事项)
最近帮同学做毕设,一个物流管理系统,一个点餐系统,用注解开发起来还是很快的,就是刚开始搭环境费了点事,今天把物流管理系统的一部分跟环境都贴出来,有什么不足的,请大神不吝赐教. 1.结构如下 2.jar ...
- spring与struts2整合出现常见错误
错误信息 严重: Exception starting filter struts2 Unable to load configuration. - bean - jar:file:/F:/Strut ...
随机推荐
- 关于nginx的一点记录
(1) 安装nginx官网下载:http://nginx.org下载适合Windows的安装包,是一个压缩包,直接解压就可以了. (2) 启动nginx有三种方式启动:a. 双击nginx.exe图标 ...
- 前端基础:HTTP 状态码详解
HTTP 状态码详解 1xx(信息类):表示接收到请求并继续处理 100 客户端应当继续发送请求.这个临时响应是用来通知客户端他的部分请求已经被服务器接收,且仍未被拒绝.客户端应当继续发送请求的剩余部 ...
- BZOJ5308 ZJOI2018胖
贝尔福特曼(?)的方式相当于每次将所有与源点直接相连的点的影响区域向两边各扩展一格.显然每个点在过程中最多更新其他点一次且这些点构成一段连续区间.这个东西二分st表查一下就可以了.注意某一轮中两点都更 ...
- What?
What? 本文主要讲解一下kubernetes周边的概念,可以说是一小部分的生态圈,逐渐了解一下,走进kubernetes的世界.请读者在读的时候,带着批判的态度去读. 一张概览图: 云计算: 原文 ...
- 读取Maven项目下resources目录下的配置文件(properties为例)
配置文件:xxxxx.properties a.url=******************** b.url=---------------------------------- 读取配置文件: im ...
- 遇到问题---java---@value注解为null
Spring 3支持@value注解的方式获取properties文件中的配置值,大简化了读取配置文件的代码. 在xml文件中配置properties文件 例如 cas.authn.mongo.col ...
- java堆溢出
java堆是用来存储对象实例的:只要不断创建对象,GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,当对象数量达到最大堆的容量限制的时候就会产生内存溢出异常.异常对战信息为OutOf ...
- android中的style部分属性值介绍 --zz
Android平台定义的主题样式: android:theme="@android:style/Theme.Dialog" 将一个Activity显示为对话框模式 •andro ...
- Android之断点续传下载(转)
Android之断点续传下载http://www.cnblogs.com/zxl-jay/archive/2011/10/09/2204195.html
- bzoj 2428: [HAOI2006]均分数据 && bzoj 3680 : 吊打XXX 模拟退火
每次把元素随便扔随机一个初始解,退火时每次随机拿一个元素扔到随机一个集合里,当温度高时因为状态不稳定扔到那个元素和最小的里边. 如果新解优,更新ans. 把原式拆一下,就可以用int存了. bzoj ...