第7章 Filter和Listener

1. Filter过滤器

通过Filter技术,可以在用户访问某个Web资源(如:JSP、Servlet、HTML、图片、CSS等)之前,对访问的请求和响应进行预处理,从而实现一些特殊功能。
例如,验证用户访问权限、记录用户操作、对请求进行重新编码、压缩响应信息等。

一个Web应用中,也可以部署多个过滤器,这些过滤器组成了一个过滤器链。过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求可以在这些过滤器之间进行传递,直到达到目标资源。


过滤器链

字符集过滤器
字符集过滤器在访问目标资源之前将请求和响应对象的字符集全部设置为utf-8。将原来每个servlet的doGet或doPost方法都要先设置字符集的代码统一在过滤器中完成,提升了代码的可维护性。

1. 编写过滤器类,实现javax.servlet.Filter接口并实现其中的方法

package com.neuedu.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class CharacterEncodingFilter implements Filter{

    @Override
    public void destroy() {
        System.out.println("字符集过滤器销毁");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //设置请求和响应的字符集
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        //放行请求,访问下一个过滤器或资源
        chain.doFilter(request, response);
    }
    @Override
    public void init(FilterConfig config) throws ServletException {
        System.out.println("字符集过滤器初始化");
    }
}

2. 注册并配置过滤器
2.5版本
在web.xml中完成注册和配置,其中url-pattern配置的是过滤器过滤的范围为/*,即为整个工程全部资源


  CharacterEncodingFilter
  com.neuedu.filter.CharacterEncodingFilter


  CharacterEncodingFilter
  /*

3.0版本
通过在类中添加注解来声明过滤器的范围

@WebFilter("/*")
public class CharacterEncodingFilter implements Filter{
...
}

防盗链过滤器
盗链是指在web应用中,用户未经授权访问了需要授权的资源。
比如

盗链演示

在访问user_list.jsp时需要判断用户是否通过正常业务流进入,此时用户必行经过了登录授权后才能访问,盗链没有经过登录业务,应该是不能访问页面的。
此时我们在过滤器中判断用户是否登录过即可,在以往的代码中,用户登录后会在session中记录用户的登录信息(online),我们判断session中是否存在这个信息,就可以知道当前的请求是否是经过授权的。
由于某些页面就是无需登录授权就可以访问的,比如login.jsp。所以此时不能将过滤器的过滤范围设置为/*,我们需要在路径中区分需要登录授权的资源和不需要登录授权的资源。

  • 将需要登录授权访问的JSP放入/jsp路径下。
  • 将需要登录授权访问的Servlet放入/servlet路径下。
package com.neuedu.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebFilter({"/jsp/*","/servlet/*"})
public class LoginDefanceFilter implements Filter {

    public void destroy() {
        System.out.println("防盗链过滤器销毁");
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //检测session中是否有online数据
        HttpServletRequest req = (HttpServletRequest)request;
        HttpSession session = req.getSession();
        Object o = session.getAttribute("online");
        if(o != null) {
            chain.doFilter(request, response);
        }else {
            HttpServletResponse resp = (HttpServletResponse)response;
            resp.sendRedirect(req.getContextPath()+"/login.jsp");
        }
    }

    public void init(FilterConfig fConfig) throws ServletException {
        System.out.println("防盗链过滤器初始化");
    }
}

2. Listner监听器

监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。
JavaWeb中的监听器主要监听的是各种作用域的生命周期和作用域内容变化。


各种监听器

统计在线人数
当用户登录后会在作用域中存入名字online的信息,当触发此事件时我们认为在线人数+1,当某个session销毁时我们认为在线人数-1。
监听器类

package com.neuedu.listener;

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class OnlineUserListener implements HttpSessionAttributeListener, HttpSessionListener {
    
    public static int count = 0;

    /**
     * 创建session对象时产生,服务器session内存开辟,客户端拥有JSESSIONID
     */
    public void sessionCreated(HttpSessionEvent arg0)  { 
         // TODO Auto-generated method stub
    }


    /**
     * 销毁session对象时产生,服务器回收内存,服务器超时,invalidate方法执行
     */
    public void sessionDestroyed(HttpSessionEvent ev)  { 
        if(count > 0) {
            count--;
        }
    }


    /**
     * 向session作用域中添加一个数据   setAttribute(key,value), key之前不存在
     */
    public void attributeAdded(HttpSessionBindingEvent ev)  { 
         if(ev.getName().equals("online")) {
             count++;
         }
    }


    /**
     * 从session作用域中移除一个数据  removeAttribute
     */
    public void attributeRemoved(HttpSessionBindingEvent arg0)  { 
         // TODO Auto-generated method stub
    }


    /**
     * 从session作用域中替换一个数据  setAttribute(key,value), key之前存在
     */
    public void attributeReplaced(HttpSessionBindingEvent arg0)  { 
         // TODO Auto-generated method stub
    }   
}

注册监听器
2.5版本


  com.neuedu.listener.OnlineUserListener

3.0版本

@WebListener
public class OnlineUserListener implements HttpSessionAttributeListener, HttpSessionListener{
  ...
}

main.jsp

<%@page import="com.neuedu.listener.OnlineUserListener"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




主页


    当前在线人数:<%=OnlineUserListener.count %>
    注销


登录功能

package com.neuedu.servlet;

import java.io.IOException;
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 javax.servlet.http.HttpSession;

import com.neuedu.po.EmployeesPO;
import com.neuedu.service.SystemService;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //验证登录
        String lname = request.getParameter("lname");
        String lpass = request.getParameter("lpass");
        
        //调用service
        SystemService ss = new SystemService();
        EmployeesPO po = ss.login(lname, lpass);
        
        //跳转
        if(po != null) {
            HttpSession session = request.getSession();
            session.setAttribute("online", po);
            response.sendRedirect(request.getContextPath()+"/jsp/main.jsp");
        }else {
            response.sendRedirect(request.getContextPath()+"/login.jsp");
        }
        
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

注销功能

package com.neuedu.servlet;

import java.io.IOException;
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 javax.servlet.http.HttpSession;

@WebServlet("/haha/logoff")
public class LogoffServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.invalidate();
        response.sendRedirect(request.getContextPath()+"/login.jsp");
        
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }
}

你可能感兴趣的:(第7章 Filter和Listener)