一、Filter过滤器概述
- Filtert概述
Filter技术,即过滤器技术,是Servlet三大核心技术之一。
主要用于拦截请求进行过滤操作。
可以实现权限控制、全站乱码解决、压缩响应等功能。
过滤器可以拦截对资源的访问,拦截之后,可以控制访问是否放行,如果放行还可以在访问之前或之后做一些额外的操作。
过滤器可以配置多个,多个过滤器之前采用责任链模式,依次进行拦截。只有所有过滤器都通过,才可以访问到最终的资源。

- 过滤器开发
a.开发Filter的步骤
i.写一个类实现Filter接口
ii.在web.xml中配置Filter
b.写一个类实现Filter接口
Filter接口
| Method Summary | |
|---|---|
| void | destroy() Called by the web container to indicate to a filter that it is being taken out of service.销毁的方法,当filter在web容器中被销毁时会调用此方法 |
| void | doFilter(ServletRequest request, ServletResponse response, FilterChain chain) The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.当有请求访问资源被当前过滤器拦截时,此方法执行。request 代表当前拦截下来的请求对象response代表当前拦截下来的响应对象chain代表当前整个过滤器链 提供了doFilter()方法,可以放行过滤器 |
| void | init(FilterConfig filterConfig) Called by the web container to indicate to a filter that it is being placed into service.初始化的方法,当filter在web容器中被初始化时会调用此方法.filterConfig 代表当前Filter在web.xml中的配置信息 |
案例:自定义一个过滤器
package cn.tedu.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter01 implements Filter {
/**
* 服务器启动或web应用初始化时 过滤器被创建
* 创建出来之后立即调用init方法执行初始化操作
* 之后过滤器对象一直被保留在服务器内部 为后续过滤器操作服务
*
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("##MyFilter01..init..");
}
/**
* 在存活期间每次拦截到对资源的访问 都会造成doFilter方法的执行可以在这个方法中完成拦截逻辑
* 过滤器默认拦截对资源的方法不允许通过
* 可以手工调用chain.doFilter()方法来放行对资源的访问
* 放行之后执行过滤器链中的下一个过滤器,如果没有下一个过滤器就访问到目标资源
* @param request
* @param response
* @param chain
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("##MyFilter01..doFilter..");
chain.doFilter(request,response);
}
/**
* 直到服务器关闭或web应用移除出容器时
* 随着应用的销毁 过滤器对象被销毁
* 在销毁之前 执行destory方法 进行善后工作
*/
@Override
public void destroy() {
System.out.println("##MyFilter01..destory..");
}
}
c.在web.xml中配置Filter
在web.xml中配置过滤器的过程非常类似于配置一个Servlet
要通过< filter>< filter-mapping>标签实现
其中< filter-mapping>中可以通过< servlet-name>或< url-pattern>
< servlet-name>可以配置要拦截哪个名字的Servlet
< url-pattern>可以配置要拦截哪个url路径
一个web资源也可以被多个过滤器拦截,拦截顺序取决于过滤器的< filter-mapping>在web.xml中的配置顺序。
案例:配置过滤器
<!--配置过滤器-->
<filter>
<filter-name>MyFilter01</filter-name>
<filter-class>cn.tedu.filter.MyFilter01</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter01</filter-name>
<servlet-name>MyServ01</servlet-name>
<url-pattern>/MyServlet02</url-pattern>
<url-pattern>/img/*</url-pattern>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
-
过滤器的生命周期
当服务器启动web应用初始化时,web应用中的过滤器对象被创建出来
创建出来之后立即执行init方法进行初始化
之后一直驻留在内存中为后续的拦截进行服务
拦截到任何资源都会执行doFilter方法执行拦截
可以在doFilter方法中开发拦截逻辑
过滤器默认拦截不放行,可以通过调用FilterChain的doFilter方法来放行访问
也可以在放行之前和之后执行一些额外操作
直到web应用移除出容器时,随着web应用的销毁过滤器对象被销毁
在销毁之前会调用destory方法执行善后工作 -
多个过滤器执行过程
多个过滤器执行的先后顺序取决于过滤器的的配置顺序
先配置的先拦截先执行过滤
多个过滤器的执行过程,采用了责任链模式,非常类似于方法调用的过程,每当调用chain.doFilter()都会执行后续资源,后续资源执行过后,在返回到当前过滤器执行chain.doFilter()之后的内容。

二、FilterConfig
-
FilterConfig概述
FilterConfig是代表过滤器在web.xml中配置的对象 -
FilterConfig功能
获取过滤器名称

b.获取过滤器中配置的初始化参数

c.获取ServletContext对象

三、Filter案例 - 改造EasyMall
- 全站乱码解决过滤器
web应用中,获取请求参数和发送响应数据时都有可能产生乱码,需要手动解决。
与其在每个Servlet中单独解决乱码,不如开发一个过滤器拦截所有资源,统一进行乱码解决。
a.开发过滤器类
package cn.tedu.filter;
import javax.servlet.*;
import java.io.IOException;
/**
*全站乱码解决过滤器
*/
public class EncodingFilter implements Filter {
private FilterConfig config = null;
@Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String encoding = config.getInitParameter("encoding");
//1.解决请求乱码
request.setCharacterEncoding(encoding);
//2.解决响应乱码
response.setContentType("text/html;charset="+encoding);
//3.放行资源
chain.doFilter(request,response);
}
@Override
public void destroy() {
this.config = null;
}
}
b. 配置该Filter,拦截所有的资源
<!--全站乱码解决过滤器-->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>cn.tedu.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 30天内自动登录过滤器

