Filter
2 Servlet规范中的过滤器-Filter
2.1 过滤器入门
2.1.1 过滤器概念及作用
过滤器——Filter,它是JavaWeb三大组件之一。另外两个是Servlet和Listener。
它是在2000年发布的Servlet2.3规范中加入的一个接口。是Servlet规范中非常实用的技术。
它可以对web应用中的所有资源进行拦截,并且在拦截之后进行一些特殊的操作。
常见应用场景:URL级别的权限控制;过滤敏感词汇;中文乱码问题等等。
过滤器介绍
在程序中访问服务器资源时,当一个请求到来,服务器首先判断是否有过滤器与请求资源相关联,如果有,过滤器可以将请求拦截下来,完成一些特定的功能,再由过滤器决定是否交给请求资源。如果没有则像之前那样直接请求资源了,响应也是类似的。
Filter介绍
Filter是一个接口。如果想实现过滤器的功能,必须实现该接口
核心方法
| 返回值 | 方法名 | 作用 |
| void | init(FilterConfig config) | 初始化方法 |
| void | doFilter(ServletRequest request,ServletResponse,FilterChain chain) | 对请求资源和响应资源过滤 |
| void | destroy() | 销毁方法 |
配置方式
注解方式
配置文件
FilterChain介绍
FilterChain是一个接口,代表过滤器链对象。由Servlet容器提供实现类对象
过滤器可以定义很多个,就会组成过滤器链
如果有多个过滤器,在第一个过滤器中调用下一个过滤器,以此类推。直到到达最终访问资源
如果只有一个过滤器,放行时,就会直接到达最终访问资源
2.1.2 过滤器的入门案例
需求说明
通过Filter过滤器解决多个资源写出中文乱码的问题。
最终目的
通过本需求,最终掌握Filter过滤器的使用。
1)前期准备
创建JavaWeb工程
创建两个Servlet功能类,都向客户端写出中文数据
创建一个Filter过滤器实现类,重写doFilter核心方法
在方法内解决中文乱码,并放行
部署并启动项目
通过浏览器测试
处理中文乱码问题(过滤器拦截 处理完在放行)
先创建两个Servlet
ServletDemo01
package com.itheima.servlet;
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("/servletDemo01")
public class ServletDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servletDemo01执行了。。。");
//resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("servletDemo01执行了。。。");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
ServletDemo02
package com.itheima.servlet;
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("/servletDemo02")
public class ServletDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servletDemo02执行了。。。");
//resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("servletDemo02执行了。。。");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
过滤器
FilterDemo01
package com.itheima.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
* 过滤器的基本使用
* */
@WebFilter("/*")
public class FilterDemo01 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo01执行了");
//处理乱码
servletResponse.setContentType("text/html;charset=UTF-8");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
运行结果如图
控制台输出如下
过滤器使用细节
配置方式
注解方式@WebFilter(拦截路径)
配置文件方式
filterDemo1 com.itheima.web.filter.FilterDemo1 filterDemo1 /*
多个过滤器使用顺序
如果有多个过滤器,取决于过滤器映射的顺序
的配置前后顺序决定过滤器的调用顺序,也就是由映射配置顺序决定。
过滤器生命周期
创建
当应用加载时实例化对象并执行init 初始化方法
服务
对象提供服务的过程,执行doFilter方法
销毁
当应用卸载时或服务器停止时对象销毁,执行destory方法。
package com.itheima.filter;
import javax.servlet.*;
import java.io.IOException;
/*
* 过滤器的生命周期
* */
//@WebFilter("/*")
public class FilterDemo03 implements Filter {
/*
* 初始化方法
* */
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("对象初始化成功了");
}
/*
* 提供服务的方法
* */
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo03执行了");
//处理乱码
servletResponse.setContentType("text/html;charset=UTF-8");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("对象销毁了");
}
}
最后停止服务器的时候销毁
2.2.4 过滤器与Servlet的区别
| 方法/类型 | Servlet | Filter | 备注 |
|---|---|---|---|
| 初始化 方法 | void init(ServletConfig); |
void init(FilterConfig); |
几乎一样,都是在web.xml中配置参数,用该对象的方法可以获取到。 |
| 提供服务方法 | void service(request,response); |
void dofilter(request,response,FilterChain); |
Filter比Servlet多了一个FilterChain,它不仅能完成Servlet的功能,而且还可以决定程序是否能继续执行。所以过滤器比Servlet更为强大。 在Struts2中,核心控制器就是一个过滤器。 |
| 销毁方法 | void destroy(); |
void destroy(); |
FilterConfig介绍
FilterConfig是一个接口,代表过滤器的配置对象,可以加载一些初始化参数。
FilterDemo04
package com.itheima.filter;
import javax.servlet.*;
import java.io.IOException;
import java.net.Socket;
/*
* 过滤器的配置对象的使用
* */
//@WebFilter("/*")
public class FilterDemo04 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("对象初始化成功了。。。");
//获取过滤器名称
String filterName = filterConfig.getFilterName();
System.out.println(filterName);
//根据name获取value
String username = filterConfig.getInitParameter("username");
System.out.println(username);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo04执行了");
//处理乱码
servletResponse.setContentType("text/html;charset=UTF-8");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
web.xml
filterDemo04 com.itheima.filter.FilterDemo04 username zhangsan filterDemo04 /*
过滤器五种拦截行为
我们的过滤器目前拦截的是请求,但是在实际开发中,我们还有请求转发和请求包含,以及由服务器触发调用的全局错误页面。默认情况下过滤器是不参与过滤的,要想使用,需要我们配置。配置的方式如下:
拦截方式
FilterDemo1 com.itheima.web.filter.FilterDemo1 true FilterDemo1 /ServletDemo1 REQUEST ERROR FORWARD INCLUDE ASYNC
2.3过滤器的使用案例
2.3.2 特殊字符过滤器
1)需求说明
在实际开发中,可能会面临一个问题,就是很多输入框都会遇到特殊字符。此时,我们也可以通过过滤器来解决。
例如:
我们模拟一个论坛,有人发帖问:“在HTML中表示水平线的标签是哪个?”。
如果我们在文本框中直接输入就会出现一条水平线,这个会让发帖人一脸懵。
我们接下来就用过滤器来解决一下。
2)编写步骤
第一步:创建JavaWeb工程
沿用第一个案例的工程
第二步:编写Servlet和JSP
package com.itheima.servlet;
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("/servletDemo01")
public class ServletDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String content = req.getParameter("content");
resp.getWriter().write(content);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
jsp页面
<%--
Created by IntelliJ IDEA.
User: 12270
Date: 2021/3/22
Time: 22:24
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
$Title$
第三步:编写过滤器
package com.itheima.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HTMLFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
//创建一个自己的Request类
MyHttpServletRequest2 myrequest = new MyHttpServletRequest2(request);
//放行:
chain.doFilter(myrequest, response);
}
public void destroy() {
}
}
class MyHttpServletRequest2 extends HttpServletRequestWrapper {
//提供一个构造方法
public MyHttpServletRequest2(HttpServletRequest request){
super(request);
}
//重写getParameter方法
public String getParameter(String name) {
//1.获取出请求正文: 调用父类的获取方法
String value = super.getParameter(name);
//2.判断value是否有值
if(value == null){
return null;
}
return htmlfilter(value);
}
private String htmlfilter(String message){
if (message == null)
return (null);
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuilder result = new StringBuilder(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
}
第四步:配置过滤器
<?xml version="1.0" encoding="UTF-8"?>HTMLFilter com.itheima.filter.HTMLFilter HTMLFilter /*
测试效果
2.3.2 特殊字符过滤器
1)需求说明
在实际开发中,可能会面临一个问题,就是很多输入框都会遇到特殊字符。此时,我们也可以通过过滤器来解决。
例如:
我们模拟一个论坛,有人发帖问:“在HTML中表示水平线的标签是哪个?”。
如果我们在文本框中直接输入就会出现一条水平线,这个会让发帖人一脸懵。
我们接下来就用过滤器来解决一下。
2)编写步骤
第一步:创建JavaWeb工程
沿用第一个案例的工程
第二步:编写Servlet和JSP
/**
* @author 黑马程序员
* @Company http://www.itheima.com
*/
public class ServletDemo1 extends HttpServlet {
?
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String content = request.getParameter("content");
response.getWriter().write(content);
}
?
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
?
}
<servlet>
<servlet-name>ServletDemo1servlet-name>
<servlet-class>com.itheima.web.servlet.ServletDemo1servlet-class>
servlet>
<servlet-mapping>
<servlet-name>ServletDemo1servlet-name>
<url-pattern>/ServletDemo1url-pattern>
servlet-mapping>
<% page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>title>
head>
<body>
<form action="${pageContext.request.contextPath}/ServletDemo1" method="POST">
回帖:<textarea rows="5" cols="25" name="content">textarea><br/>
<input type="submit" value="发言">
form>
body>
html>
第三步:编写过滤器
?
/**
* @author 黑马程序员
* @Company http://www.itheima.com
*/
public class HTMLFilter implements Filter {
?
public void init(FilterConfig filterConfig) throws ServletException {
?
}
?
?
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
//创建一个自己的Request类
MyHttpServletRequest2 myrequest = new MyHttpServletRequest2(request);
//放行:
chain.doFilter(myrequest, response);
}
?
public void destroy() {
}
}
class MyHttpServletRequest2 extends HttpServletRequestWrapper {
//提供一个构造方法
public MyHttpServletRequest2(HttpServletRequest request){
super(request);
}
?
//重写getParameter方法
public String getParameter(String name) {
//1.获取出请求正文: 调用父类的获取方法
String value = super.getParameter(name);
//2.判断value是否有值
if(value == null){
return null;
}
return htmlfilter(value);
}
?
private String htmlfilter(String message){
if (message == null)
return (null);
?
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuilder result = new StringBuilder(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
?
}
第四步:配置过滤器
<filter>
<filter-name>HTMLFilterfilter-name>
<filter-class>com.itheima.web.filter.HTMLFilterfilter-class>
filter>
<filter-mapping>
<filter-name>HTMLFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>