注意!!Filter 是单例模式的!
要实现filter接口,需要在web.xml中配置.他会在一组资源(比如说servlet html css等)前面执行.
他可以让请求得到或者没法得到目标.
过滤器有拦截请求的能力
注意:filter往往是对一组资源进行统一的操作。
三个方法
服务器启动时创建filter对象
init():filter对象创建之后马上执行
destory:销毁之前执行(服务器关闭的时候销毁)
doFilter(ServletRequest,ServletResponse,FilterChain:每次过滤的时候都会执行。
注意:
filter接口的dofilter三个参数
filterchain的dofilter只有两个接口,用来放行
web.xml配置
<filter>
<filter-name></filter-name>
<filter-class>文件所在路径。</filter-class>
</filter>
<filter-mapping>
<filter-name></filter-name>
<url-pattern>(一般都是“/*”)</url-pattern>
<!--这里可以写servlet-name。指定特定的servlet,可以有多个、-->
</filter-mapping>
多过滤器
顺序取决于mapping的配置顺序FilterChain的doFilter方法
->执行资源就是执行下一个过滤器, 如果没有下一个过滤器,则目标执行资源
->执行顺序示例,astart->bstart->资源->bend->aend
过滤器的四种拦截方式
配置:在 <filter-mapping>中配置 <dispatcher>属性- 拦截请求(不写默认是这个)-> request
- 拦截转发 ->forward
- 拦截包含 ->include
- 拦截错误 ->error ->一般可能会额外设置拦截 <err-page>
应用场景
执行目标资源前做的预处理工作,比如说处理编码。
request.setCharacterEncoding();
根据条件进行判断,比如说是否登陆。或者禁用ip。
在目标资源执行后,做一些后续处理工作,例如说把目标数据进行处理,或者回程拦截。
应用案例摘要
1.分ip统计访问次数
1.数据保存在map中,map保存在application中,方便项目各个地方应用
2.map创建时机,用listener在服务器启动的时候创建,并保存在application
3. filter中获取map
可以request.getSession.getServletContext
4.通过init()传的config调用getServletContext,新建一个成员变量,保存起来, 补充:获取ip ->getremoter()
2.粗粒度权限控制
游客,会员,管理员->简单管理权限控制,叫粗粒度,
filter中的参数是servletrequest,先要强转成httpservletrequest
管理员和会员分别存一个session判断登录用户的时候分别判断进行过滤。
3.全站字符乱码问题。
1.注意,要包含get和post两种乱码问题 2.request.setcharacterencoding(“utf-8”)->post 请求编码
3.使用装饰类增强request的getparameter方法->get请求编码
encodingre继承httpservletwrapper,重写getparameter方法、重新设置编码格式。
4.filter创建对象调用。
然后getmethod判断是post还是get然后调用响应的编码代码。
4.页面静态化
什么是页面静态化
首先去数据库访问数据,然后把数据保存在一个html页面上,
二次访问就不用再去获取了,直接显示html。
如果数据会经常更新,那么不适合使用页面静态化。
思路
1.给出一个过滤器,把servlet请求的资源所做的输出保存到一个html文件中,重定向到html文件中
2.再次访问的时候,如果这个html已经存在那么直接重定向。
3.怎么输出到html文件中
掉包response,重写getwriter方法。,在构造方法地方,加一个路径参数,指定html路径
构造方法中创建一个printwriter,参数是path和编码,这样jsp就会用这个流输出数据。都输出到html中了
html乱码解决,在show.jsp增加响应头,Context-Type
代码演示
String category = request.getParameter("category");
String htmlPage = category + ".html";//得到对应的文件名称
String htmlPath = config.getServletContext().getRealPath("/htmls");
//得到文件的存放目录
File destFile = new File(htmlPath, htmlPage);
if(destFile.exists()) {
res.sendRedirect(req.getContextPath() + "/htmls/" + htmlPage);
return;
}
//如果文件存在则直接重定向
StaticResponse sr = new StaticResponse(res, destFile.getAbsolutePath());
//不存在,创建一个重写后的respnse,设定向指定文件写入html
chain.doFilter(request, sr);
//放行,即生成了html文件
res.sendRedirect(req.getContextPath() + "/htmls/" + htmlPage);
public class StaticResponse extends HttpServletResponseWrapper {
private PrintWriter pw;
public StaticResponse(HttpServletResponse response, String path)
throws FileNotFoundException, UnsupportedEncodingException {
super(response);
pw = new PrintWriter(path, "utf-8");
}
public PrintWriter getWriter() {
return pw;
}
}