a. 改造LoginServlet
package cn.tedu.web;
import cn.tedu.domain.User;
import cn.tedu.exception.MsgException;
import cn.tedu.service.UserService;
import cn.tedu.utils.MD5Utils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.net.URLEncoder;
/**
* 登录
*/
@WebServlet(urlPatterns = "/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.解决乱码
//request.setCharacterEncoding("utf-8");
//response.setContentType("text/html;charset=utf-8");
//1.获取用户名密码
String username = request.getParameter("username");
String password = MD5Utils.md5(request.getParameter("password"));
//####记住用户名
if("true".equals(request.getParameter("remname"))){
//--创建cookie
Cookie remnameC = new Cookie("remnamec", URLEncoder.encode(username,"utf-8"));
//--指定MaxAge
remnameC.setMaxAge(60 * 60 * 24 * 30);
//--指定Path
remnameC.setPath(request.getContextPath());
//--发送cookie
response.addCookie(remnameC);
}else{
//--创建cookie
Cookie remnameC = new Cookie("remnamec", "");
//--指定MaxAge
remnameC.setMaxAge(0);
//--指定Path
remnameC.setPath(request.getContextPath());
//--发送cookie
response.addCookie(remnameC);
}
//####记住用户名
//2.调用Service完成登录
try{
UserService userService = new UserService();
User user = userService.login(username,password);
//3.登录
HttpSession session = request.getSession();
session.setAttribute("user",user);
//###30天内自动登录
if("true".equals(request.getParameter("autologin"))){
//发送cookie保存用户名密码
String cv = URLEncoder.encode(username+"#"+password,"utf-8");
Cookie autologinc = new Cookie("autologin",cv);
autologinc.setMaxAge(60 * 60 * 24 * 30);//设定保存时长,30天 autologinc.setPath(request.getContextPath());//设定访问哪个路径及其子孙路径带着cookie回来
response.addCookie(autologinc);
}
//###30天内自动登录
//3.回主页
response.sendRedirect(request.getContextPath()+"/index.jsp");
return;
}catch (MsgException e){
//3.登录失败回登录页面提示
request.setAttribute("msg",e.getMessage()); request.getRequestDispatcher("/login.jsp").forward(request,response);
return;
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
b. 开发AutoLoginFilter
package cn.tedu.filter;
import cn.tedu.domain.User;
import cn.tedu.exception.MsgException;
import cn.tedu.service.UserService;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.URLDecoder;
public class AutologinFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
//1.未登录才做自动登录
HttpSession session = req.getSession();
if(session.getAttribute("user")==null){
//2.带了自动登录cookie才做自动登录
Cookie[] cs = req.getCookies();
Cookie findC = null;
if(cs!=null){
for(Cookie c : cs){
if("autologin".equals(c.getName())){
findC = c;
break;
}
}
}
if(findC!=null){
//3.自动登录cookie中的用户名密码正确才做自动登录
String v = URLDecoder.decode(findC.getValue(),"utf-8");//孙悟空#123
String username = v.split("#")[0];
String password = v.split("#")[1];
UserService userService = new UserService();
try{
User user = userService.login(username,password);
//--未登录、带了自动登录cookie、自动登录cookie中的用户名密码正确,自动登录
session.setAttribute("user",user);
}catch (MsgException e){
//--自动登录中的用户名密码不正确,不自动登录
}
}
}
//--无论是否自动登录,都放行资源
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
<!--30天内自动登录过滤器-->
<filter>
<filter-name>AutologinFilter</filter-name>
<filter-class>cn.tedu.filter.AutologinFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AutologinFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
c. 改造LogoutServlet
需要在登出操作时,删除30天内自动登录cookie
package cn.tedu.web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.net.URLEncoder;
/**
* 登出
*/
@WebServlet(urlPatterns = "/LogoutServlet")
public class LogoutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.杀死session
HttpSession session = request.getSession();
session.invalidate();
//##删除30天内自动登录cookie
Cookie autologinc = new Cookie("autologin","");
autologinc.setPath(request.getContextPath());
autologinc.setMaxAge(0);
response.addCookie(autologinc);
//##删除30天内自动登录cookie
//2.重定向回主页
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
本文详细介绍了JavaWeb中的Filter过滤器技术,包括过滤器的概述、FilterConfig的使用,以及在EasyMall项目中应用过滤器解决全站乱码问题和实现30天内自动登录的功能。过滤器作为Servlet三大核心技术之一,主要负责拦截请求并进行过滤操作,如权限控制、乱码处理和响应压缩等。在web.xml中配置多个过滤器时,它们按照配置顺序依次执行,采用责任链模式。
1177

被折叠的 条评论
为什么被折叠?



