« | August 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | 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 | | | | | | | |
| 公告 |
戒除浮躁,读好书,交益友 |
Blog信息 |
blog名称:邢红瑞的blog 日志总数:523 评论数量:1142 留言数量:0 访问次数:9691658 建立时间:2004年12月20日 |

| |
[j2ee]Struts加载spring的问题 原创空间, 软件技术
邢红瑞 发表于 2005/8/5 8:41:29 |
前几天不是一个同事使用OpenSessionInView pattern时,遇到Hibernate 3的mappinglazy="true"的问题,也不会想到它struts启动spring的WebApplicationContextspring有三种启动方式,使用ContextLoaderServlet,ContextLoaderListener和ContextLoaderPlugIn.看一下ContextLoaderListener的源码,这是一个ServletContextListener/** * Initialize the root web application context. */ public void contextInitialized(ServletContextEvent event) { this.contextLoader = createContextLoader(); this.contextLoader.initWebApplicationContext(event.getServletContext()); } /** * Create the ContextLoader to use. Can be overridden in subclasses. * @return the new ContextLoader */ protected ContextLoader createContextLoader() { return new ContextLoader(); } contextLoader的源码 public WebApplicationContext initWebApplicationContext(ServletContext servletContext) throws BeansException {
long startTime = System.currentTimeMillis(); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } servletContext.log("Loading Spring root WebApplicationContext");
try { // Determine parent for root web application context, if any. ApplicationContext parent = loadParentContext(servletContext);
WebApplicationContext wac = createWebApplicationContext(servletContext, parent); servletContext.setAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
if (logger.isInfoEnabled()) { logger.info("Using context class [" + wac.getClass().getName() + "] for root WebApplicationContext"); } if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext [" + wac + "] as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); }
if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); }
return wac; } catch (RuntimeException ex) { logger.error("Context initialization failed", ex); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; } catch (Error err) { logger.error("Context initialization failed", err); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err); throw err; } } 注意WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,这里面放了WebApplicationContext,需要使用时从ServletContext取出 可以使用WebApplicationContextUtils得到WebApplicationContext public static WebApplicationContext getWebApplicationContext(ServletContext sc) { Object attr = sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); if (attr == null) { return null; } if (attr instanceof RuntimeException) { throw (RuntimeException) attr; } if (attr instanceof Error) { throw (Error) attr; } if (!(attr instanceof WebApplicationContext)) { throw new IllegalStateException("Root context attribute is not of type WebApplicationContext: " + attr); } return (WebApplicationContext) attr; } 关键的问题在于struts如何启动的spring的,ContextLoaderPlugIn的源码 // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); public String getServletContextAttributeName() { return SERVLET_CONTEXT_PREFIX + getModulePrefix(); } 不同加载的Key竟然不同,原因就是WebApplicationContext放在那里的问题,可spring调用的时候会根据WebApplicationContext里面定义的那个名字去找的,问题出在这里
在struts-config.xml中配置 <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml" /> </plug-in>
<controller> <set-property property="processorClass" value="org.springframework.web.struts.DelegatingRequestProcessor" /> </controller> 原理是这样的,Struts虽然只能有一个ActionServlet实例,但是对于不同的子应用分别能有自己的RequestProcessor实例每个RequestProcessor实例分别对应不同的struts配置文件。 子应用的ProcessorClass类必须重写一般就是继承RequestProcessor类,然后再其配置文件的controller元素中的<processorClass>属性中作出修改。那么当 getRequestProcessor(getModuleConfig(request)).process(request,response);就能根据request选择相应的moduleconfig,再根据其<processorClass>属性选择相应的RequestProcessor子类来处理相应的请求了。
|
|
|