javaweb 中的过滤器 包装器
过滤器要做的事情:
请求过滤器:完毕安全检查,又一次格式化请求首部或体。建立请求审计或日志
响应过滤器:
压缩响应流,追加或改动响应流创建一个全然不同的响应.
过滤器和servlet三个相似地方:
1.容器知道过滤器的api,过滤器api的其他成员能够訪问ServletContext 还能够与其他过滤器链接
2.容器管理过滤器的生命周期,过滤器有init和destroy方法。还有doFilter方法
3.web应用能够有非常多过滤器。须要在配置文件里配置
过滤器的生命周期
init 容器实例化一个过滤器时。在init方法中完毕调用过滤器之前全部的初始化任务。
保存filterConfig对象
的一个引用,以备过滤去以后使用.
其次调用 doFIlter 能够保存username记录到一个文件里,压缩响应输出。
最后destroy删除一个过滤器实例,
FilterChain的doFIlter 方法要负责明白接下来调用谁的doFilter放大,假设到达链尾,则要确定调用哪个servlet的service方法。
在配置文件里确定过滤器的顺序
在配置文件里做三件事
1.声明过滤器
2.将过滤器映射到你想过滤的web资源
3,组织这些映射,创建过滤器调用序列
声明过滤器
<filter>
<filter-name>BeerRequest</filter-name>
<filter-class>com.gac.test.BeerRequestFilter</filter-class>
<init-param>
<param-name>LogFileName</param-name>
<param-value>UserLog.txt</param-value>
</init-param>
</filter>
声明url模式的过滤器映射
<filter-mapping>
<filter-name>BeerRequest</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
声明相应servlet名的过滤器映射
<filter-mapping>
<filter-name>BeerRequest</filter-name>
<servlet-name>AdviceServlet</servlet-name>
</filter-mapping>
为通过请求分派请求的web资源声明一个过滤器映射
<filter-mapping>
<filter-name>MonitorFilter</filter-name>
<url-pattern>*.do</url-pattern>
<dispatcher>REQUEST</dispatcher>
和/或
<dispatcher>INCLUDE</dispatcher>
和/或
<dispatcher>FORWARD</dispatcher>
和/或
<dispatcher>ERRO</dispatcher>
</filter-mapping>
声明规则:
必需要有filter-name
必需要有url-pattern或servlet-name元素当中之中的一个
能够有0-4个dispatcher
Request值表示对client请求启用过滤器,假设没有指定<dispatcher>元素。则默觉得
Rquest
INCLUDE值表示对由一个include()调用分派来的请求启用过滤器
FORWARD值表示对一个由forward()调用分派来的请求启用过滤器
ERROR值表示对错误处理调用资源启用过滤器
过滤器请求路径样例
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/Recipes/*<url-pattern> /Recipes/HopsReport.do 过滤器序列 1 5
</filter-mapping> /Recipes/HopsList.do 过滤器 15 2
<filter-mapping>
<filter-name>Filter2</filter-name> /Recipes/Modify/ModRecipes.do 过滤器 1 5 4
<url-pattern>/Recipes/HopsList.do<url-pattern> /HopsList.do 过滤器 5
</filter-mapping>
<filter-mapping> /Recipes/Add/AddRecipes.do 过滤器 1 3 5
<filter-name>Filter3</filter-name>
<url-pattern>/Recipes/Add/*<url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Filter4</filter-name>
<url-pattern>/Recipes/Modify/ModRecipes.do<url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Filter5</filter-name>
<url-pattern>/*<url-pattern>
</filter-mapping>
/**************************************************************/
//过滤器必须实现Filter接口
public class BeerRequestFilter implements Filter{
private FilterConfig fc;
//完毕清理工作
@Override
public void destroy() {
// TODO Auto-generated method stub
}
//详细的业务逻辑
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest httpReq = (HttpServletRequest) req;//能够将请求和响应对象强制转换为Http类型
String name = httpReq.getRemoteUser();
if(name != null){
fc.getServletContext().log("User"+name +"is updating");
}
chain.doFilter(req, resp);//接下来要调用的过滤器或者servlet
}
//必须实现init 通常只在当中保存配置config对象
@Override
public void init(FilterConfig config) throws ServletException {
// TODO Auto-generated method stub
this.fc = config;
}
}
/***************************************************************/
为过滤器压缩数据响应为了不实现太多的函数降低复杂性能够利用包装器。
利用包装器的演示样例
public class CompressFilter implements Filter{
private ServletContext ctx;
private FilterConfig cfg;
@Override
public void destroy() {
// TODO Auto-generated method stub
cfg = null;
ctx = null;
}
//这个过滤器核心是用装饰包装响应对象,他用一个压缩的IO流包装输出流.
//当且仅当客户包括一个Accept-Encoding首部 才会完毕输出流压缩
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp =(HttpServletResponse) response;
String valid_encodings = req.getHeader("Accept-Encoding");//客户是否接收gzip压缩
if( valid_encodings.indexOf("gzip") > -1 ){
ComPressResponseWrapper wrappedResp = new ComPressResponseWrapper(resp);
wrappedResp.setHeader("Content-Encoding","gzip");
chain.doFilter(req, wrappedResp);
GZIPOutputStream gzos = wrappedResp.getGZIPOutputStream();
gzos.finish();
ctx.log(cfg.getFilterName()+": finished the request. ");
}else{
ctx.log(cfg.getFilterName()+": no encoding performed.");
}
}
//init方法保存配置对象,并保存servlet上下文对象的一个直接引用 以便完毕日志记录
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
this.cfg = filterConfig;
ctx = cfg.getServletContext();
ctx.log(cfg.getFilterName()+" initialized.");
}
}
public class ComPressResponseWrapper extends HttpServletResponseWrapper{
private GZIPServletOutputStream servletGzipOS = null;//servlet响应的压缩输出流
private PrintWriter pw = null;
public ComPressResponseWrapper(HttpServletResponse response) {
super(response);
// TODO Auto-generated constructor stub
}
public void setContentLength(int len){}
/*过滤器使用这个装饰器的方法压缩过滤器提供一个GZIP输出流的句柄,以便过滤器完毕和刷新输出GZIP流*/
public GZIPOutputStream getGZIPOutputStream(){
return this.servletGzipOS.internalGzipOS;
}
private Object streamUsed = null;//同意訪问所装饰的servlet输出流
public ServletOutputStream getOutputStream()throws IOException{
//仅当servlet还没有訪问打印书写器时 同意servlet訪问servlet输出流
if((null != streamUsed) && (streamUsed!=pw)){
throw new IllegalStateException();
}
//用我们的压缩输出流包装原来的servlet输出流
if(servletGzipOS == null){
servletGzipOS =
new GZIPServletOutputStream(getResponse().getOutputStream());
streamUsed = servletGzipOS;
}
return servletGzipOS;
}
//执行訪问所装饰的打印书写器
public PrintWriter getWriter() throws IOException{
if((streamUsed != null) && (streamUsed != servletGzipOS)){
throw new IllegalStateException();
}
if(pw == null){
servletGzipOS =
new GZIPServletOutputStream(getResponse().getOutputStream());
OutputStreamWriter osw =
new OutputStreamWriter(servletGzipOS,getResponse().getCharacterEncoding());
pw = new PrintWriter(osw);
streamUsed = pw;
}
return pw;
}
}
class GZIPServletOutputStream extends ServletOutputStream{
/*internalGzipOs保存对原始Gzip流的一个引用。这个实例变量在包范围内私有,所以响应包装器能够訪问这个变量*/
GZIPOutputStream internalGzipOS;
//装饰器构造函数
GZIPServletOutputStream(ServletOutputStream sos) throws IOException{
this.internalGzipOS = new GZIPOutputStream(sos);
}
//这种方法把write调用托付给GZIP压缩流 从而实现压缩装饰 GZIP压缩流包装了原来的ServletOutputStream
@Override
public void write(int b) throws IOException {
// TODO Auto-generated method stub
internalGzipOS.write(b);
}
}
javaweb 中的过滤器 包装器的更多相关文章
- JavaWeb中监听器+过滤器+拦截器区别、配置和实际应用
JavaWeb中监听器+过滤器+拦截器区别.配置和实际应用 1.前沿上一篇文章提到在web.xml中各个元素的执行顺序是这样的,context-param-->listener-->fil ...
- asp.net core 2.2 中的过滤器/筛选器(上)
ASP.NET Core中的过滤器/筛选器 通过使用 ASP.NET Core MVC 中的筛选器,可在请求处理管道中的特定阶段之前或之后运行代码. 注意:本主题不适用于 Razor 页面. ASP. ...
- MVC中的过滤器/拦截器怎么写
创建一个AuthenticateFilterAttribute(即过滤器/拦截器) 引用System.Web.Mvc; public class AuthenticateFilterAttribute ...
- 【Head First Servlets and JSP】笔记 28: 过滤器与包装器
1.过滤器的执行顺序: <url-pattern> 为第一梯队, <servlet-name> 为第二梯队,梯队内的执行顺序和 DD 里的声明顺序相同. When the co ...
- Java中基本数据类型和包装器类型的关系
在程序设计中经常用到一系列的数据类型,在Java中也一样包含八中数据类型,这八种数据类型又各自对应一种包装器类型.如下表: 基本类型 包装器类型 boolean Boolean char Charac ...
- springboot中使用过滤器、拦截器、监听器
监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ...
- SwiftUI 中一些和响应式状态有关的属性包装器的用途
SwiftUI 借鉴了 React 等 UI 框架的概念,通过 state 的变化,对 View 进行响应式的渲染.主要通过 @State, @StateObject, @ObservedObject ...
- JavaWeb chapter 8 过滤器
1. 一个中间组件,用于拦截源数据和目的数据之间的消息,过滤二者之间传递的数据: 2. Servlet过滤器是驻留在Web服务器上的Web组件,过滤从客户端传递到服务器端的请求和相应. 3. 多 ...
- JavaWeb之Filter过滤器
原本计划这一篇来总结JSP,由于JSP的内容比较多,又想着晚上跑跑步减减肥,所以今天先介绍Filter以及它的使用举例,这样的话还有些时间可以锻炼锻炼.言归正传,过滤器从字面理解她的话有拦网.过滤的功 ...
随机推荐
- sram bist scripts
主要三个script: mbist_run: call mbistarchitect tool run.do:run bist flow bist setup => bist mode(bis ...
- CM3中数据传输对齐/非对齐方式
在CM3中,非对齐的数据传输只发生在常规的数据传送指令中,如LDR.LDRH.LDRSH.其他指令则不支持,包括: 1.多个数据的加载.存储(LDM/STM). 2.堆栈操作PUSH.POP. 3.互 ...
- perl学习之裸字
use strict包含3个部分.其中之一(use strict "subs")负责禁止乱用的裸字. 这是什么意思呢? 如果没有这个限制,下面的代码也可以打印出"hell ...
- Web框架之Django_05 模型层了解(单表查询、多表查询、聚合查询、分组查询)
摘要: 单表查询 多表查询 聚合查询 分组查询 一.Django ORM 常用字段和参数: 常用字段:#AutoFieldint自增列,必须填入参数primary_key = True,当model中 ...
- 我的Python分析成长之路4
一.函数 1.什么是函数?:函数是带名字的代码块,调用函数,只要调用函数名就可以. 2.函数的性质:1.减少重复代码 2.使程序变得可扩展 3.使程序变得易维护 3.编程范示: 1.面向对象编程 ...
- UIBarButtonSystemItem 样式
使用时需要注意创建方式的区别: 01 typedef enum { 02 UIBarButtonSystemItemDone, 03 UIBarButtonSystemItemCanc ...
- 学习javascript中的事件——事件流
事件概念: HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件onclick.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件.想要知道 ...
- python知识点拾遗
内容概要 1.__str__ 2.os.path相关方法 1.__str__ 我们先定义一个Student类,打印一个实例: class Student(object): def __init__(s ...
- 请编写一个方法,返回某集合的所有非空子集。 给定一个int数组A和数组的大小int n,请返回A的所有非空子集。保证A的元素个数小于等于20,且元素互异。各子集内部从大到小排序,子集之间字典逆序排序,见样例。
题解:观察测试样例,会发现每个子集的选择规律与二进制((2^n) - 1)到 1 的顺序生成的规律是一致的,样例中n=3,2^n-1=7,用二进制表示为111,其中每一位的1表示数组中的三个数都选择. ...
- Leetcode 385.字典序排序
字典序排序 给定一个整数 n, 返回从 1 到 n 的字典顺序. 例如, 给定 n =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] . 请尽可能的优化算法的时间复杂度和 ...