Filter介绍
Servlet有三大组件:Servlet,Filter,Listener.
Filter中文意思为过滤,在Web中,过滤器可以在请求到达目标资源之前先对请求进行拦截,也就是可以先对请求进行一些处理,之后再放行去访问目标资源;也可以在响应返回到客户端之前对响应进行拦截,也就是可以对响应做一些处理,再返回给客户端。
过滤器作用
通过Filter,能够对web服务器管理的所有web资源,比如jsp,servlet,静态图片,静态html等文件进行拦截过滤,从而实现一些特殊的功能。比如登录验证,统一编码处理,敏感词汇过滤等。
Filter接口
在Servlet中,提供了一个接口javax.servlet.Filter
,只要实现该接口的类,就可以称为过滤器。
Filter接口有三个方法需要重写:
init()
:初始化方法,在服务器启动后会创建Filter对象,然后调用init方法,只会执行一次,用于加载资源。doFilter()
:核心方法,对于请求和响应的过滤,都是在该方法中完成,每一次请求被拦截的资源时会执行。destroy()
:销毁方法,在服务器关闭后,Filter对象被销毁,会执行该方法,只执行一次,一般用于释放资源。创建Filter过滤器
javax.servlet.Filter
接口import javax.servlet.*;
import java.io.IOException;
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter 初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter 调用");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.println("Filter 销毁");
}
}
注意:在Filter的doFilter方法内部如果没有调用doFilter(request,response)方法,那么服务器中的资源是不会被访问到的。doFilter(request,response)就是一个放行
Filter细节
web.xml配置
注册Filter
<filter>
<filter-name>Demo1</filter-name>
<filter-class>com.zzy.www.filter.FilterDemo1</filter-class>
<init-param>
<param-name>path</param-name>
<param-value>/WEB_INF/a.txt</param-value>
</init-param>
</filter>
<filter-name>
:设置过滤器的名字,内容不能为空
<filter-class>
:指定过滤器的完整的类名
<init-param>
:用于为过滤器指定初始化参数,<param-name>
指定参数的名称,<param-value>
指定参数的值。(在过滤器中可以使用FilterConfig接口对象来访问初始化参数)(多个参数就有多个<init-param>
)
映射Filter
<filter-mapping>
<filter-name>Demo1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-name>
:用于设置Filter的注册名称,这个值必须是在注册Filter时<filter>中声明过的过滤器名字。
<url-pattern>
:设置Filter要拦截的请求路径。Filter的全路径匹配只支持/*,不支持/
<filter-mapping>
还有两个标签<servlet-name>
和<dispatcher>
<servlet-name>
:指定过滤器要拦截的Servlet名称
<dispatcher>
:指定过滤器拦截的资源被Servlet调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认是REQUEST。
<jsp:include page="xxx.jsp"/>
嵌入进来的页面,每一个嵌入的页面,都会走一次值为INCLUDE的过滤器。如果是注解的方式配置,则是设置dispatcherTypes属性。
过滤器执行流程
过滤器生命周期
过滤器链(多个过滤器)
? 如果在web中设置了多个过滤器,那么这些过滤器执行过程是以一种链的形式执行的。
也就是每一个Filter串一起形成一条链,按照链的顺序依次执行,一个Filter执行完filterChain的doFilter()方法后,转而执行另一个Filter,直到最后一个Filter,最后一个Filter的filterChain.doFilter()会自动跳转到最终的请求资源。
? 在请求到达Filter之后,Filter可以拦截请求对象,并能对请求进行修改,修改过后再转向下一个Filter或资源。
? 当最终的资源执行完毕,形成了响应对象后,会按照Filter链的顺序逆序再次访问Filter,此时的Filter能够拦截到响应对象,并能对响应进行修改,最后客户端接收到的是被FIlter修改过的响应。
Filter的特点
Filter解决乱码问题
之前编写servlet时候,在处理POST请求乱码时,需要在获取请求参数前设置request的编码request.setCharacterEncoding("utf-8");
在响应时候,也需要处理乱码问题,之前是使用response.setContentType("text/html;charset=utf-8");
这种处理方式很繁琐,需要在每一个servlet中都声明这些编码,可以通过使用过滤器,提取这些公有代码到过滤器中。
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("username: " + username);
response.getWriter().println("用户名为:" + username);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/BookTest/LoginServlet" method="post">
<label for="username">姓名:</label><input type="text" id="username" placeholder="请输入姓名" name="username"> <br>
<input type="submit" value="登录">
</form>
</body>
</html>
@WebFilter(filterName = "FilterTest1", urlPatterns = "/*")
public class FilterTest1 implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
登陆验证
针对用户访问网站,当用户未登录时只能访问首页,登陆页面,其他页面是没有权限访问的,必须登陆才能访问,此时过滤器可以做一个权限管控,如果用户已登录,就放行;否则则跳转到登录页面。
比如用户访问news.jsp页面.未登录前先访问news.jsp是会自动跳转到登录页面的,只有登录后访问才能直接访问news.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>news</title>
</head>
<body>
<h1>Welcome!</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/BookTest/LoginServlet" method="post">
<label for="username">姓名:</label><input type="text" id="username" placeholder="请输入姓名" name="username"> <br>
<label for="password">密码:</label><input type="password" id="password" placeholder="请输入密码" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("username: " + username);
if (username != null) {
HttpSession s = request.getSession();
if (s.getAttribute("username") == null) {
s.setAttribute("username", username);
}
}
response.sendRedirect("/BookTest/news.jsp");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
@WebFilter(filterName = "FilterTest2",urlPatterns = "/*")
public class FilterTest2 implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
// 获取访问地址
String path = request.getServletPath();
System.out.println(path);
if (path.startsWith("/news.jsp")) {
HttpSession s = request.getSession();
System.out.println(s);
// 说明还没登录
if (s == null) {
// 跳转到登录界面
response.sendRedirect("/BookTest/login.html");
} else {
String name = (String)s.getAttribute("username");
System.out.println("name = " + name);
if (name == null) {
response.sendRedirect("/BookTest/login.html");
}
}
}
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
原文:https://www.cnblogs.com/LucasBlog/p/13709249.html