过滤器简介
但这还不是全部。您真的不认为 servlet 有那么简单,是吗?
除了我们已经分析过的 servlet 之外,还有所谓的“实用 servlet”——过滤器。它们与 servlet 非常相似,但它们的主要工作是帮助 servlet 处理请求。
过滤器就像秘书,而 servlet 就像导演。在文件到达主任办公桌之前,它会通过秘书的手。在主管签字后,它会再次交给秘书,例如已经作为外发信函。
这样的秘书可以拒绝对主管的某些请求(例如,垃圾邮件)。或者对他已知的问题给出标准答案(“导演不在位”)。等等。而且,可以有多个这样的秘书:一个可以一次性为所有董事过滤垃圾邮件,另一个可以在不同董事之间传递请求,等等。
过滤器的工作方式相同。
类 Filter、FilterChain、FilterConfig
过滤器与 servlet 非常相似,但有一些细微差别。要编写自己的过滤器,您需要继承自javax.servlet.Filter
.
过滤器也有方法init()
和destroy()
。service()
过滤器没有方法,而是有一个doFilter()
. 甚至有自己的类 FilterConfig。过滤器也被添加到 web.xml 文件中的 servlet 或通过 @WebFilter 注释。
方法列表:
方法 | 描述 | |
---|---|---|
1个 | init(FilterConfig config) |
过滤器初始化 |
2个 | destroy() |
过滤卸料 |
3个 | doFilter(ServletRequest , ServletResponse, FilterChain) |
请求处理(过滤) |
servlet 和过滤器有什么区别?
可以有多个过滤器,它们按顺序处理请求(和响应)。它们被组合成一个所谓的链 - 甚至有一个特殊的类FilterChain
。
在方法中处理完请求后,doFilter()
需要调用doFilter()
链中下一个过滤器的方法。例子:
public class MyFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
PrintWriter out = resp.getWriter();
out.print("Adding something before the body of the response");
chain.doFilter(req, resp); // call the next filter in the chain
out.print("Adding something after the body of the response");
}
public void destroy() {
}
}
实际上,您不能那样添加响应主体。形式上,过滤器和 servlet 是相互独立的,可以独立更改。它们可以由不同的开发人员在不同的时间编写。过滤器功能只是一个服务功能,例如:
- 记录所有传入的请求(和响应)
- 数据压缩
- 数据的加密(和解密)
- 请求数据验证
- 添加/删除所需的标题
- 重定向请求
- 访问控制(检查用户是否登录)
RequestDispatcher类
doFilter()
有时可能需要在方法中运行过滤器时调用另一个 servlet 。为此,容器有一个特殊的对象RequestDispatcher
。
您可以通过两种方式获得它:
- 在对象
HttpServletRequest
- 在对象
ServletContext
该对象可用于将现有请求重定向到另一个 servlet。例如,原来用户没有被授权,我们想给他看一个有授权的页面。好吧,或者服务器出现错误,我们想向用户显示一个错误页面:)
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = "/error.html";
ServletContext servletContext = this.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
requestDispatcher.forward(request, response);
}
}
您也可以RequestDispatcher
从过滤器调用。
public class MyFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
String path = "/error.html";
ServletContext servletContext = req.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
requestDispatcher.forward(req, resp);
}
public void destroy() {
}
}
注意请求会在方法中处理,使用后forward()
不需要再调用。doFilter()
RequestDispatcher
重定向和转发的比较
还有一点很重要。如果你想将用户重定向到你的 servlet 中的另一个 URI,那么你可以通过两种方式做到这一点:
redirect
forward
我们已经对它们进行了分析,但为了方便我再说一遍。
当您通过调用重定向response.sendRedirect("link")
时,服务器会向浏览器(客户端)发回响应302
和您指定的链接。浏览器在分析服务器响应后,会下载您传递的链接。即,浏览器中的链接更改为新链接。
如果您通过 call转发requestDispatcher.forward()
,则会在容器内发出一个新请求,并且您的 servlet 会将其响应发送给浏览器(客户端)作为您的 servlet 的响应。在这种情况下,浏览器收到来自新 servlet 的响应,但浏览器中的链接没有改变。
GO TO FULL VERSION