struts2 18拦截器详解(十六)
actionmappingparametersinteceptor拦截器处于defaultstack第十四的位置,该拦截器继承自parametersinterceptor,也是用于把参数设置到valuestack中,只不过该拦截器的参数是来源于actionmapping中,而不是来自请求参数。往valuestack中设置值的逻辑与parametersinterceptor一模一样,正是这个原因才把parametersinterceptor拦截器放在了该拦截器之前讲解。大家可以发现该拦截器只是覆盖了parametersinterceptor的两个方法:
[java] view plaincopy
@override
protected map<string, object> retrieveparameters(actioncontext ac) {
//获取acitonmapping对象
actionmapping mapping = (actionmapping) ac.get(servletactioncontext.action_mapping);
if (mapping != null) {
return mapping.getparams();//获取acitonmapping参数
} else {
return collections.emptymap();
}
}
@override//将参数设置到actioncontext的parameters map中
protected void addparameterstocontext(actioncontext ac, map newparams) {
//获取请求参数
map previousparams = ac.getparameters();
map combinedparams = null;
if (previousparams != null) {
combinedparams = new treemap(previousparams);
} else {
combinedparams = new treemap();
}
//newparams为actionmapping中的经过了合法性检查后的合法参数
combinedparams.putall(newparams);
//将请求参数与合法参数一起设置到actioncontext的parameters map中
ac.setparameters(combinedparams);
}
因为现在执行的是actionmappingparametersinteceptor拦截器所以在parametersinterceptor的dointercept方法中调用的retrieveparameters方法是actionmappingparametersinteceptor拦截器中的retrieveparameters,这是java多态的表现,所以该拦截器通过覆盖父类的retrieveparameters方法达到了改变参数来源的目的。
在parametersinterceptor拦截器的setparameters方法中最后一句调用了addparameterstocontext方法,而在actionmappingparametersinteceptor子类中覆盖了addparameterstocontext方法,所以执行的也是actionmappingparametersinteceptor拦截器定义的addparameterstocontext方法,将将请求参数与合法参数一起设置到actioncontext的parameters map中。
但有一点需要大家注意,就是actionmapping的参数永远为null,所以执行该拦截器时为valuestack设置值的操作根本就不会发生,下面通过源代码进行证明。在证明之前actionconfig,actionmapping,actionmapper之间的关系需要明白,actionconfig对象保存的是action的配置信息,actionmapping对象保存的是action的映射信息,actionmapper是根据你访问的url去actionconfig中进行匹配再映射成actionmapping对象。例如,一个action的配置中可以有多个方法,可以有多个result,但是在执行的时候只能执行action中的一个方法,返回的时候只能有一个result而actionmapper的功能就是根据url与acitonconfig映射成actionmapping对象。
strutsprepareandexecutefilter的dofilter方法:
[java]
public void dofilter(servletrequest req, servletresponse res, filterchain chain) throws ioexception, servletexception {
//省略...
actionmapping mapping = prepare.findactionmapping(request, response, true);//调用prepare对象的findactionmapping
//省略...
}
下面是findactionmapping方法:
[java]
public actionmapping findactionmapping(httpservletrequest request, httpservletresponse response, boolean forcelookup) {
actionmapping mapping = (actionmapping) request.getattribute(struts_action_mapping_key);
if (mapping == null || forcelookup) {
try {
//去容器中找actionmapper对象,并调用actionmapper对象的getmapping方法返回actionmapping对象
mapping = dispatcher.getcontainer().getinstance(actionmapper.class).getmapping(request, dispatcher.getconfigurationmanager());
if (mapping != null) {
request.setattribute(struts_action_mapping_key, mapping);
}
} catch (exception ex) {
dispatcher.senderror(request, response, servletcontext, httpservletresponse.sc_internal_server_error, ex);
}
}
return mapping;
}
actionmapper是一个接口,在struts2中其默认实现类是org.apache.struts2.dispatcher.mapper.defaultactionmapper,下面是该类的getmapping方法:
[java]
public actionmapping getmapping(httpservletrequest request, configurationmanager configmanager) {
actionmapping mapping = new actionmapping();//新建一个actionmapping对象
string uri = geturi(request);//获取uri
int indexofsemicolon = uri.indexof(";");
uri = (indexofsemicolon > -1) ? uri.substring(0, indexofsemicolon) : uri;//处理 uri
uri = dropextension(uri, mapping);//去掉uri后缀
if (uri == null) {
return null;
}
//解析action的namespace与name
parsenameandnamespace(uri, mapping, configmanager);
//处理特殊参数
handlespecialparameters(request, mapping);
if (mapping.getname() == null) {
return null;
}
//解析actionname,因为struts2可以支持动态方法调用,如:xxxaction!login
parseactionname(mapping);
return mapping;
}
一开始以为会在handlespecialparameters设置actionmapping参数,但进去看了以后发现也没有为actionmapping设置参数的操作,所以对于用defaultactionmapper作为actionmapper的的实现类的话,actionmapping中的参数是为null的。
到此该拦截器就讲到这里了,准备下一个拦截器......
上一篇: C++ —— C++运算符与表达式
下一篇: Struts2配置及案例实现