一、概述
滤器(filter):本质是Java中预先定义好了不同的接口,可以过滤不同的内容,在项目中,我们对访问某些资源的请求需要进条件的筛选、过滤时、就需要使用者定义一个实现类,然后实现接口中的过滤方法,在方法中书写过滤的条件。filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行。
应用:1、过滤论动中的非法字符
2、登录权限检查
API:
void init(FilterConfig filterConfig); //过滤器对象创建的时候调用的方法
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain);//执行过滤的方法
void destory();//过滤器销毁的时候调用的方法
开发步骤:
步骤一:新建一个java类、实现Filter接口
步骤二:重写Filter接口的3个方法
步骤三:类上面配置注解
@WebFilter 配置Filter的注解
filterName;设置过滤器的名称
urlPatterns 配置这个过滤器要拦截的资源的路径
步骤四:在doFilter()方法中、书写过滤的业务逻辑
chain.doFilter()方法放行
演示:
Servlet代码、LoginServlet.java
package com.mvcCase.Test;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//重定向到首页
response.sendRedirect("index.jsp");
}
}
MyFilter.java
package com.mvcCase.Test;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(filterName = "MyFilter", urlPatterns = {"/login","/index.jsp"})
public class MyFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//执行过滤的方法
//将ServletRequest对象强转成HttpServletRequest对象
HttpServletRequest request = (HttpServletRequest) req;
//获取请求路径
StringBuffer url = request.getRequestURL();
System.out.println("拦截了请求:"+url);
//放行
chain.doFilter(request,resp);
}
public void destroy() {
}
}
二、过滤器的执行流程
过滤器的doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)方法中的request对象和response对象并不是过滤器自己创建的。而是,从被过滤的资源中传递过来的。过滤器的执行流程如下:
1. 客户端(浏览器)的HttpRequest到达Servlet之前,被Filter的doFilter()方法拦截;
2. 根据需要,我们可以获取或者修改HttpRequest对象中的数据;
3. 在这个请求响应给浏览器之前,Filter拦截了HttpResponse对象;
4. 根据需要,我们可以获取或者修改HttpReponse对象中的数据;
5. 最后,由doFilter中的chain决定是否让这个请求通过;
三、Filter生生命周期
1、Filter类的对象是在服务器启动的时候创建的;
2、Filter类对象创建完成后会调用init()方法;
3、只要一个请求符合Filter拦截路径、浏览器请求一次、就会被doFilter方法拦截、
4、服务器停止、调用destory方法
演示:
package com.mvcCase.Test;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(filterName = "LifeFilter",urlPatterns = "/login")
public class LifeFilter implements Filter {
/**
* 显示创建这个类的无参构造方法
*/
public LifeFilter() {
System.out.println("LifecycleFilter对象被创建了.................");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LifecycleFilter的init方法被执行了.......................");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("LifecycleFilter的doFilter方法执行了..............");
}
@Override
public void destroy() {
System.out.println("LifecycleFilter的destory方法执行了.......................");
}
}
doFilter()方法
doFilter()方法是拦截请求的方法,只要一个请求符合Filter拦截路径,都会被doFilter()方法拦截。doFilter()方法有3个参数,这3个参数的作用分别如下:
参数 | 说明 |
---|---|
ServletRequest req | ServletRequest是HttpServletRequest类的父类,其中包含了被拦截的请求的信息 |
ServletResponse resp | ServletResponse是HttpServletResponse类的父类,其中包含了被拦截的响应的信息 |
FilterChain chain | FilterChain给Filter提供了放行的方法。chain.doFilter(); |
四、Filter映射路径
1、精确匹配
精确匹配,要求访问的资源路径必须与Filter的urlPatterns中的配置一致。如下:
精确匹配 | 说明 |
---|---|
urlPatterns = "/index.jsp" | 拦截对index.jsp页面的请求 |
urlPatterns = "/loginServlet" | 拦截对loginServlet的请求 |
urlPatterns = "/a.jpg" | 拦截对a.jsp的请求 |
Filter的urlPatterns参数中也可以一次性配置多个路径,如下:
精确匹配 | 说明 |
---|---|
urlPatterns = {"/login.jsp","/descServlet"} | 既能拦截login.jsp又拦截descServlet的请求 |
2、模糊匹配
模糊匹配主要有以下3种写法:
模糊匹配 | 使用示例 | 说明 |
---|---|---|
urlPatterns = "/*" | urlPatterns = "/*" | 对所有的请求都进行拦截 |
urlPatterns = "/xxx/*" | urlPatterns = "/user/*" | 对映射路径中/user下的所有资源进行拦截 |
urlPatterns = "*.xxx" | urlPatterns = "*.jsp" | 对指定后缀的请求进行拦截 |
五、Filter应用案例
1、Filter统一解决post请求乱码问题
8.0版本以上的tomcat为我们解决了get请求的乱码问题。我们需要自己处理post请求的乱码问题,因为我们的一个项目中可能有很多的请求。这时就可以用Filter来处理了。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "AEncodeFilter",urlPatterns = "/demoServlet")
public class AEncodeFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//响应的乱码的处理
HttpServletResponse response = (HttpServletResponse)resp;
response.setContentType("text/html;charset=utf-8");
//post请求的乱码处理
HttpServletRequest request = (HttpServletRequest)req;
String method = request.getMethod();
if("POST".equals(method)){
req.setCharacterEncoding("utf-8");
}
//放行
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
2、非法字符过滤器
说明:
1.创建一个表单用于发表言论。
2.创建一个txt文件,其中存入非法字符。
3.创建一个Filter,拦截请求。在init方法中将txt文件中的非法字符读取到内存中。
4.获取请求中的参数,对请求的参数进行非法字符的校验。
5.如果言论中不含有非法字符,就放行。
6.如果言论中含有非法字符,就拦截,并且提示用户非法言论
form.jsp表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/wordsServlet" method="post">
用户名:<input type="text" name="username"><br>
评论:<textarea name="desc"></textarea><br>
<input type="submit" value="提交">
</form>
</body>
</html>
WordsServlet.java
package com.filter.errorwords;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/wordsServlet")
public class wordsServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
//
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;character=utf-8");
String str = request.getParameter("username");
String str1 = request.getParameter("desc");
response.getWriter().print("context is true ="+str+str1);
}
}
WordsFilter.java 过滤器
package com.filter.errorwords;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
@WebFilter(filterName = "WordsFilter",urlPatterns = {"/wordsServlet"})
public class WordsFilter implements Filter {
StringBuffer sb = new StringBuffer();
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
request.setCharacterEncoding("utf-8");
// HttpServletResponse response = (HttpServletResponse) resp;
// response.setContentType("text/html;character=utf-8");
String desc = request.getParameter("desc");
// System.out.println("desc = " + desc);
if (sb.toString().contains(desc)){
System.out.println("内容敏感,重新提交");
resp.getWriter().print("内容敏感、重新提交");
return;
}
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
String realPath = config.getServletContext().getRealPath("disu.txt");
String line = null;
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(realPath),"utf-8");
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null){
sb.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("sb"+sb.toString());
}
}