filter是servlet的拦截器,能够在servlet处理前进行一些操作,比如设置编码、登录拦截等。(aop和filter非常类似)
配置filter
可以在web.xml配置
<filter>
<filter-name>demo1</filter-name>
<filter-class>com.52dixiaowo.web.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
<!-- 拦截路径 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
它的配置和servlet相似,只需要配置filter-class,和filter-mapping即可。
使用注解时,可使用@WebFilter
拦截方式
对于拦截路径, 下面有 4 种简单的方式, 还可以自由组合
- 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
- 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
- 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
- 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
对于请求方式, 还可以选定哪种请求, 需要设置dispatcherTypes属性
- REQUEST:默认值。浏览器直接请求资源, 也可以同时设置多个值
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
filter 过滤链的顺序问题: 如果是web.xml是按照<filter-mapping>的顺序, 而注解则是类名字符串大小, 比如 AFilter 比 BFilter先拦截.
关键方法 : doFilter
使用 doFilter 方法, 写上你要处理的逻辑代码, 该方法三参数, request, response, filterchain, 分别代表请求对象, 响应对象, 以及过滤链对象
其中 filterchain 对象, 有一个方法, filterChain.doFilter(servletRequest,servletResponse); 表示放行, 在它之前的代码表示对请求的处理, 在它之后的代码表示对响应的处理
对于 filter 的另外 2 个方法, init 和 destroy 表示web容器启动和销毁的处理
统一编码
如果使用get请求, 是不会乱码的, 而post有可能乱码, 可以使用filter设置统一编码
先 new 一个 class , 名称叫 EncodingFilter , 并拷贝如下代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 解决全站乱码问题,处理所有的请求
*/
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse rep, FilterChain filterChain) throws IOException, ServletException {
//将父接口转为子接口
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) rep;
//获取请求方法
String method = request.getMethod();
//解决post请求中文数据乱码问题, get不会乱码
if(method.equalsIgnoreCase("post")){
request.setCharacterEncoding("utf-8");
}
//处理响应乱码, 仅设置响编码,而不是 setContentType
response.setCharacterEncoding("utf-8");
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
注意,上述代码设置了response编码,对于html等资源由于项目环境问题反而有可能会造成乱码。
拦截登陆
在访问特定uri时,先检测session中是否存在对应的字段
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/admin/*")
public class AdminFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
//禁止未登录的admin
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (request.getSession().getAttribute("admin")==null){
response.setCharacterEncoding("utf-8");
String s = "<!DOCTYPE html><html><head><meta charset='UTF-8'><title>未登录</title>";
s+="<script>function countDown(){var time=document.getElementById('Time');";
s+="if(time.innerHTML==0){window.location.href='"+request.getContextPath()+"/index.html'}";
s+="else{time.innerHTML=time.innerHTML-1}}window.setInterval('countDown()',1000);</script>";
s+="<style>p{font-size:50px;text-align:center}#Time{font-size:100px;text-align:center}</style></head>";
s+="<body><p>admin,您还未登录!</p><p>即将在3秒后自动跳转登录界面,点击<a href='"+request.getContextPath()+"/index.html'>";
s+="立刻跳转</a></p><p id='Time'>3</p></body></html>";
response.getWriter().println(s);
}else{
filterChain.doFilter(request,response);
}
}
@Override
public void destroy() {
}
}
以上只是一个简单的示例且并不灵活,更灵活的方式是把拦截页面设置为Html静态文件,使用I/O流读取。
本篇完,还有疑问?留下评论吧