顾名思义,Filer的作用就是过滤,主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.适用Filter完整的流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并响应,最后Filter再对服务器响应进行处理.
filter有以下几个种类:
1.用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求.
2.在HttpServletRequest到达Servlet之前,拦截客户的HtttpServletRequest
3.根据需要检查HtttpServletRequest,也可以修改HtttpServletRequest头和数据
4.在HtttpServletResponse到达客户端前,拦截HtttpServletResponse
5.负责解码的filter:包括对非标准编码的请求解码
6.根据需要检查HtttpServletResponse,也可以修改HtttpServletResponse头和数据
7.filter可负责拦截多个请求或响应,一个请求或响应也可被多个Filter拦截.
创建一个Filter需要两个步骤:
1.创建Filter处理类
2.web.xml文件中配置Filter
创建Filter类
创建Filter必须实现javax.servlet.Filter的初始化
void init(filterConfig config):用于完成Filter的初始化
void destroy():用于Filter销毁前,完成资源回收
void Filter(ServletRequest request,ServletResponse response,FilterChain chain);
实现过滤功能,该 方法就是对每个请求及响应增加的额外处理
案例一:实现字符替换过滤器
对于容器产生的HttpServletRequest对象,无法直接修改某些信息,如请求参数值.就需要自己写方法来实现
但是httpServletWrapper实现了HttpServlet几口,只要继承httpServletWrapper类,并编写重新定义的方法即可
如下图:
输入:
提交后:
发现文本内容变成了超链接,原本文本域输出的效果应该是:
因此这里就需要将一些html过滤掉,如将<,>角括号换为HTML实体字符<与>,如果不想改程序,就可以直接用过滤器的方式,将用户请求参数中的角括号字符进行替换掉.
过滤替换并不需要我们来实现,可以直接适用APache Commons Lang程序库中,StringEscapeUtils.escapeHtml(String value)方法进行替换,可以从网盘下载解压放到lib文件夹中即可.
链接:https://pan.baidu.com/s/1m_Nt4LLkORpubfPGMb_Qgw 密码:4zo9
或者可以从官网下载:
http://commons.apache.org/lang/
在容器调用Servlet的service方法之前,Servlet并不知道有请求的到来,而在Servlet的service()方法运行后,容器真正对浏览器进行HTTP响应之前,浏览器也不会知道Servlet真正的响应是什么.Filter可拦截过滤浏览器对Servlet的请求,也可以改变Servlet对浏览器的响应.
换句话说,我们提交请求参数后,需要要让getParameter()返回过滤后的请求参数值,我们可以重写这个方法来实现.
EscapeWrapper.java(字符替换,重写getParameter()方法)
package Servlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.lang3.StringEscapeUtils;
/**
* Servlet implementation class EscapeWrapper
*/
@WebServlet("/EscapeWrapper")
public class EscapeWrapper extends HttpServletRequestWrapper {
@Override
public String getParameter(String name) {
String value = getRequest().getParameter(name);
return StringEscapeUtils.escapeHtml4(value);
}
/**
* @see HttpServletRequestWrapper#HttpServletRequestWrapper(HttpServletRequest)
*/
public EscapeWrapper(HttpServletRequest request) {
super(request);
// TODO Auto-generated constructor stub
}
}
EscapeFilter.java(进行拦截,调用请求封装器进行过滤)
原理:filter接口的doFilter方法类似于Servlet接口的service()方法.当请求来到容器,而容器发现调用Servlet的service()方法前,可以应用某过滤器时,就会先调用改过滤器的doFilter()方法.filterChain运行后会以堆栈顺序返回
package javax.servlet;
import java.io.IOException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import Servlet.EscapeWrapper;
@WebFilter("/*")
public class EscapeFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
Filter.super.destroy();
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest requestWrapper = new EscapeWrapper((HttpServletRequest)request);
/*如果调用了FilterChain的doFilter()方法,就会运行下一个过滤器,如果没有下一个,就调用请求目标Sevlet的service()方法*/
chain.doFilter(requestWrapper, response);
}
}
testFilter.jsp(提交文本域)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
showText.jsp(显示文本域信息)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
<%=request.getAttribute("name") %>
TestFilter.java(控制器)
package Servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class TestFilter
*/
@WebServlet("/TestFilter")
public class TestFilter extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public TestFilter() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("text");
request.setAttribute("name", name);
request.getRequestDispatcher("showText.jsp").forward(request, response);
}
}
运行后如下图:
点击提交:
可以看到过滤器已经实现了字符替换,这个应用可以载入留言功能时,防止用户借助留言板广告.
根据上述代码的实现,便能了解过滤器用在字符替换上的作用了.
案例二:实现编码设置过滤器
前面为了防止中文乱码,也废了不少劲去设置编码问题,虽然解决了,但是存在缺陷:每一次页面的编写,遇到编码问题,都要依次进行设置,当工程量大的时候,这些重复的代码设置就是冗余的.所以可以通过过滤器实现一次性过滤,这样更加方便.
同样,我们也需要提前拦截请求参数进行封装处理.
testEncodingFilter.jsp(提交请求)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
showEncoding.jsp(显示)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
<%=request.getAttribute("name") %>
TestEncodingServlet.java(控制器)
package Servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class TestEncodingFilter
*/
@WebServlet("/TestEncodingServlet")
public class TestEncodingServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public TestEncodingServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
String name = request.getParameter("name");
request.setAttribute("name", name);
request.getRequestDispatcher("showEncoding.jsp").forward(request, response);
}
}
EncodingWrapper.java(包装)
package Servlet;
import java.io.UnsupportedEncodingException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.sound.sampled.AudioFormat.Encoding;
import org.apache.commons.lang3.StringEscapeUtils;
/**
* Servlet implementation class EscapeWrapper
*/
@WebServlet("/EscapeWrapper")
public class EncodingWrapper extends HttpServletRequestWrapper {
private String EnCODING;
@Override
public String getParameter(String name) {
String value = getRequest().getParameter(name);
value = StringEscapeUtils.escapeHtml4(value);
if (value != null) {
try {
byte[] b = value.getBytes("ISO-8859-1");
value = new String(b, EnCODING);
} catch (UnsupportedEncodingException e) {
// TODO: handle exception
throw new RuntimeException(e);
}
}
return value;
}
/**
* @see HttpServletRequestWrapper#HttpServletRequestWrapper(HttpServletRequest)
*/
public EncodingWrapper(HttpServletRequest request, String ENCODING) {
super(request);
// TODO Auto-generated constructor stub]
this.EnCODING = ENCODING;
}
}
EncodingFilter.java()
package javax.servlet;
import java.io.IOException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import Servlet.EncodingWrapper;
@WebFilter(
urlPatterns={"/*"},
initParams={
@WebInitParam(name="ENCODING",value="UTF-8")
}
)
public class EncodingFilter implements Filter{
private String ENCODING;
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
ENCODING = filterConfig.getInitParameter("ENCODING");//读取初始化参数
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest requestWrapper =(HttpServletRequest)request;
if ("GET".equals(requestWrapper.getMethod())) {
requestWrapper =new EncodingWrapper(requestWrapper,ENCODING);
} else {
requestWrapper.setCharacterEncoding(ENCODING);
}
chain.doFilter(requestWrapper, response);
}
}
若是不添加编码过滤器,程序中也没有处理,运行后如下图:
点击提交(就会有乱码):
添加过滤器后:
提交(因为有过滤器的存在,所以不会有乱码):
不过,到最后想把编码过滤器和字符替换一起放在项目中,就会出现问题,tomcat会报错,无法正常启动.目前没找出原因.