Filter
1.工作原理
Request Contexts服务
事实上,你可以把Request Context看作是HttpServletRequest和HttpServletResponse这两个对象总和,除此之外,多个Request Context可以被串起来,被称为Request Context Chain。
Request Context在预处的时候,可以利用HttpServletRequestWrapper和HttpServletResponseWrapper来包装和修改request和response,这一点和filter相同,最先的Request Context成为最内层的包装,最后的Request Context成为最外层的包装。
webx目前提供了以下几种request context的实现
名称 | 功能 |
<basic> | 提供基础安全特性,例如:过滤response headers、cookies,限制cookie的大小等 |
<buffered> | 缓存response中的内容 |
<lazy-commit> | 延迟提交response |
<parser> | 解析参数 |
<rewrite> | 重定请求的URL和参数 |
<session> | 一套可扩展的session框架 |
<set-locale> | 设置Locale区域和charset字符集编码 |
1.使用
<?xml version="1.0" encoding="UTF-8" ?> <beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:services="http://www.alibaba.com/schema/services" xmlns:request-contexts="http://www.alibaba.com/schema/services/request-contexts" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.alibaba.com/schema/services http://localhost:8080/schema/services.xsd http://www.alibaba.com/schema/services/request-contexts http://localhost:8080/schema/services-request-contexts.xsd http://www.springframework.org/schema/beans http://localhost:8080/schema/www.springframework.org/schema/beans/spring-beans.xsd "> ... <services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts"> <basic /> <buffered /> <lazy-commit /> <parser /> <set-locale defaultLocale="zh_CN" defaultCharset="UTF-8" /> <!-- Optional - <session /> <rewrite /> --> </services:request-contexts> <services:upload sizeMax="5M" /> </beans:beans>
2.注入request作用域的对象
对象类型 | 作用域 |
ServletContext | Singleton scope |
HttpServletRequest | Request scope |
HttpServletResponse | Request scope |
HttpSession | Session scope |
所有RequestContext对象,如:ParserRequestContext | Request scope |
在Spring中不能把一个短期对象如request、response和request Context注入到singleton对象,然而在webx中,这样做是可以的,因为Request Context服务对上表所列的短期对象作了特殊的处理,使它们可以被注入到singleton对象中。事实中,被注入的只是一个“空壳”,真正的对象是在被访问到的时候才会从线程中取得。
Pipeline服务
pipeline只能控制流程,不能改变request和response。
1.pipeline的使用
(1)创建一个valve
public class MyValve implements Valve { public void invoke(PipelineContext pipelineContext) throws Exception { System.out.println("valve started."); pipelineContext.invokeNext(); // 调用后序valves System.out.println("valve ended."); } }
pipeline.xml
<services:pipeline xmlns="http://www.alibaba.com/schema/services/pipeline/valves"> ... <valve class="com.alibaba.myapp.pipeline.MyValve" /> ... </services:pipeline>
(2)执行一个pipeline
@Autowired private Pipeline myPipeline; public void invokePipeline() { PipelineInvocationHandle invocation = myPipeline.newInvocation(); invocation.invoke(); System.out.println(invocation.isFinished()); System.out.println(invocation.isBroken()); }
(3)调用子流程
子流程不过是另一个pileline对象而已。
public class MyNestableValve implements Valve { private Pipeline subPipeline; public void setSubPipeline(Pipeline subPipeline) { this.subPipeline = subPipeline; } public void invoke(PipelineContext pipelineContext) throws Exception { // 发起子流程,以当前流程的pipelineContext为参数 PipelineInvocationHandle subInvocation = subPipeline.newInvocation(pipelineContext); subInvocation.invoke(); System.out.println(subInvocation.isFinished()); System.out.println(subInvocation.isBroken()); pipelineContext.invokeNext(); // 别忘了调用后序的valves } }
<services:pipeline xmlns="http://www.alibaba.com/schema/services/pipeline/valves"> ... <valve class="com.alibaba.myapp.pipeline.MyNestableValve" p:subPipeline-ref="subPipeline" /> ... </services:pipeline>
(4)中断一个pipeline
pipelineContext.breakPipeline(0); // level=0,中断当前pipeline pipelineContext.breakPipeline(1); // level=1,中断上一级pipeline pipelineContext.breakPipeline("label"); // 中断到指定label的上级pipeline // 以上调用相当于: pipelineContext.breakPipeline(pipelineContext.findLabel("label")); pipelineContext.breakPipeline(Pipeline.TOP_LABEL); // 终止所有pipelines
(5)存取pipeline的状态
pipelineContext.index(); // 当前valve在pipeline中的序号 pipelineContext.level(); // 当前pipeline在所有子pipeline中的级别 pipelineContext.isBroken(); // 当前pipeline是否已经被中断 pipelineContext.isFinished(); // 当前pipeline的所有valves是否已经执行完 // 存取任意数据 pipelineContext.getAttribute(key); pipelineContext.setAttribute(key,value);
(6)现成可用的valves
- 无条件循环-<loop>
<services:pipeline> <loop loopCounterName="count" maxLoopCount="10"> <valve /> <break-if test="..." /> </loop> </services:pipeline>
循环变量loopCounterName将被保存在pipelineContext中,且可被其它的valve所访问。无条件循环一定要和<break>,<break-if>或<break-unless>等valves相配合。
- 条件循环-<while>
<services:pipeline> <while loopCounterName="count" test="count <= 2"> <valve /> </while> <while maxLoopCount="10"> <conditions:condition class="..." /> <valve /> </while> </services:pipeline>
- 单条件分支-<if>
<services:pipeline> <if test="1 == 2"> <valve /> </if> <if> <conditions:condition class="..." /> <valve /> </if> </services:pipeline>
- 多条件分支-<choose><when><otherwise>
<services:pipeline> <choose> <when test="1 == 2"> <valve /> </when> <when> <conditions:condition class="..." /> <valve /> </when> <otherwise> <valve /> </otherwise> </choose> </services:pipeline>
- 无条件中断-<break>
<services:pipeline> <loop> <valve /> <break /> <valve /> </loop> <loop> <valve /> <loop> <break levels="1" /> </loop> <valve /> </loop> <loop label="MY_LOOP"> <valve /> <loop> <break toLabel="MY_LOOP" /> </loop> <valve /> </loop> </services:pipeline>
- 有条件中断-<break-if> <break-unless>
<services:pipeline> <loop loopCounterName="count"> <valve /> <break-if test="count > 2" /> <valve /> </loop> <loop label="MY_LOOP"> <valve /> <break-if toLabel="MY_LOOP"> <conditions:condition class="..." /> </break-if> <valve /> </loop> <loop loopCounterName="count"> <valve /> <break-unless test="count <= 2" /> <valve /> </loop> </services:pipeline>
- 无条件退出整个pipeline-<exit>
<services:pipeline> <loop> <valve /> <loop> <exit /> </loop> <valve /> </loop> </services:pipeline>
- 异常捕获和finally处理-<try-catch-finally>
<services:pipeline> <try-catch-finally> <try> <valve /> </try> <catch exceptionName="myexception"> <valve /> </catch> <finally> <valve /> </finally> </try-catch-finally> </services:pipeline>
<catch>标签可以将捕获的异常以指定名称保存在pipelineContext中,以便其它valve取得。
- 创建子流程
<services:pipeline> <valve /> <sub-pipeline label="mylabel"> <valve /> </sub-pipeline> <valve /> </services:pipeline>
(7)条件
Condition是一个简单的接口。
public interface Condition { /** * 如满足条件,则返回<code>true</code>。 */ boolean isSatisfied(PipelineStates pipelineStates); }webx默认提供了一个JexlCondition,JEXL表达式是Apache的一个小项目,表达式语法见: http:// commons.apache.org/jexl/reference/syntax.html http:// commons.apache.org/jexl/reference/syntax.html。
另外,webx还提供了三个组合式的条件。
- <all-of>
要求所有条件均满足,相当于Java中的&&操作符。
<all-of> <condition1 /> <condition2 /> <condition3 /> </all-of>
- <any-of>
<any-of> <condition1 /> <condition2 /> <condition3 /> </any-of>
- <none-of>
要求所有条件均不满足。
<none-of> <condition1 /> <condition2 /> <condition3 /> </none-of>