最近碰到一个小要求,想让一些action返回的resultType默认为freemarker,开始是想在action上配置全局的result,然后name用一个表达式,然后type="freemarker",
但是经过实验,发现不行,因为这些配置是在struts2一启动的时候就已经实例化了,再在action中使用表达式起不了作用,最后会报异常.
于是去跟踪源码,最后在PackageConfig这个类中找到了相关的代码
public String getFullDefaultResultType() { if ((defaultResultType == null) && !parents.isEmpty()) { for (PackageConfig parent : parents) { String parentDefault = parent.getFullDefaultResultType(); if (parentDefault != null) { return parentDefault; } } } return defaultResultType; }
这个是一个递归查询,如果本包没有配置,就会查找父包,最后会找到default-package中,这个里面指定了为dispatcher.
好吧,代码是找到了,那么如何更改呢,
只需要在包中重新申明一下这个result-type
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult" default="true" />
并指定为default,
在解析这个包的时候就会将这个设置为默认的result-type.
相关代码在com.opensymphony.xwork2.config.providers.XmlConfigurationProvider类的addResultTypes方法中.
protected void addResultTypes(PackageConfig.Builder packageContext, Element element) { NodeList resultTypeList = element.getElementsByTagName("result-type"); for (int i = 0; i < resultTypeList.getLength(); i++) { Element resultTypeElement = (Element) resultTypeList.item(i); String name = resultTypeElement.getAttribute("name"); String className = resultTypeElement.getAttribute("class"); String def = resultTypeElement.getAttribute("default"); Location loc = DomHelper.getLocationObject(resultTypeElement); Class clazz = verifyResultType(className, loc); if (clazz != null) { String paramName = null; try { paramName = (String) clazz.getField("DEFAULT_PARAM").get(null); } catch (Throwable t) { // if we get here, the result type doesn't have a default param defined. } ResultTypeConfig.Builder resultType = new ResultTypeConfig.Builder(name, className).defaultResultParam(paramName) .location(DomHelper.getLocationObject(resultTypeElement)); Map<String, String> params = XmlHelper.getParams(resultTypeElement); if (!params.isEmpty()) { resultType.addParams(params); } packageContext.addResultTypeConfig(resultType.build()); // set the default result type if ("true".equals(def)) { packageContext.defaultResultType(name); } } } }
这段代码用来解析struts2的配置文件,获得result-type元素,然后,解析相关元素,如果设置了default为true,则会将这个result-type设置为默认的.