该问题与ModelDriven
和Struts 2.3.16有关。由于params
拦截器的行为已更改为访问传递给操作的参数,因此需要配置acceptParamNames
列表以与ModelDriven
操作一起使用。如果acceptParamNames
列表为空,则默认情况下通过默认模式接受params。假设我们有一个
ModelDriven
操作:
@Namespace("/modelDriven")
public class ModelDrivenAction extends ActionSupport implements ModelDriven {
private Gangster model = new Gangster();
private String name; //getter and setter
public Object getModel() {
return model;
}
@Actions({
@Action(value="modelDriven", results=@Result(location = "/modelDriven/modelDriven.jsp")),
@Action(value="modelDrivenResult", results=@Result(location = "/modelDriven/modelDrivenResult.jsp"))
})
public String execute() throws Exception {
model.setName(name);
return SUCCESS;
}
}
模特:
public class Gangster {
private String name; //getter and setter
}
modelDriven.jsp:
<s:form id="modelDrivenForm" action="modelDrivenResult" method="POST" namespace="/modelDriven">
<s:textfield
label="Gangster Name"
name="[1].name"/>
<sj:submit cssClass="btn btn-primary" executeScripts="true" targets="div1"/>
</s:form>
<div id="div1"/>
modelDrivenResult.jsp:
<s:label
label="Gangster Name"
name="name"/><br/>
在动作execute
方法中,我们得到参数name
,它应该由params
拦截器填充并初始化model属性以在结果中显示它。但问题是参数未填充。如何让参数name
被params拦截器填充,所以动作可以显示值?
答案 0 :(得分:0)
name
是模型的属性,也是动作类的属性。 modelDriven
拦截器将模型推送到值堆栈之上,因此在JSP中很容易使用它。操作对象位于模型下方。因此,可以使用[1]
前缀直接引用它。见OGNL basics。
但如果模型和操作对象中没有重复的属性名称,则没有必要。当OGNL评估诸如name
之类的名称时,它会从值堆栈的顶部搜索到属性访问器的堆栈。第一个找到的访问者将被执行。因此,model属性具有优先级,因为模型位于值堆栈之上。
如果应在操作上设置名称为name
的属性,则可以直接将该属性命名为[1].name
。但是,params
拦截器的默认模式不接受此类参数名称。但是,它是一个有效的OGNL表达式。因此,要让它通过拦截器,您需要将其添加到接受的参数名称模式中。像那样
@Action(value="modelDrivenResult", results=@Result(location = "/modelDriven/modelDrivenResult.jsp"),
interceptorRefs = @InterceptorRef(value="defaultStack", params={
"params.acceptParamNames", "(\\[\\d+\\]\\.)*\\w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['\\w+'\\])|(\\('\\w+'\\)))*"
})
)
这是因为OGNL还检查接受参数的模式,这个正则表达式模式允许匹配params
和OGNL匹配器。