问题与ModelDriven和Struts 2.3.16有关。由于params拦截器的行为更改为访问传递给操作的参数,因此需要配置acceptParamNames列表以与ModelDriven操作一起使用。如果acceptParamNameslist为空,则默认情况下它将通过默认模式接受参数。假设我们有一个
ModelDriven
params
acceptParamNames
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/>
在action execute方法中,我们获取name应由params拦截器填充的参数,并初始化model属性以将其显示在结果中。但是问题是没有填充参数。如何获取name由params拦截器填充的参数,以便操作可以显示值?
execute
name
该name是模型的财产,也是动作类的属性。该modelDriven拦截器推值堆顶部的模型,所以很容易在JSP中使用它。动作对象位于模型下方。因此,可以使用[1]前缀直接引用它。请参阅OGNL基础。
modelDriven
[1]
但是,如果模型和操作对象中没有重复的属性名称,则没有必要。当名称name由OGNL评估时,它将从值堆栈的顶部搜索到堆栈的下方,以查找属性访问器。找到的第一个访问器将被执行。因此,模型属性具有优先级,因为模型位于值堆栈的顶部。
如果name应在操作中设置具有名称的属性,则可以直接将该属性命名为[1].name。但是,params拦截器的默认模式不接受此类参数名称。但是,它是有效的OGNL表达式。因此,要使其通过拦截器,您需要将其添加到已接受参数名称的模式中。像那样
[1].name
@Action(value="modelDrivenResult", results=@Result(location = "/modelDriven/modelDrivenResult.jsp"), interceptorRefs = @InterceptorRef(value="defaultStack", params={ "params.acceptParamNames", "(\\[\\d+\\]\\.)*\\w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['\\w+'\\])|(\\('\\w+'\\)))*" }) )
这是因为OGNL还会检查接受参数的模式,并且此正则表达式模式允许同时匹配paramsOGNL匹配器。