过滤器
1.1.1. 如何编写过滤器
编写过滤器遵循下列步骤:
- 编写一个实现了Filter接口的类
- 实现Filter接口的三个方法,过滤逻辑在doFilter方法中实现
- 在Web程序中注册过滤器
- 把过滤器和Web应用一起打包部署
步骤一、实现Filter接口
Filter是过滤器API中最核心的接口,定义一个Java类实现该接口以提供过滤逻辑。代码如下:
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
public class CommentFilter implements Filter{
//… …
}
步骤二、实现doFilter方法
Filter接口中共定义了三个方法,分别是init,doFilter,destroy方法。
init方法在创建Filter时会被调用,且只调用一次,一般在该方法中做一些数据的准备工作,可以通过传入的FilterConfig参数获取在web.xml文件中配置提供给过滤器的初始参数。
destroy方法只有在销毁过滤器对象时被调用一次,用于释放一些资源的操作。
doFilter方法内编写过滤器的具体处理逻辑,会被多次执行。该方法共有三个参数,请求和响应用于获取数据以及追加数据,FilterChain是过滤器链,负责多过滤器的传递。
实现代码如下:
- import java.io.IOException;
- import java.io.PrintWriter;
- import javax.servlet.*;
- import javax.servlet.http.*;
- public class CommentFilter implements Filter{
- private FilterConfig config;
- public void destroy() {
- //.....
- }
- /*
- * 容器会调用doFilter方法来处理请求(
- * 相当于servlet的service方法)。
- * 容器会将request对象(arg0)和response对象
- * (arg1)作为参数传给doFilter方法。
- * 如果调用了FilterChain(arg2)的doFilter(request,response)方法,
- * 则容器会调用后续的过滤器或者servlet,否则请求处理完毕。
- */
- public void doFilter(ServletRequest arg0,
- ServletResponse arg1, FilterChain arg2)
- throws IOException, ServletException {
- //.....
- }
- /*
- * FilterConfig对象可以用来访问过滤器的初始化参数。
- * init方法只会执行一次。
- */
- public void init(FilterConfig arg0) throws ServletException {
- //.....
- }
- }
步骤三、注册过滤器
在web.xml文件中注册过滤器,代码如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.4"
- xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
- http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
- <!-- 过滤器 -->
- <filter>
- <filter-name>filter1</filter-name>
- <filter-class>web.CommentFilter</filter-class>
- <!-- 初始化参数,由FilterConfig对象读取-->
- <init-param>
- <param-name>illegalStr</param-name>
- <param-value>胡萝卜</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>filter1</filter-name>
- <url-pattern>/comment</url-pattern>
- </filter-mapping>
- </web-app>
步骤四、部署过滤器
将编译后的过滤器和其他Web组件类合在一起,连同web.xml文件放进应用程序结构中即可。
1.1.2. 过滤器的优先级
在一个Web应用中,可以有多个过滤器,它们的优先级由位于web.xml文件中的声明顺序决定,具体是按照<filter-mapping>的顺序来决定的。如下代码所示,filter1和filter2都已经注册,执行顺序是filter2 -> filter1 。
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.4"
- xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
- http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
- <!-- 过滤器 -->
- <filter>
- <filter-name>filter1</filter-name>
- <filter-class></filter-class>
- </filter>
- <filter>
- <filter-name>filter2</filter-name>
- <filter-class></filter-class>
- </filter>
- <filter-mapping>
- <filter-name>filter2</filter-name>
- <url-pattern>/comment2</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>filter1</filter-name>
- <url-pattern>/comment1</url-pattern>
- </filter-mapping>
- </web-app>
1.1.3. 过滤器的初始化参数
容器启动之后,会创建过滤器实例。通过init方法来完成过滤器的初始化。初始化时可以添加一些配置,提升动态性。而这些参数通过在web.xml文件中的<init-param>以name-value对的形式存在。
读取这些name-value对需要使用FilterConfig对象,从web.xml文件到FilterConfig对象的过程由容器完成,并通过参数传入到init方法之中,只需要设定一些成员对象保存数值就可以在doFilter方法中使用。
1.1.4. 初始化参数的配置
在web.xml文件中添加过滤器初始化参数的配置代码如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.4"
- xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
- http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
- <!-- 过滤器 -->
- <filter>
- <filter-name>filter1</filter-name>
- <filter-class>web.CommentFilter1</filter-class>
- <!-- 初始化参数 -->
- <init-param>
- <param-name>illegalStr</param-name>
- <param-value>胡萝卜</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>filter1</filter-name>
- <url-pattern>/comment</url-pattern>
- </filter-mapping>
- </web-app>
1.1.5. 读取初始化参数
读取初始化参数使用如下代码:
- public class CommentFilter implements Filter{
-
- public void init(FilterConfig config ) throws ServletException {
- String illegalStr = config.getInitParameter("illegalStr");
- }
- public void doFilter(ServletRequest arg0,
- ServletResponse arg1, FilterChain arg2)
- throws IOException, ServletException {
- // … …
- }
-
- public void destroy() {
- // … …
- }
- }
1.1.6 案例
针对用户输入的评论内容进行敏感词汇的过滤,如果包含“damn”字样,则提示用户评论已关闭。
步骤一:新建comment.jsp页面
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>评论</title>
</head>
<body>
<form action="comment" method="post">
<fieldset>
<legend>评论</legend>
请输入评论:
<textarea name="comment" style="vertical-align: middle; width: 140px; height: 55px"></textarea>
<Br>
<input type="submit" value="发表评论" />
</fieldset>
</form>
</body>
</html>
步骤二:新建FirstTest.java文件
package com.xinrong;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FilterTest extends HttpServlet{
private static final long serialVersionUID = 7910764243266128882L;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
//获取评论内容
String str = request.getParameter("comment");
//显示评论内容
out.println("<h3>评论内容:" + str + "</h3>");
out.close();
}
}
步骤三:新建CommentFilter类
package com.xinrong;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CommonFilter implements Filter {
private String illegalWord;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
req.setCharacterEncoding("UTF-8");
res.setContentType("text/html;charset=UTF-8");
PrintWriter out = res.getWriter();
String comment = req.getParameter("comment");
if (comment.indexOf(illegalWord) != -1) {
//有敏感词汇
out.print("<h3>评论内容已关闭</h3>");
} else {
//没有敏感词汇则向后处理,交给其他过滤器或Servlet
filterChain.doFilter(req, res);
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 读取初始化参数
illegalWord = filterConfig.getInitParameter("illegalWord");
System.out.println("Filter1:init is runnming... " + illegalWord);
}
}
步骤四:配置CommentFilter过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>FilterDemo01</display-name>
<welcome-file-list>
<welcome-file>Filter.jsp</welcome-file>
</welcome-file-list>
<!-- Filter -->
<filter>
<filter-name>FilterDemo</filter-name>
<filter-class>com.xinrong.CommonFilter</filter-class>
<!-- 初始化参数 -->
<init-param>
<param-name>illegalWord</param-name>
<param-value>damn</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<!-- 与哪个servlet路径一致,代表针对这个路径的请求要进行过滤 -->
<url-pattern>/comment</url-pattern>
</filter-mapping>
<!-- servlet -->
<servlet>
<servlet-name>Filter</servlet-name>
<servlet-class>com.xinrong.FilterTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Filter</servlet-name>
<url-pattern>/comment</url-pattern>
</servlet-mapping>
</web-app>
步骤五:部署应用,输入评论查看结果