Filter概述
什么是Filter
-
生活中的过滤器
净水器、空气净化器、地铁安检、山大王(土匪)
-
web中的过滤器
当用户访问服务器资源时,过滤器将请求拦截下来,完成一些通用的操作
-
应用场景
登录验证、统一编码处理、敏感字符过滤
- 作用
过滤掉请求的路径
过滤器原理
过滤器的快速入门
实现步骤
步骤:
1. 定义一个类,实现接口Filter,规范.
2. 重写方法
3. 配置拦截路径
1. web.xml
2. 注解
代码实现
package cn.yanqi.web;
import javax.servlet.*;
import java.io.IOException;
/**
* @Auther: yanqi
* @Desc
*/
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("--init--");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//默认不会放行
System.out.println("--doFilter--");
}
@Override
public void destroy() {
System.out.println("--destroy--");
}
}
在web.xml中配置过滤器路径
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>cn.yanqi.web.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<!--指定拦截,如配置hello.html路径,这个就拦截进入过滤器中-->
<!--
<url-pattern>/index.jsp</url-pattern>
<url-pattern>/LoginServlet</url-pattern>
<url-pattern>/hello.html</url-pattern>-->
<!--拦截所在请求路径-->
<!--<url-pattern>/*</url-pattern>-->
</filter-mapping>
过滤的分析
Filter生命周期
-
init
服务器启动项目加载,创建filter对象,执行init方法(只执行一次)
-
doFilter
用户访问被拦截目标资源时,执行doFilter方法,执行多次
-
destroy
在服务器关闭前,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
过滤器一定是优先于Servlet创建的
Filter生命周期:
1、当服务器启动时就初始化,并且只初始化一次
2、每次请求都会走doFilter方法,
3、服务器正常关闭,Filter销毁
Servlet生命周期:
1、用户第一次访问时servlet初始化,并且只初始化一次
2、每次请求都会走service方法,
3、服务器正常关闭,Servlet销毁
servlet的生命周期 , filter过滤器的生命周期, 应用用场景和实现接口不一样
拦截路径
在开发时,我们可以指定过滤器的拦截路径来定义拦截目标资源的范围
-
精准匹配
用户访问指定目标资源(/show.html)时,过滤器进行拦截
-
目录匹配
用户访问指定目录下(/user/*)所有资源时,过滤器进行拦截
/user/cart/*
/user/info/*
-
后缀匹配
用户访问指定后缀名(*.html)的资源时,过滤器进行拦截
/*.html 错误写法
-
匹配所有
用户访问该网站所有资源(/*)时,过滤器进行拦截
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>cn.yanqi.web.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<!--指定拦截-->
<url-pattern>/hello.html</url-pattern>
<url-pattern>/UserServlet</url-pattern>
<url-pattern>/show.html</url-pattern>
<!--匹配后缀-->
<url-pattern>*.html</url-pattern>
<!--拦截所有请求路径-->
<!--<url-pattern>/*</url-pattern>-->
</filter-mapping>
doFilter方法说明
| chain.doFilter(request,response) | 放行 执行后续组件 |
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("======初始化-init=======");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("======doFilter=======");
//获取所有请求路径 /login.html /LoginServlet
HttpServletRequest request = (HttpServletRequest) servletRequest;
String requestURI = request.getRequestURI();
//只放行login.html
if("/login.html".equals(requestURI)){
//放行代码
filterChain.doFilter(servletRequest ,servletResponse);
}
}
@Override
public void destroy() {
System.out.println("======销毁-destroy=======");
}
}
注解方式
/**
* @Auther: yanqi
* @Desc 注释方式
*/
// @WebFilter(urlPatterns = "/hello.jsp")
// @WebFilter(urlPatterns = {"/servletDemo","hello.html"})
// @WebFilter(urlPatterns = "*.html")
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
}
}
编码过滤器
public class EncodingFilter implements Filter {
private String encoding;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
encoding = filterConfig.getInitParameter("encoding");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
request.setCharacterEncoding(encoding);
response.setContentType("text/html;charset=" + encoding);
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
encoding = null;
}
}
web.xml
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>cn.yanqi.web.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
用户访问权限的控制
给用户添加URL访问权限
应用场景:搭建在 用户系统完成之后.
系统中存在很多资源,将需要进行权限控制的资源,放入特殊路径中,编写过滤器管理访问特殊路径的请求,如果没有相应身份和权限,控制无法访问
分析: 首先获取客户端请求的资源地址!
基于CustomerManager 系统添加登陆模块
业务分析
* 1。拦截所有请求路径
* 2。把通用 login.html list.html... 放行
* 3。才能判断用户是否登录
* 4。判断登录的是什么用户
* 5。如果管理员,放行
* 6。如果普通用户,如果请求的是什么,我给放了
* 7。否则不放,告诉用户权限不足
代码实现
修改前面写过的用户管理系统
@WebFilter("/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
String path = req.getRequestURI(); // /login.html /LoginServlet
String requestUri = req.getRequestURI();
if(!("/login2.html".equals(requestUri) || "/loginServlet".equals(requestUri))) {
//过滤没有登录的情况
Object user = req.getSession().getAttribute("user");
if(user == null) { //没有登录
resp.sendRedirect("/login2.html");
return;
}
}
//放行
chain.doFilter(req, resp);
}
@Override
public void destroy() {
}
}
bject user = req.getSession().getAttribute(“user”);
if(user == null) { //没有登录
resp.sendRedirect(“/login2.html”);
return;
}
}
//放行
chain.doFilter(req, resp);
}
@Override
public void destroy() {
}
}