java中关于Struts和spring集成的一些原理剖析
来源:互联网 发布:ipad软件连不上网络 编辑:程序博客网 时间:2024/05/18 12:33
用过ssh的人都知道struts和spring的有很多种集成方式现在我就常用的一些spring类做简单的剖析,我们先看第一个类org.springframework.web.struts.DelegatingActionProxy,我们看一些它做了那些事。
//看到Action 就知道他也是一个Action
public class DelegatingActionProxy extends Action {
public DelegatingActionProxy() {
}
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Action delegateAction = getDelegateAction(mapping);//通过映射文件mapping找到spring创建的ActionBean,然后委托他,其实这种方式也是一种代理,只是显现的方式有些不同吧了。
return delegateAction.execute(mapping, form, request, response);
}
protected Action getDelegateAction(ActionMapping mapping)
throws BeansException {
WebApplicationContext wac = getWebApplicationContext(getServlet(),
mapping.getModuleConfig());//通过ServletContext找到WebApplicationContext ,当spring的ContextLoaderListener或ContextServlet创建好之后放在ServletContext中就是application中
String beanName = determineActionBeanName(mapping);//通过mapping查找actionName
return (Action) wac.getBean(beanName, org / apache / struts / action
/ Action);//从WebApplicationContext 查找ActionBean
}
protected WebApplicationContext getWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig)
throws IllegalStateException {
return DelegatingActionUtils.findRequiredWebApplicationContext(
actionServlet, moduleConfig);
}
protected String determineActionBeanName(ActionMapping mapping) {
return DelegatingActionUtils.determineActionBeanName(mapping);
}
}
通过DelegatingActionProxy 的源码我们知道struts在访问spring创建好的Action时是通过spring的代理Action在调用execute方法时委托给Action来现实的,那是不是只有这一种方式了,其实不然,我们在看另外的一种方式。
Struts1中还有一种通过processor来控制的,当用户的一个请求发出给了ActionServlet之后紧接着ActionServlet把请求交给了Processor处理下面就看一下spring是如何处理的。
public class DelegatingRequestProcessor extends RequestProcessor {
public DelegatingRequestProcessor() {
}
public void init(ActionServlet actionServlet, ModuleConfig moduleConfig)
throws ServletException {
super.init(actionServlet, moduleConfig);
if (actionServlet != null)
webApplicationContext = initWebApplicationContext(actionServlet,
moduleConfig);//初始化webApplicationContext
}
//关键地方是在这里
protected Action processActionCreate(HttpServletRequest request,
HttpServletResponse response, ActionMapping mapping)
throws IOException {
//当创建Action时spring做了处理,从webApplicationContext 中取出创建好的Action实例,然后把请求交给Action实例。
Action action = getDelegateAction(mapping);
if (action != null)
return action;
else
return super.processActionCreate(request, response, mapping);
}
private WebApplicationContext webApplicationContext;
}
这个是上面的类似都是代理的方式实现的。这是spring和struts的集成问题,那spring和hibernate的集成有没有问题了,请看下面的代码。
public class OpenSessionInViewFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException
{
SessionFactory sessionFactory;
boolean participate;
sessionFactory = lookupSessionFactory(request);//查找SessionFactory
participate = false;
if(isSingleSession())//session是不是单例
{
if(TransactionSynchronizationManager.hasResource(sessionFactory))
{
participate = true;
} else
{
logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
Session session = getSession(sessionFactory);//获取Session
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));//绑定Session到当前的线程中
}
} else
if(SessionFactoryUtils.isDeferredCloseActive(sessionFactory))
participate = true;
else
SessionFactoryUtils.initDeferredClose(sessionFactory);
filterChain.doFilter(request, response);
break MISSING_BLOCK_LABEL_154;
Exception exception;
exception;
if(!participate)
if(isSingleSession())
{
SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);//请求执行完毕之后又解除绑定
logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");
closeSession(sessionHolder.getSession(), sessionFactory);
} else
{
SessionFactoryUtils.processDeferredClose(sessionFactory);//处理延迟关闭的Session
}
throw exception;
if(!participate)
if(isSingleSession())
{
SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");
closeSession(sessionHolder.getSession(), sessionFactory);//关闭Session
} else
{
SessionFactoryUtils.processDeferredClose(sessionFactory);//处理延迟关闭的session
}
return;
}
通过以上的代码的分析我们知道在处理一次请求可以使用一个Session或多个Session而且Session不是调用完了就立即关闭而是等到一次请求完毕之后再统一关闭。为什么要这样做了?我们都知道hibernate有延迟加载的功能但是通常session使用完了就关闭了所以当遇到延迟加载的对象就出现Session已经关闭的异常消息,那为什么配置了SessionInViewFilter就可以避免了,是因为session在Filter过滤请求之前打开,在Filter过滤请求之后才关闭满足了延迟加载。那为什么Filer可以再请求之前了,我们都知道用户请求的一般执行过程,现实Filter过滤然后再是Servlet或者Action,那这又和页面访问对象的属性有什么关系了,Servlet和Action执行完了之后还是要关闭Session啊,这是因为页面也是Servlet,这样Filter就在页面请求的所有资源就可以再Filter中过滤了,Session是在页面动态构建好之后显示在用户之前关闭的。其实jsp页面对解析成Servlet了然后在Service方法中动态的构建好html然后输出的。不信可以看一下Tomcat中的work目录中我们的项目,全部是Jsp页面对应的Servlet类。
下面看一下DispatchAction如何实现动态调用Action中的方法。
public abstract class DispatchAction extends Action {
public DispatchAction() {
clazz = getClass();
methods = new HashMap();
types = (new Class[] { org.apache.struts.action.ActionMapping.class,
org.apache.struts.action.ActionForm.class,
javax.servlet.http.HttpServletRequest.class,
javax.servlet.http.HttpServletResponse.class });
}
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
if (isCancelled(request)) {
ActionForward af = cancelled(mapping, form, request, response);
if (af != null)
return af;
}
String parameter = getParameter(mapping, form, request, response);//获取页面提交过来的参数(mapping对应parameter 具体的方法参数)
String name = getMethodName(mapping, form, request, response, parameter);//获取方法名称parameter对应的参数值
if ("execute".equals(name) || "perform".equals(name)) {
String message = messages.getMessage("dispatch.recursive", mapping
.getPath());
log.error(message);
throw new ServletException(message);
} else {
return dispatchMethod(mapping, form, request, response, name);//调用Action的中的方法
}
}
protected ActionForward dispatchMethod(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response, String name) throws Exception {
if (name == null)
return unspecified(mapping, form, request, response);
Method method = null;
try {
method = getMethod(name);//从反射机制获取对应的方法
} catch (NoSuchMethodException e) {
String message = messages.getMessage("dispatch.method", mapping
.getPath(), name);
log.error(message, e);
String userMsg = messages.getMessage("dispatch.method.user",
mapping.getPath());
throw new NoSuchMethodException(userMsg);
}
ActionForward forward = null;
try {
Object args[] = { mapping, form, request, response };//Action中的方法参数列表
forward = (ActionForward) method.invoke(this, args);//使用反射动态的调用Action中的方法
} catch (ClassCastException e) {
String message = messages.getMessage("dispatch.return", mapping
.getPath(), name);
log.error(message, e);
throw e;
} catch (IllegalAccessException e) {
String message = messages.getMessage("dispatch.error", mapping
.getPath(), name);
log.error(message, e);
throw e;
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof Exception) {
throw (Exception) t;
} else {
String message = messages.getMessage("dispatch.error", mapping
.getPath(), name);
log.error(message, e);
throw new ServletException(t);
}
}
return forward;
}
}
通过以上代码分析知道DsiptcherAction是通过反射技术实现动态的调用Action中的方法。
接下来看一下spring与struts2是怎样集成的:
public class SpringObjectFactory extends ObjectFactory implements
ApplicationContextAware {
//覆盖ObjectFactory 中的方法,不使用Class直接new对象而是使用spring创建对象好的对象
public Object buildBean(String beanName, Map extraContext,
boolean injectInternal) throws Exception {
Object o = null;
try {
o = appContext.getBean(beanName);//beanName在WebApplicationContext中取出创建好的Action对象
} catch (NoSuchBeanDefinitionException e) {
Class beanClazz = getClassInstance(beanName);
o = buildBean(beanClazz, extraContext);
}
if (injectInternal)
injectInternalBeans(o);
return o;
}
}
- java中关于Struts和spring集成的一些原理剖析
- spring和struts的集成
- spring和struts的集成
- 关于spring+struts+hibernate集成的问题
- Struts+Spring+Hibernate (一) 集成原理和搭建环境
- 【Spring】Struts和Spring集成
- spring+struts的集成
- spring+struts的集成
- cxf和spring集成的一些事
- 转载:) 关于spring、hibernate、struts的一些错误问题 不断补充中(靠自己了)
- ssh中关于spring,struts,hibernate的工作机制与原理详解
- Spring集成Struts的方法
- Struts与Spring的集成
- Spring集成Struts的方法
- Spring与Struts的集成
- Struts中关于Spring的OpensesionInView
- Struts和Spring集成配置的一点小问题
- Struts和Spring集成的两种方式
- java中使用asm实现动态创一个类动态代理
- linux设备驱动开发详解 阅读笔记2(第一篇入门)
- Debian 5 lenny 的安装全过程
- C++ 模板类型萃取技术
- 关于class文件中的指令剖析
- java中关于Struts和spring集成的一些原理剖析
- java中Excel操作的简单封装
- 转一些Linux进程间通信的(IPC)的一些文章(来源于IBM developerworks)
- 用 C++开发了一个Sql Server加密解密的存储过程,同时在此基础上写了两个加密解密的函数
- java Random类详解
- java中关于Tree的操作的小例子
- Tiles框架的配置
- php与mysql程序设计 读书笔记——张迅雷闪击PHP(7-9章)
- itextshap实现在PDF上插入图片?