Servlet过滤器
Servlet过滤器主要用于对客户端的请求进行过滤处理,将过滤后的请求转交给下一资源
什么是过滤器
Servlet过滤器与Servlet十分相似,但它具有拦截客户端请求的功能,Servlet过滤器可以改变请求中的内容来满足实际开发中的需要
对于程序开发人员来说,过滤器实际上就是在Web应用服务器上的一个Web应用组件,用于拦截客户端与目标资源的请求,并对这些请求进行一定过滤处理再发送给目标资源,同时,目标资源处理之后,请求的回应信息也同样需要经过过滤器
如果一个Web应用中使用一个过滤器不能解决实际中的业务需求,可以部署多个过滤器对业务请求进行多次处理,这样就组成了一个过滤器链
过滤器核心对象
过滤器对象放置在javax.servlet包中,其名称为Filter,是一个接口。除此之外,与过滤器有关的对象还有FilterConfig对象(配置对象)与FilterChain对象(过滤器传递工具),这两个对象也是接口对象,位于同一个包中
在实际开发中,定义过滤器只需要直接或间接实现Filter接口即可
-
Filter接口
Filter接口中定义了3个方法,分别为init(),doFilter()和destroy()方法,说明如下:
方法声明 | 说明 |
---|---|
public void init(FilterConfig filterConfig) throws ServletException | 过滤器初始化方法,该方法在过滤器初始化时调用 |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException | 对请求进行过滤处理 |
public void destroy() | 销毁方法,以便释放资源 |
-
FilterConfig接口
FilterConfig接口由Servlet容器进行实现,主要用于获取过滤器中的配置信息,方法声明如下:
方法声明 | 说明 |
---|---|
public String getFilterName() | 用于获取过滤器的名字 |
public ServletContext getServletContext() | 获取Servlet上下文 |
public String getInitParameter(String name) | 获取过滤器的初始化参数 |
public Enumeration getInitParameterNames() | 获取过滤器的所有初始化参数 |
-
FilterChain接口
FilterChain接口仍由Servlet容器进行实现,这个接口中只有一个方法,如下:
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException
用于将过滤后的请求传递给下一个过滤器,如果是过滤链最后一个过滤器,则传递给目标资源
过滤器创建与配置
创建一个Filter过滤器需要实现javax.servlet.Filter接口的3个方法,例子如下:
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
public void init(FilterConfig config) throws ServletException{
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{
// 在请求处理之后,需要调用chain参数的doFilter()将请求传给下一个过滤器或者目标资源
chain.doFilter(request, response);
}
public void destroy(){
}
}
使用过滤器不一定要将请求向下传递给过滤器或者目标资源,如果业务逻辑需要,可以在过滤处理之后回应于客户端
过滤器与Servlet一样,在创建之后需要对其进行配置,分为两个步骤,主要为声明过滤器对象和创建过滤器映射
创建名为MyFilter的过滤器对象
<filter>
<filter-name>MyFliter</filter-name>
<filter-class>com.wang.yx.Filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFliter</filter-name>
<url-pattern>/MyFilter</url-pattern>
</filter-mapping>
<filter>标签用于声明过滤器对象,这个标签中配置了两个子元素,为过滤器名称和过滤器完整类名
<filter-mapping>标签用于创建过滤器映射,它的作用就是指定Web应用中,哪些URL应用哪一个过滤器进行处理。其中<filter-name>用于定义过滤器的名称,<url-pattern>用于指定过滤器应用的URL
创建一个过滤器,实现网站访问计数器的功能,并在web.xml配置中将网站访问量的初始值设置为5000
(1)创建名称为CountFilter的类,通过该过滤器对象实现统计网站访问人数功能:
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class CountFilter implements Filter {
private int count;
@Override
public void init(FilterConfig config) throws ServletException{
// 对count进行赋值,通过FilterConfig对象读取配置文件中的初始化参数进行获取
String param = config.getInitParameter("count");
count = Integer.valueOf(param);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{
count++;
// 为了能够访问计数器中的值,将其放置于Servlet的上下文中,上下文对象通过将ServletRequest转换为HttpServletRequest对象后获取
HttpServletRequest req = (HttpServletRequest)request;
ServletContext context = req.getSession().getServletContext();
context.setAttribute("count", count);
chain.doFilter(request, response);
}
@Override
public void destroy(){
}
}
(2)配置已创建的CountFilter对象,通过配置web.xml文件实现:
<filter>
<filter-name>CountFilter</filter-name>
<filter-class>com.wang.yx.Filter.CountFilter</filter-class>
<init-param>
<param-name>count</param-name>
<param-value>5000</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CountFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
实例通过<init-param>标签配置过滤器的初始化参数,初始化参数为count,参数值为5000
(3)创建首页index.jsp,在页面中通过JSP内置对象Application获取计数器的值,如下:
<body>
<h2>
欢迎光临,<br>
您是本站的第【 <%=application.getAttribute("count")%> 】位访客!
</h2>
</body>
字符编码过滤器
在Java Web开发中,由于Web容器内部所使用的编码格式不支持中文字符集,所以,处理浏览器请求中的中文数据就会出现乱码现象,如下图:
解决此问题的方法,在业务处理中重新指定中文字符集进行编码即可解决。最简单的操作就是加入一个字符编码的过滤器,即使Web容器的编码格式不支持中文,但经过过滤器进行转码,所以可以避免中文乱码的产生,如图:
eg:实现图书信息的添加功能,并创建字符编码过滤器,避免中文乱码现象的产生
(1)创建字符编码过滤器,名称为CharactorFilter类
import javax.servlet.*;
import java.io.IOException;
public class CharactorFilter implements Filter {
String encoding = null;
@Override
public void destroy(){
encoding = null;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (encoding != null){
request.setCharacterEncoding(encoding);
response.setContentType("text/html; charset=" + encoding);
}
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig config)throws ServletException{
encoding = config.getInitParameter("encoding");
}
}
在创建了过滤器之后,还需要对过滤器进行一定的配置,修改web.xml,如下:
<filter>
<filter-name>CharactorFilter</filter-name>
<filter-class>com.wang.yx.Filter.CharactorFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharactorFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
实例中使用”/*“来匹配所有请求(可以用正则表达式来满足需要过滤器的请求)
(2)创建名为AddServlet的类,继承HttpServlet,是处理添加图书信息请求的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;
import java.io.PrintWriter;
@WebServlet(name = "AddServlet")
public class AddServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
String id = request.getParameter("id");
String name = request.getParameter("name");
String author = request.getParameter("author");
String price = request.getParameter("price");
writer.print("<h2>图书信息添加成功</h2><hr>");
writer.print("图书编号:" + id + "<br>");
writer.print("图书名称:" + name + "<br>");
writer.print("作者:" + author + "<br>");
writer.print("价格:" + price + "<br>");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
在doGet()方法中调用doPost()方法,把业务处理代码写道doPost()方法中,或是相反,这样子无论Servlet接受的请求类型是GET还是POST,Servlet都会进行处理
编写Servlet类之后,也需要在web.xml中进行配置:
<servlet>
<servlet-name>AddServlet</servlet-name>
<servlet-class>com.wang.yx.servlet.AddServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AddServlet</servlet-name>
<url-pattern>/AddServlet</url-pattern>
</servlet-mapping>
<filter>
<filter-name>MyFliter</filter-name>
<filter-class>com.wang.yx.Filter.MyFilter</filter-class>
</filter>
(3)创建名为index.jsp页面,主要用于放置添加图书信息的表单,关键代码如下:
<body>
<form action="AddServlet" method="post">
<table align="center" border="1" width="350">
<tr>
<td class="2" align="center" colspan="2">
<h2>添加图书信息</h2>
</td>
</tr>
<tr>
<td align="right">图书编号:</td>
<td>
<input type="text" name="id">
</td>
</tr>
<tr>
<td align="right">图书名称:</td>
<td>
<input type="text" name="name">
</td>
</tr>
<tr>
<td align="right">作 者:</td>
<td>
<input type="text" name="author">
</td>
</tr>
<tr>
<td align="right">价 格:</td>
<td>
<input type="text" name="price">
</td>
</tr>
<tr>
<td class="2" align="center" colspan="2">
<input type="submit" value="添 加">
</td>
</tr>
</table>
</form>
</body>
运行实例,添加信息,即可查看运行结果。