Struts2 源码分析-----拦截器源码解析 --- ParametersInterceptor
ParametersInterceptor拦截器其主要功能是把ActionContext中的请求参数设置到ValueStack中,如果栈顶是当前Action则把请求参数设置到了Action中,如果栈顶是一个model(Action实现了ModelDriven接口)则把参数设置到了model中。
下面是该拦截器的doIntercept方法源码:
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();//获取当前执行的Action对象
if (!(action instanceof NoParameters)) {//判断Action是否实现了NoParameters接口,实现该接口表示该Action没有任何请求参数
ActionContext ac = invocation.getInvocationContext();//获取ActionContext对象
final Map<String, Object> parameters = retrieveParameters(ac);//获取请求参数Map
//省略...
if (parameters != null) {//如果请求参数不为null
Map<String, Object> contextMap = ac.getContextMap();//获取ActionContext内部的context Map,即OgnlContext对象
try {
//省略...
ValueStack stack = ac.getValueStack();//获取值栈
setParameters(action, stack, parameters);//为值栈设置参数
} finally {
//省略...
}
}
}
return invocation.invoke();//调用下一个拦截器
}
setParameters方法才是该拦截器的主要逻辑,现在进入该方法:
protected void setParameters(Object action, ValueStack stack, final Map<String, Object> parameters) {
ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware)
? (ParameterNameAware) action : null;//判断Action有无实现ParameterNameAware接口 Map<String, Object> params;
Map<String, Object> acceptableParameters;//合法参数集合
//判断参数设置是否有序,ordered默认为false,即无序
if (ordered) {
params = new TreeMap<String, Object>(getOrderedComparator());//如果有序则要获取比较器
acceptableParameters = new TreeMap<String, Object>(getOrderedComparator());
params.putAll(parameters);
} else {
params = new TreeMap<String, Object>(parameters);
acceptableParameters = new TreeMap<String, Object>();
}
//迭代请求参数
for (Map.Entry<String, Object> entry : params.entrySet()) {
String name = entry.getKey();
//判断参数是否合法,如果Action实现了ParameterNameAware则acceptableName(name)返回true且parameterNameAware.acceptableParameterName(name)
//也返回true该参数才是合法的;如果Action没有实现ParameterNameAware则参数是否合法由acceptableName(name)方法决定
boolean acceptableName = acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name));
//如果参数合法
if (acceptableName) {
acceptableParameters.put(name, entry.getValue());//把合法参数添加到合法参数集合中
}
} ValueStack newStack = valueStackFactory.createValueStack(stack);
//省略...
for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {//迭代合法参数
String name = entry.getKey();//参数名
Object value = entry.getValue();//参数值
try {
newStack.setValue(name, value);//将该参数设置到ValueStack中
} catch (RuntimeException e) {
//省略...
}
}
//省略...
//看该方法的名称是将合法参数添加到ActionContext中,但在该拦截器中,该方法为空实现,无任何代码
//该方法被声明为protected,即子类可以覆盖该方法以改变行为
addParametersToContext(ActionContext.getContext(), acceptableParameters);
}
根据上面的注释大家应该可以发现该setParameters方法逻辑还是很明确的,就是先判断提交过来的参数是否合法,因为提交过来的参数会影响到值栈所以struts2要对提交过来的参数进行合法性检查,以防止恶意用户的攻击,凡是请求参数中表达式中含有等号(=),逗号(,),#号(#)的都是非法表达式,现在就去看一下具体是如何判断一个参数是否合法的。上面注释也讲到了,如果Action实现了ParameterNameAware,即要判断ParameterNameAware接口中声明的acceptableParameterName(name)方法(逻辑由自己实现)也要判断该拦截器的acceptableName(name)方法,我们这里假设Action没有实现ParameterNameAware接口,参数是否合法由acceptableName(name)方法决定,下面是该方法源码:
protected boolean acceptableName(String name) {
//调用isAccepted与isExcluded方法判断
if (isAccepted(name) && !isExcluded(name)) {
return true;
}
return false;
}
isAccepted与isExcluded方法源码:
protected boolean isAccepted(String paramName) {
if (!this.acceptParams.isEmpty()) {
for (Pattern pattern : acceptParams) {
Matcher matcher = pattern.matcher(paramName);
if (matcher.matches()) {
return true;
}
}
return false;
} else
return acceptedPattern.matcher(paramName).matches();
} protected boolean isExcluded(String paramName) {
if (!this.excludeParams.isEmpty()) {
for (Pattern pattern : excludeParams) {
Matcher matcher = pattern.matcher(paramName);
if (matcher.matches()) {
return true;
}
}
}
return false;
}
上面说到了该拦截器配置了参数过滤,配置了一个名为excludeParams的参数,用于指定哪些参数要排除,即不合法,我们传递的时候是字符串在设置该字符串的时候该拦截器会对该字符串进行解析转化成相应的Pattern对象以用于正则表达式校验,而isAccepted与isExcluded方法中就是在用这些正则表达式进行检验,逻辑很简单,就说这么多。
最终进行参数赋值是调用的ValueStack的setValue方法,该方法内部使用是OGNL表达式引擎进行赋值的,虽然内部非常复杂,但我们只需要知道OGNL表达式引擎在把请求参数设置到ValueStack中时,是从栈顶往栈底寻找有相应setter方法的对象,如果正在赋值的参数在ValueStack找到了一个对象有setter方法则把该参数的值赋给该对象,如果没有找到则继承往栈底寻找,直到找到为止,如果找到栈底还是没有找到也就没有赋值成功。
到此该拦截器就讲解完毕了,最后调用invocation.invoke();调用下一个拦截器......
Struts2 源码分析-----拦截器源码解析 --- ParametersInterceptor的更多相关文章
- Spring AOP 源码分析 - 拦截器链的执行过程
1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...
- Struts2 源码分析——拦截器的机制
本章简言 上一章讲到关于action代理类的工作.即是如何去找对应的action配置信息,并执行action类的实例.而这一章笔者将讲到在执行action需要用到的拦截器.为什么要讲拦截器呢?可以这样 ...
- springMVC源码分析--拦截器HandlerExecutionChain(三)
上一篇博客springMVC源码分析--HandlerInterceptor拦截器调用过程(二)中我们介绍了HandlerInterceptor的执行调用地方,最终HandlerInterceptor ...
- Nacos 2.0源码分析-拦截器机制
温馨提示: 本文内容基于个人学习Nacos 2.0.1版本代码总结而来,因个人理解差异,不保证完全正确.如有理解错误之处欢迎各位拍砖指正,相互学习:转载请注明出处. Nacos服务端在处理健康检查和心 ...
- struts2拦截器源码分析
前面博客我们介绍了开发struts2应用程序的基本流程(开发一个struts2的实例),通过前面我们知道了struts2实现请求转发和配置文件加载都是拦截器进行的操作,这也就是为什么我们要在web.x ...
- Jfinal拦截器源码解读
本文对Jfinal拦截器源码做以下分析说明
- 0002 - Spring MVC 拦截器源码简析:拦截器加载与执行
1.概述 Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理.例如通过拦截器可以进行权限验证.记录请求信息的日 ...
- 5.2 spring5源码--spring AOP源码分析三---切面源码分析
一. AOP切面源码分析 源码分析分为三部分 1. 解析切面 2. 创建动态代理 3. 调用 源码的入口 源码分析的入口, 从注解开始: 组件的入口是一个注解, 比如启用AOP的注解@EnableAs ...
- drf的基本使用、APIView源码分析和CBV源码拓展
cbv源码拓展 扩展,如果我在Book视图类中重写dispatch方法 -可以实现,在get,post方法执行之前或者之后执行代码,完成类似装饰器的效果 def dispatch(self, requ ...
随机推荐
- pugixml 1.9 manual解读(部分)
Plain character data nodes (node_pcdata) represent plain text in XML. PCDATA nodes have a value, but ...
- 爬虫第一篇:爬虫详解之urllib.request模块
我将urllib.request 的GET请求和POST请求两种方法做了总结 GET请求 GET请求爬取: import urllib.request import urllib.parse head ...
- NodeJS Cross domain
跨域问题主要在header上下功夫 首先提供一个w3c的header定义 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 再提供一个网友提 ...
- JavaScript秘密
对象 对象使用和属性 JavaScript 中所有变量都可以当作对象使用,除了两个例外 null 和 undefined. false.toString(); // 'false' [1, 2, 3] ...
- 分享知识-快乐自己:Liunx 安装MySQL
第一步: 1):下载mysql安装包:这里选择下载版本 5.6.33,通用版,linux下64位 http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql- ...
- Python3之hashlib模块
Python3之hashlib 简介: 用于加密相关的操作,代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法.在python3中已 ...
- 一個在WCF學習中的小教訓(本人非科班菜鳥,此經驗無參考價值,衹是自己的經驗記錄)
1.关于“ServiceHost 仅支持类服务类型”的解决: Service属性必须执行,不是接口. 改为下图所示: 解决! (注:按朱哥的方法WCF已经可以通信---截至今天的11:11(例子在 ...
- OpenCV——黑白调整
参考算法: 闲人阿发伯的博客 // define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUD ...
- FEC之我见二
前面简单说了一下FEC,以及它的配合使用的方法.下面我想详细说一下FEC算法: 曾经有位大神在帖子里这么写着:采用改进型的vandermonde矩阵RS算法.其优点算法运算复杂度更低且解决了利用矩阵构 ...
- uoj problem 10
uoj problem 10 题目大意: 给定任务若干,每个任务在\(t_i\)收到,需要\(s_i\)秒去完成,优先级为\(p_i\) 你采用如下策略: 每一秒开始时,先收到所有在该秒出现的任务,然 ...