Filter
1. 过滤器简介
1. 过滤器是Java Web三大组件之一,它在很多方面都与Servlet相似
2. 过滤器可以理解成拦截器,其实过滤器的代码是环绕在被访问资源的前后,为被访问的资源提供增强的作用(比如过滤器就像楼层中保安,所有人员经过楼层必须经过保安)
3. 过滤器的应用场景:
1). 执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作
2). 通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用
3). 在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理
2. 过滤器编写步骤
1. 编写一个类实现javax.servlet.Filter接口。在doFilter方法中编写过滤代码
2. 在web.xml中配置哪些资源要经过该过滤器
<filter>
<filter-name>命名</filter-name>
<filter-class>包名.类名</filter-class>
</filter>
<filter-mapping>
<filter-name>命名</filter-name>
<url-pattern>拦截的资源</url-pattern>
</filter-mapping>
一个目标资源可以指定多个过滤器,过滤器的执行顺序是在web.xml文件中的</filter-mapping>部署顺序
3. 过滤器的执行过程和生命周期
1、过滤器是在应用启动时就完成了实例化和初始化
2、对于过滤范围内资源的每次访问都会调用doFilter
3、应用被卸载时会调用destory方法
4. FilterConfig&FilterChain
ServletConfig
ServletContext getServletContext():获取ServletContext的方法;
String getFilterName():获取Filter的配置名称;与<filter-name>元素对应;
String getInitParameter(String name):获取Filter的初始化配置,与<init-param>元素对应;
Enumeration getInitParameterNames():获取所有初始化参数的名称
FilterChain
doFilter()方法的参数中有一个类型为FilterChain的参数,它只有一个方法:doFilter(ServletRequest,ServletResponse)
区别:
1.个数不同
Filter接口doFilter是3个参数: ServletRequest,ServletResponse,FilterChain
FilterChian的doFilter是2个参数: ServletRequest,ServletResponse
2.作用不同
Filter接口doFilter拦截作用
FilterChian中doFilter起放行作用
5. 过滤器其他配置
过滤四个类型:REQUEST FORWARD INCLUDE ERROR
<filter-mapping>
<filter-name>Filter06_Typetest</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher> <!-- 默认REQUEST,如果配置了其他类型,默认的就没有了 -->
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
6. 巩固包装设计模式
1、装饰模式口诀
a、定义一个类实现与被包装类相同的接口
b、定义一个变量记住被包装类对象的引用
c、定义构造方法,传入被包装类对象的实例
d、对于要改写的方法,改写即可
e、对于不需要改写的方法,调用被包装对象的对应方法
2、装饰模式变化
改写的方法所在的类,本身就是个包装类
a、定义一个类,继承要包装的类
b、定义一个变量,记住被包装类的引用
c、定义构造方法,传入被包装类的实例
d、覆盖要改写的方法
过滤器的案例
1. 过滤器简单案例(编码/静态和动态缓存控制)
1. 过滤器中实现设置编码
强转request和response
强转request和response、初始化容器时赋值config属性
String encoding = config.getInitParameter("encoding");
request.setCharacterEncoding(encoding);
response.setContentType("text/html;charset="+encoding);
chain.doFilter(request, response);
2. 全站动态资源无缓存
强转request和response
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("pragma", "no-cache");
chain.doFilter(request, response);
3. 静态资源设置缓存时间
强转request和response
String uri = request.getRequestURI();
String extendsionName = uri.substring(uri.lastIndexOf(".")+1);
String time = "0";
time = config.getInitParameter(extendsionName);
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
if(time != null) {
response.setDateHeader("Expires", System.currentTimeMillis()+Integer.parseInt(time)*60*60*1000);
}
chain.doFilter(request, response);
最后勿忘配置web.xml文件
2. 用户自动登录
用户自动登录案例
1. 新建数据库中的表和对应的JavaBean对象
create database day19;
use day19;
create table user(
id int primary key,
username varchar(100) not null unique,
password varchar(100) not null
);
private int id;
private String username;
private String password;
2. 数据访问层UserDaoImpl类
void save(User user)
User find(String username, String password)
3. 工具类
引入DBUtils/C3P0Util/EncodingUtil工具类
4. 业务逻辑层BusinessServiceImpl类
public void register(User user)
public User findUser(String username, String password)
5. LoginServlet类
过滤器解决乱码问题
5.1 获取请求参数
5.2 调用业务逻辑判断是否登录成功
5.3 将用户名和密码设置在cookie信息中Cookie c = new Cookie("loginInfo",loginInfo);
5.4 判断用户选择的方式,设置相应的有效期
5.5 设置cookie路径
5.6 将cookie添加到响应头中
5.7 重定向到首页
6. LogoutServlet类
6.1 移除session域中的user
6.2 新建空的cookie信息,设置cookie的有效期为过期0,设置cookie路径,添加到response头信息中
6.3 重定向到首页
7. 过滤器类,处理编码
7.1 获取初始化的参数
7.2 设置编码之后再放行
8. 自动登录过滤器类AutoLoginFilter
8.1 强制request,response
8.2 获取请求的uri信息
8.3 如果请求的参数不是以login.jsp登录
8.4 获取session域中的user
8.5 如果user为空
8.6 获取请求的cookie信息
8.7 如果获取的cookie为空重定向登录页面
8.8 遍历所有cookie,如果为是用户的cookie就赋值为新cookie,break;
8.9 如果赋值的新cookie不为空,获取cookie中的值
8.10 切割value获取username和password中的值
8.11 解码用户名,调用业务逻辑层方法判断用户名和密码
8.12 如果获得的用户名不为空,将用户设置到session域中
8.13 chain放行
页面设计
1. login.jsp 用户登录页面提供选择有效期,提交到LoginServlet类
2. top.jsp 头部,如果session域中的用户为空,提示登录,如果不为空,提示欢迎界面,提供注销功能
3. index.jsp 引入top.jsp,提供帖子链接
4. 1.jsp 帖子链接
3. 过滤器拓展案例(全站编码/敏感词汇/html标签过滤)
1. 全站编码问题
1). 强转request/response
2). 设置编码为了解决post编码问题
3). 若解决get提交编码问题,在doFilter放行之前包装一下request对象
4). 定义MyHttpServletRequest继承HttpServletRequestWrapper
5). 重写getParameter方法
super.getParameter(name);接收用户请求的的参数的值
如果为空直接返回null
判断请求的方式super.getMethod(),如果get请求,将请求的值编码再解码
2. 敏感词汇过滤
1). 强转request/response
2). 在doFilter放行之前包装一下request对象
3). 定义MyHttpServletRequest继承HttpServletRequestWrapper
4). 定义词库词汇
5). 获取请求参数的值,如果为空,直接返回空
6). 遍历词库,替换请求参数的值
7). 最后返回请求参数的值
3. HTML标签过滤
1). 强转request/response
2). 在doFilter放行之前包装一下request对象
3). 定义MyHtmlServletRequest继承HttpServletRequestWrapper
4). 调用filter方法替换请求参数的值
5). filter方法在tomcatwebappsexamplesWEB-INFclassesutilHTMLFilter.java
4. 全站压缩
1. 建立GZIP压缩过滤类GzipFilter
2. 在放行之前改写response,然后把改写之后的response传给doFilter
3. 针对HttpServletResponseWrapper,改写类为MyHttpServletResponse,重写其中的getOutputStream和getWriter方法
3.1 定义临时容器
3.2 定义获取临时容器的数据getBufferByte()
6. 针对临时容器,实现HttpServletResponseWrapper,提供write方法将数据写到临时容器中