9. Servlet过滤器(filter)
Filter是拦截Request请求的对象,用于在请求和响应之间执行过滤任务,处于表示层与浏览器之间
创建一个过滤器,需要实现javax.servlet.Filter
接口,并重写其中的方法,包括init()
(初始化过滤器)、doFilter()
(处理请求)和destroy()
(销毁过滤器)
9.1配置Filter
1.确定哪些资源需要使用这个Filter拦截处理
2.实现Filter接口,添加@WebFilter注解配置Filter
(Servlet3.0规范开始,就能用注解配置Filter,不需要在web.xml中配置)
/**
* value:用来指定当前过滤器过滤哪些请求
* /*:所有以项目根路径开头的请求都被当前过滤器过滤
* 其中/代表项目根路径 *表示任意多个字符
*/
@WebFilter(value = "/*")
public class AuthFilter implements Filter {}
9.1.1WebFilter的属性*
属性 | 说明 |
---|---|
filterName | 过滤器的名称,用于在web.xml文件中配置过滤器的映射关系。如果未指定该属性,默认值为过滤器类的简单名称。 |
value | 过滤器的URL模式,用于指定过滤器要过滤的URL路径。可以指定多个URL模式,使用数组形式或逗号分隔的字符串形式。 |
urlPatterns | 过滤器的URL模式,与value 属性作用相同,用于指定过滤器要过滤的URL路径。可以指定多个URL模式,使用数组形式或逗号分隔的字符串形式。 |
servletNames | 过滤器要过滤的Servlet名称,用于指定过滤器要过滤哪些Servlet。可以指定多个Servlet名称,使用数组形式或逗号分隔的字符串形式。 |
dispatcherTypes | 过滤器的调度器类型,用于指定过滤器的调度策略。可以指定多个调度器类型,包括REQUEST 、FORWARD 、INCLUDE 和ERROR 。 |
asyncSupported | 指定是否支持异步请求,默认为false。如果设置为true,表示过滤器支持异步请求处理。 |
initParams | 过滤器的初始化参数,用于设置过滤器的配置参数。以数组形式指定多个初始化参数,每个参数由@WebInitParam 注解定义。 |
9.2 Filter API
Filter的实现必须继承javax.servlet.Filter接口,这个接口包含了Filter的3个生命周期:init、doFilter、destroy。
//初始化
@Override
public void init(FilterConfig filterConfig){}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain){}
@Override
public void destroy() {}
9.2.1 doFilter()方法
当Servlet容器每次处理Filter相关的资源时,都会调用doFilter方法,doFilter有三个参数
doFilter中最后一行必须调用FilterChain中的doFilter方法,FilterChain就像一条链条将多个Filter连接起来,filterChain.doFilter能触发下一个Filter如果没有下一个,将触发处理资源的方法;如果没有在doFilter的最后调用FilterChain.doFilter方法,该请求将会种植,后面的处理会中断
filterChain.doFilter(servletRequest,servletResponse);
例子:只有登录成功的用户才能访问主页等页面
/**
* 过滤器
* value:用来指定当前过滤器过滤哪些请求
* /* 其中/代表项目根路径 *表示任意多个字符
* /*:所有以项目根路径开头的请求都被当前过滤器过滤
* auth:authentication 认证
*
* URL:类似绝对路径
* URI:类似相对路径
*/
@WebFilter(value = "/*")
public class AuthFilter implements Filter {
/**
* 初始化方法
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
//执行过滤方法
//HttpServletRequest是ServletRequest的子类
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// System.out.println("---过滤器执行");
//设置响应编码方式
servletResponse.setContentType("text/html; charset=utf-8");
servletRequest.setCharacterEncoding("UTF-8");
//获取URI
HttpServletRequest request = (HttpServletRequest) servletRequest;
String uri = request.getRequestURI();
if(requireLogin(uri)){
System.out.println("需要登陆");
//从session中得到用户id
if(request.getSession().getAttribute("uid")!=null){
//已登录
//过滤器放行,让后面的过滤器或servlet处理这个请求
filterChain.doFilter(servletRequest,servletResponse);
}else{
//未登录
//返回结果,进入登录界面
servletResponse.getWriter().write("无法访问此界面,请登录");
servletResponse.getWriter().write("<br><a style='font-size:0.5em' href='/bank100_war/'>点击此处登录</a>");
return;
}
}else{
System.out.println("不需要登陆");
//过滤器链,过滤器的执行有先后顺序
filterChain.doFilter(servletRequest,servletResponse);
}
// System.out.println(uri);
}
//验证请求的uri是否需要登录之后才能访问
private boolean requireLogin(String uri){
//不需要登陆的uri
String uris[] = {"/bank100_war/","/bank100_war/index.html","/bank100_war/login"};
String straticResource[] = {"/bank100_war/js/","/bank100_war/css/"};
for (String s : uris) {
if(uri.equals(s)){
return false;
}
}
for (String s : straticResource) {
if(uri.startsWith(s)){
return false;
}
}
return true;
}
@Override
public void destroy() {
}
}