Filter与Listener

Filter

Filter,过滤器,顾名思义,是用来过滤网站数据的:

  • 处理中文乱码
  • 登录验证
  • ……

实现Filter接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import java.io.IOException;

public class CharacterEncodingFilter implements Filter {

// web服务器启动时,初始化过滤器,监听过滤对象出现
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化CharacterEncodingFilter");
}

/**
* 特定路径的请求(在web.xml中设置)都会触发该代码
*
* @param request 请求
* @param response 响应
* @param chain 让请求和响应继续通行的过滤链
* @throws IOException IOException
* @throws ServletException ServletException
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html");
System.out.println("CharacterEncodingFilter执行前");
// 过滤链,如果不执行这条语句,请求就会被完全拦截在Filter,没有后续处理
chain.doFilter(request, response);
System.out.println("CharacterEncodingFilter执行后");
}

// web服务器停止时,销毁过滤器
public void destroy() {
System.out.println("销毁CharacterEncodingFilter");
}
}

web.xml中配置Filter

1
2
3
4
5
6
7
8
9
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.hunter.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- 只要是 /servlet 路径下的任何请求,都会经过这个过滤器 -->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>

Listener

监听器有很多种,在GUI编程中经常使用。

以session监听器为例。

编写一个session监听器

要做的就是实现监听器的接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 统计网站在线人数:统计session
public class OnlineCountListener implements HttpSessionListener {
// 创建session就会触发这个方法
public void sessionCreated(HttpSessionEvent se) {
// ServletContext:保存的数据只在服务器中有效,从打开服务器到关闭服务器。
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("onlineCount");

if (onlineCount == null) {
onlineCount = 1;
} else {
onlineCount++;
}
ctx.setAttribute("onlineCount", onlineCount);
}

// 销毁session就会触发这个方法
public void sessionDestroyed(HttpSessionEvent se) {
// ServletContext:保存的数据只在服务器中有效,从打开服务器到关闭服务器。
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("onlineCount");

if (onlineCount == null || onlineCount <= 0) {
onlineCount = 0;
} else {
onlineCount--;
}
ctx.setAttribute("onlineCount", onlineCount);
}
}

web.xml中配置Listener

1
2
3
4
<!-- 注册监听器 -->
<listener>
<listener-class>com.hunter.listener.OnlineCountListener</listener-class>
</listener>

销毁Listener

  1. 手动销毁

    在销毁session的方法中,在合适位置添加 se.getSession().invalidate();即可。

  2. 自动销毁

    web.xml文件中添加标签 <session-config>

    1
    2
    3
    4
    <session-config>
    <!-- 设置自动过期时间 -->
    <session-timeout>1</session-timeout>
    </session-config>

Filter、Listener的常见应用

权限拦截

例如:用户登录之后才能进入主页,注销后就不能进入主页。

  1. 用户登录之后,向Session中放入用户的数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 获取前端请求的参数
    String username = req.getParameter("username");

    if (username != null && username.equals("admin")) {
    req.getSession().setAttribute(Constant.USER_SESSION, req.getSession().getId());
    resp.sendRedirect("/sys/success.jsp");
    } else {
    resp.sendRedirect("/error.jsp");
    }
  2. 进入主页时,判断用户是否已经登录(在过滤器中实现

    1
    2
    3
    4
    5
    6
    7
    8
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;

    // 如果session中没有用户成功登录的attributeName,就跳转到错误页面
    if (req.getSession().getAttribute(Constant.USER_SESSION) == null) {
    resp.sendRedirect("/error.jsp");
    }
    chain.doFilter(request, response);