struts2 handle static resource
在web.xml中作如下配置:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>packages</param-name>
<param-value>net.zdsoft.eis.template</param-value>
</init-param>
</filter><filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping><filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/static/*</url-pattern>
</filter-mapping>用于处理静态资源(css、js、图片之类),启动后正常。但当修改了struts配置文件,并且struts.configuration.xml.reload=true时,再次加载静态资源时会出错如下错误:
java.lang.NullPointerException at org.apache.struts2.dispatcher.DefaultStaticContentLoader.findStaticResource(DefaultStaticContentLoader.java:164)
atorg.apache.struts2.dispatcher.ng.ExecuteOperations.executeStaticResourceRequest(ExecuteOperations.java:62)
atorg.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:86)
atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
原因:重新加载配置文件时,静态资源的处理类DefaultStaticContentLoader的setHostConfig(HostConfig filterConfig)方法没调用,导致pathPrefixes为空。解决方案:
1、继承StrutsPrepareOperations类,构造方法中传入参数FilterConfig。createActionContext方法中如果oldContext为空,则重新初始化静态资源配置。完整代码如下:
public class StrutsPrepareOperations extends PrepareOperations {
privateServletContextservletContext;
privateDispatcherdispatcher;
private FilterHostConfig config;public StrutsPrepareOperations(ServletContext servletContext, Dispatcher dispatcher,
FilterConfigfilterConfig){
super(servletContext,dispatcher);
this.dispatcher=dispatcher;
this.servletContext=servletContext;
this.config=newFilterHostConfig(filterConfig);
}// 重写doFilter,由于在struts配置文件重新加载后,静态资源有问题
/**
*Createstheactioncontextandinitializesthethreadlocal
*/
publicActionContextcreateActionContext(HttpServletRequestrequest,
HttpServletResponseresponse){
ActionContextctx;
Integercounter=1;
IntegeroldCounter=(Integer)request.getAttribute(CLEANUP_RECURSION_COUNTER);
if(oldCounter!=null){
counter=oldCounter+1;
}ActionContext oldContext = ActionContext.getContext();
if(oldContext!=null){
//detectedexistingcontext,soweareprobablyinaforward
ctx=newActionContext(newHashMap<String,Object>(oldContext.getContextMap()));
}else{
ValueStackstack=dispatcher.getContainer().getInstance(ValueStackFactory.class)
.createValueStack();
stack.getContext().putAll(
dispatcher.createContextMap(request,response,null,servletContext));
ctx = new ActionContext(stack.getContext());// add by zhaosf
StaticContentLoaderstaticResourceLoader=dispatcher.getContainer().getInstance(
StaticContentLoader.class);
staticResourceLoader.setHostConfig(config);
}
request.setAttribute(CLEANUP_RECURSION_COUNTER,counter);
ActionContext.setContext(ctx);
returnctx;
}2、继承org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter时,重写init方法,如下:
public class StrutsFilter extends StrutsPrepareAndExecuteFilter {
@Override
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
InitOperationsinit=newInitOperations();
try{
FilterHostConfigconfig=newFilterHostConfig(filterConfig);
init.initLogging(config);
Dispatcherdispatcher=init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);prepare = new StrutsPrepareOperations(filterConfig.getServletContext(), dispatcher,
filterConfig);
execute=newExecuteOperations(filterConfig.getServletContext(),dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);postInit(dispatcher, filterConfig);
}finally{
init.cleanup();
}
}