0%

过滤器和监听器

过滤器和监听器


过滤器

问题

Servlet的作用是针对浏览器发起的请求,进行请求的处理。通过Servlet技术我们可以灵活的进行请求的处理,但是我们不但要对请求进行处理,我们还需要对服务器的资源进行统一的管理,比如请求编码格式的统一设置,资源的统一分配等,这个时候应该怎么办呢?

解决

使用过滤器

作用

对服务器资源进行管理

保护servlet

使用

Filter接口

​ 作用:

​ 对服务器接受的请求资源和响应给浏览器的资源进行管理;保护servlet

​ 使用:

  1. 创建一个实现了Filter接口的普通java类

  2. 复写接口的方法

    init方法:服务器启动即执行。资源初始化

    doFilter方法:拦截请求的方法,在此方法中可以对资源实现管理。(注:需手动对请求放行--chain.doFilter(req,resp))

    destroy()方法:服务器关闭执行。

  3. 在web.xml中配置过滤器(或用注解的方式)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;

    @WebFilter(filterName = "TestFilter",urlPatterns = "/*")
    public class TestFilter implements Filter {
    public void destroy() {
    System.out.println("destroy");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    chain.doFilter(req, resp);
    System.out.println("doFilter");
    //放行
    chain.doFilter(req,resp);
    System.out.println("doFilter2");
    }

    public void init(FilterConfig config) throws ServletException {
    System.out.println("init");
    }

    }
  4. 过滤器的生命周期:

    服务器启动到服务器关闭

  5. 总结:

    过滤器由程序员声明和配置,服务器根据请求中的uri信息调用

  6. 执行:

    浏览器发起请求到服务器,服务器接收到请求后,根据URI信息在web.xml中找到对应的过滤器执行doFilter方法,该方法对此请求进行处理后如果符合要求则放行。放行后如果还有符合要求的过滤则继续进行过滤,找到执行对应的servlet进行请求处理。servlet对请求处理完毕后,也就service方法结束了。还需继续返回相应的doFilter方法继续执行。

Filter过滤器的配置

urlPatterns:/*-->表示拦截所有的请求

urlPatterns:*.do-->表示拦截所有以.do结尾的请求。一般是用来进行模块拦截处理。

urlPatterns:/ts-->表示拦截指定url的请求。针对某个servlet的请求进行拦截,保护servlet。

案例

统一管理字符编码

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
31
32
33
34
35
36
37
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.http.HttpRequest;

@WebFilter(filterName = "TestFilter",urlPatterns = "/*")
public class TestFilter implements Filter {
public void destroy() {
}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
chain.doFilter(req, resp);
System.out.println("doFilter");
//设置编码格式
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//判断session
HttpSession hs = ((HttpServletRequest)req).getSession();
if(hs.getAttribute("user")==null){
((HttpServletResponse)resp).sendRedirect("/login.jsp");
}else{
//放行
chain.doFilter(req,resp);
}

System.out.println("doFilter2");

}

public void init(FilterConfig config) throws ServletException {

}

}

权限管理

资源管理(统一水印,和谐词汇等等)

监听器

问题

使用作用域对象时,对于其具体流程,比如该对象是什么时候创建和销毁的,数据是什么时候存取、改变和删除的,我们是无法看到的,因而无法在指定的时机对其进行操作。

解决

使用监听器

概念

Servlet监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext、HttpSession和ServletRequest等域对象的创建和销毁事件,以及监听这些域对象中属性发生修改的事件。

监听对象

Request

Session

Application

监听内容

创建、销毁、属性改变事件

监听作用

在事件发生之前、之后进行一些处理,比如统计在线人数

使用

  1. 创建一个实现了指定接口的java类

    监听request-->ServletRequestListener(reqestInitialized、reqestDestroyed)-->监听request对象的创建和销毁

    监听request-->ServletRequestAttributeListener(attributeAdded、attributeRemove、attributeReplaced)-->监听request作用域数据的变更

    注意:形参可以获取被监听的数据-->sre.getServletRequest()获取监听的request对象、sare.getName()获取键、sare.getValue()获取值

    监听session-->HttpSessionListener()、HttpSessionAttributeListener(),相关函数与request类似

    监听application-->ServletContextListener()、ServletContextAttributeEvent(),相关函数与request类似

  2. 在web.xml中配置监听器类(或使用注解)

案例

统计当前在线人数

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
@WebListener()
public class MyListener implements HttpSessionListener, ServletContextListener {

@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
//获取ServletContext对象
ServletContext sc = httpSessionEvent.getSession().getServletContext();
//获取在线统计人数的变量
int count = (int) sc.getAttribute("count");
//存储
sc.setAttribute("count",++count);
}

@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
//获取ServletContext对象
ServletContext sc = httpSessionEvent.getSession().getServletContext();
//获取在线统计人数的变量
int count = (int) sc.getAttribute("count");
//存储
sc.setAttribute("count",--count);
}
//application对象初始化
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//获取application
ServletContext sc = servletContextEvent.getServletContext();
//在application对象存储变量用来存储统计磁在线人数
sc.setAttribute("count",0);
}

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {

}
}