<basic>-提供基础特性
1.拦截器接口
BasicRequestContext提供了一组interceptors拦截器接口,通过它们,你可以拦截并干预一些事件。
拦截器接口 | 说明 |
RequestContextLifecycleInterceptor | 拦截“预处理(prepare)”和“提交(commit)”事件 |
ResponseHeaderInterceptor | 拦截所有对response header的修改。 |
HeaderNameInterceptor | 拦截所有对header的修改、添加操作。可修改header name,或拒绝对header的修改。 |
HeaderValueInterceptor | 拦截所有对header的修改、添加操作。可修改header value或拒绝对header的修改。 |
CookieInterceptor | 拦截所有对cookie的添加操作。可修改或拒绝cookie对象。需要注意的是,有两种方法可以添加cookie:通过cookie对象,或者直接写response header。对于后者,需要使用cookieHeaderValueInterceptor才能拦截得到。 |
CookeiHeaderValueInterceptor | 拦截所有通过添加Headder来创建cookie的操作。可修改或拒绝该cookie。 |
RedirectLocationInterceptor | 拦截所有外部重定向操作。可修改或拒绝重定向URL。 |
StatusMessageInterceptor | 拦截所有设置status message的操作。可以修改或拒绝该message. |
通过下面的配置,就可以指定多个interceptor的实现。
<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts">
<basic>
<request-contexts:interceptors
xmlns="http://www.alibaba.com/schema/services/request-contexts/basic/interceptors">
<interceptor class="...Interceptor1" />
<interceptor class="...Interceptor2" />
</request-contexts:interceptors>
</basic>
...
</services:request-contexts>
2.默认拦截器
BasicRequestContext总是会启用一个默认的interceptor实现:ResponseHeaderSecurityFilter。
<set-locale>-设置locale区域和charset字符集编码
1.Local基础
一个locale的格式是:language_country_variant。Java和框架根据不同的locale,可以取得不同的文本、对象。
2.Charset编码基础
charset是将字符转换成字节或者将字节转换为字符的算法。Java内部采用unicode来表示一个字符。浏览器发送给WEB应用的request参数,是以字节流的方式来表示的。Request参数必须经过解码才能被Java程序所解读。用来解码request参数的charset被称为"输入字符集编码"。
web应用返回给浏览器的response响应内容必须编码成字节流,才能被浏览器或客户端解读。用来编码response内容的charset被称为“输出字符集编码”。
3.Locale和charset的关系
charset必须能够涵盖Locale所代表的语言文字,如果不能,则可能出现乱码。
4.设置locale和charset
getCharacterEncoding() | 读取输入编码 | |
setCharacterEncoding(charset) | 设置输入编码 |
|
getLocale() | 取得Accept-Language中浏览器首先项的locale | |
getLocales() | 取得Accept-Language中所指定的locales |
getCharacterEncoding() | 取得输出编码 | |
setCharacterEncodig(charset) | 设置输出编码 | |
getContentType() | 取得contentType | |
setContentType() | 设置contentType | content type中可能包含charset定义 |
getLocale() | 取得locale | |
setLocale(locale) | 设置输出locale |
|
<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts">
<set-locale defaultLocale="zh_CN" defaultCharset="GB18030" />
...
</services:request-contexts>
上面的配置,将web应用的输入charset、输出charset均设置成GB18030,将输出locale设置成zh_CN。
(1)临时覆盖默认的charset
http://localhost:8081/myapp/myform?_input_charset=UTF-8
这样,webx将采用utf-8来解码参数,但仍然使用默认的GB18030来输出页面。必须把_input_charset这个特殊的参数写在URL中。
(2)持久覆盖默认的locale和charset
http://localhost:8081/myapp?_lang=zh_CN:UTF-8
参数值_lang=zh_CN:UTF-8将被保存在session中,后续的请求不需要再次指定_lang参数,用户所作出的选择将一直持续在整个session中,直到session被作废。需要说明的是,假如我们采用了<session>request context来取代原来的session机制,那么该参数实际的保存位置将取决于session框架的设置。
(3)<set-locale>
<set-locale>所设置的输出locale和输出charset值将会保存在当前线程中,从而对整个线程产生影响。、
- LocaleUtil.getContext().getLocale()和LocaleUtil.getContext().getCharset():可以通过这两个方法取得当前线程的输出locale和charset。webx框架凡是要用默认locale和charset的地方,都会从这里去取值。
- StringEscapeUtil.escapeURL和StringEscapeUtil.unescapeURL:webx调用这两个方法进行URL编码、解码时,不需要指定charset。这两个函数将从LocaleUtil.getContext().getCharset()中取得当前的线程的输出charset。
- TemplateService:如果指定了searchLocalizedTemplates=true参数,那么它会利用当前线程的Locale来搜索本地化的模板。例如:screen/myTemplate_zh_CN.vm。
(4)<set-locale>的配置参数
<set-locale defaultLocale="..."
defaultCharset="..."
inputCharsetParam="_input_charset"
outputCharsetParam="_output_charset"
paramKey="_lang"
sessionKey="_lang" />
- inputCharsetParam:用来临时改变输入charset的参数名,支持多个名称,以“|”分隔。
- paramKey:用来持久改变输出locale和charset的参数,默认为"_lang"。
- sessionKey:用来在session中保存用户所选择的locale和charset的key,默认为"_lang"。
<parset>-解析参数
<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts">
<parser />
...
</services:request-contexts>
<services:upload sizeMax="5M" fileSizeMax="2M" />
绝大多数情况下,<parser>会自动解析所有类型的请求,包括:
- GET请求
- 普通的POST请求(Content Type: appllication/x-www-form-urlencoded)
- 可上传文件的POST请求(Content Type:multipart/form-data)
可以通过HttpServletRequest接口访问参数,也可以通过ParserRequestContext接口访问参数。
@Autowired
ParserRequestContext parser;
...
String s = parser.getParameters().getString("myparam");
和HttpServletRequest接口相比,ParserRequestContext提供了可直接取得指定类型参数的便利。
parser.getParameters().getBoolean("myparam", false);
parser.getParameters().getString("myparam", "no_value");
parser.getParameters().getInt("myparam", -1);
FileItem fileItem = parser.getParameters().getFileItem("myfile");
FileItem[] fileItems = parser.getParameters().getFileItems("myfile");
parser.getCookies().getString("mycookie");
1.上传文件
不是只有需要上传文件时,才可以用multipart/form-data表单,假如你的表单中包含富文字段(即字段的内容是以HTML或类似的技术描述的),特别昌当字段的内容比较长的时候,用multipart/form-data比用普通的表单更高效,生成的HTTP请求也更短。
Upload服务扩展于Apache Jakarta的一个项目:commons-fileupload。
<services:upload sizeMax="5M"
fileSizeMax="2M"
repository="/tmp"
sizeThreshold="10K"
keepFormFieldInMemory="true" />
- sizeMax:Http请求的最大尺寸(支持K/M/G),超过此尺寸的请求将被抛弃。值-1表示没有限制。
- fileSizeMax:单个文件支持允许的最大尺寸。
- 暂存上传文件的目录。这个目录是用Spring ResourceLoader装载的,而不是一个物理路径 。
- 将文件放在内存中的阈值,小于此值的文件被保存在内存中。
- keepFormFieldInMemory:是否将普通的form field保存在内存里,默认为false,但当sizeThreshold为0时,默认为true。
2.解析GET请求的参数
尽管<set-locale>会调用request.setCharacterEncoding(charset)这个方法来设置input charset编码,然而根据Servlet的规范,这个设定只能参request content生效,换句话说,request.setCharacterEncoding只能用来解析POST请求的参数,而不是GET请求的参数。
服务器 | 解码的逻辑 |
Tomcat5以上及搭载Tomcat5以上的JBoss |
|
Jetty Server | 总是以UTF-8来解码GET请求的参数。 |
依据默认值,<parser>会以<set-locale>中设定的input charset为准,来解码所有类型的请求。
3.过滤参数
<parser>
<filters>
<parser-filters:uploaded-file-whitelist extensions="jpg, gif, png" />
</filters>
</parser>
出于安全的考虑,<parser>还支持对输入参数进行过滤。上面的配置将会禁止文件名后缀不在列表中的文件被上传到服务器上。
<buffered>-缓存response中的内容
<buffered>改变了response的输出流,包括output stream(二进制流)和writer(文本流),使写到输出流中的内容被暂存在内存中。
1.使用方法
<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts">
<buffered />
...
</services:request-contexts>
@Autowired
BufferedRequestContext buffered;
@Autowired
HttpServletResponse response;
...
PrintWriter out = response.getWriter();
buffered.pushBuffer(); // 创建新buffer,并压入栈顶
out.print("world"); // 在新buffer中写入
String content = buffered.popCharBuffer(); // 弹出顶层buffer
out.print("hello, ");
out.print(content); // 写入较低层的buffer
- 假如你的应用使用了response.getWriter(),那么,你必须使用buffered.popCharBuffer()以取得文本buffer的内容。
- 假如你的应用使用了response.getOutputStream(),那么,你必须使用buffered.popByteBuffer()以取得二进制buffer的内容。
setBuffering(false)可以关闭buffer机制。
<lazy-commit>-延迟提交response
在Servlet中,有下列操作可能导制response被提交:
- response.sendError()
- response.sendRedirect()
- response.flushBuffer()
- response.setContentLength()或者response.setHeader("Content-Length",length)
- response输出流被写入并达到内部buffer的最大值。
<lazy-commit>必须和<buffered>配合,才能完全实现延迟提交。
<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts">
<lazy-commit />
...
</services:request-contexts>
<rewrite>-重定请求的URL和参数
它可以根据规则,在运行进修改URL和参数。
<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts">
<rewrite>
<!-- rule 1 -->
<rule pattern="...">
<condition test="..." pattern="..." flags="..." />
<condition test="..." pattern="..." flags="..." />
<substitution uri="..." flags="...">
<parameter key="..." value="..." />
<parameter key="..." value="..." />
<parameter key="..." value="..." />
</substitution>
<handlers>
<rewrite-handlers:handler class="..." />
</handlers>
</rule>
<!-- rule 2 -->
<rule pattern="...">
</rule>
<!-- rule 3 -->
<rule pattern="...">
</rule>
</rewrite>
...
</services:request-contexts>
1.取得路径
一个完整的URL路径是由contextPath+servletPath+pathInfo三部分组成的,其中contextPath是用来区分应用的,所以用来匹配rules的路径并不是URL的整个路径,而是由servletPath+pathInfo两部分组成。
2.重定向
- 永久重定向
<rule pattern="^/hello1\.htm">
<substitution uri="/new_hello.htm" flags="L,R=301" />
</rule>
- 临时重定向,不保留参数
<rule pattern="^/hello2\.htm">
<substitution uri="/new_hello.htm" flags="L,R" />
</rule>
- 临时重定向,保留参数
<rule pattern="^/hello3\.htm">
<substitution uri="/new_hello.htm" flags="L,R,QSA" />
</rule>
- 绝对URL重定向
<rule pattern="^/hello4\.htm">
<substitution uri="http://www.other-site.com/new_hello.htm" flags="L,R" />
</rule>
最后欢迎大家访问我的个人网站:1024s