JavaWeb之Filter&Listener

目录

Filter过滤器 

1.什么是过滤器?    

2.过滤器的使用场景    

3.如何编写过滤器?  

4.Filter接口的生命周期  

5.Filter接口中的相关类介绍

6.多个过滤器的执行顺序    

7.过滤器的四种拦截方式

Listener监听器

是什么

分什么

 1.application监听器  

 2.Session监听器  

         3.request监听器 


Filter过滤器 


1.什么是过滤器?
    Filter过滤器它是JavaWEB三大组件之一

(Servlet应用程序、Listener监听器、Filter过滤器)
    Filter过滤器它是JavaEE的规范,也就是接口。
    Filter过滤器它的作用:拦截请求,过滤响应
    它会在一组资源(jsp,servlet,.css,.html等)的前面执行

2.过滤器的使用场景
    a.防止未登录就进入界面
    b.控制应用编码
    c.过滤敏感词汇等场景

3.如何编写过滤器?
    a.自定义类实现Filter接口,重写接口中的抽象方法(3个)
    b.在web.xml中进行配置

<filter>
	<filter-name>DemoFilter</filter-name>
	<filter-class>com.zking.filter.DemoFilter</filter-class>
	</filter>
	<filter-mapping>
	<filter-name>DemoFilter</filter-name>
	<url-pattern>/as.do</url-pattern>
	</filter-mapping>
<url-pattern>/a.jsp</url-pattern>:你要拦截的内容是什么?
<url-pattern>/*.jsp</url-pattern>
<url-pattern>/*.do</url-pattern>
<url-pattern>/*</url-pattern>

4.Filter接口的生命周期
    void init(FilterConfig)
    * 创建之后,马上执行:Filter会在服务器启动时就创建
    void destory()
    * 销毁之前执行!在服务器关闭时销毁
    void doFilter(ServletRequest,ServletResponse,FilterChain)
    * 每次过滤器时都会执行

5.Filter接口中的相关类介绍

    FilterConfig---->与ServletConfig相似
    * 获取初始化参数:getInitParameter
    * 获取过滤器名称:getFilterName
    * 获取application:getServletContext

    FilterChain
    * doFilter(ServletRequest,ServletResponse):放行请求

6.多个过滤器的执行顺序
    过滤器的执行顺序和url-pattern标签匹配的精确程度无关,只和他们的filter-mapping标签在web.xml文件中的顺序有关,靠上的配置的先执行。

 

 

7.过滤器的四种拦截方式(了解)
    REQUEST、FORWARD、INCLUDE、ERROR。

    REQUEST:直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是REQUEST;
    

FORWARD:转发访问执行过滤器。包括RequestDispatcher#forward()方法、<jsp:forward>标签都是转发访问;

    INCLUDE:包含访问执行过滤器。包括RequestDispatcher#include()方法、<jsp:include>标签都是包含访问;
    

ERROR:当目标资源在web.xml中配置为<error-page>中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。

    可以在<filter-mapping>中添加0~n个<dispatcher>子元素,来说明当前访问的拦截方式。


例子:
      

 <filter-mapping>
    
            <filter-name>myfilter</filter-name>
    
            <url-pattern>/b.jsp</url-pattern>
    
            <dispatcher>REQUEST</dispatcher>
    
            <dispatcher>FORWARD</dispatcher>

        </filter-mapping>

    这个配置中,b.jsp为目标资源。
    当直接请求b.jsp时,会执行过滤器。
    当转发到b.jsp页面时,会执行过滤器。

8.案例
    1.自动登录

package com.zking.servlet;

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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zking.utils.CookieUtil;

public class LoginFilter implements Filter {

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        if(req.getRequestURI().contains("login.jsp")) {//如果访问login,直接放行
            chain.doFilter(req, resp);
            return;
        }else {
            String username = (String) req.getSession().getAttribute("username");
            if(username==null) {//sesion中没有,去Cookie中找
                String val = CookieUtil.getCookieValByKey("auto", req);
                if(val!= null&& !val.equals("")) {
                    String name = val.split("_")[0];
                    String pass = val.split("_")[1];

                    if("admin".equals(name) && "123".equals(pass)) {//重新验证登录
                        req.getSession().setAttribute("username", name);//登录成功,放入Session,并放行
                        chain.doFilter(req, resp);
                        return;
                    }else {//验证失败,重新登录
                        resp.sendRedirect("login.jsp");
                    }
                }else {//Cookie中也没有,第一次访问,跳转登录页面
                    resp.sendRedirect("login.jsp");
                }
            }else {//session中有,放行
            	 chain.doFilter(req, resp);
                return;
            }
        }
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}


}

 

package com.zking.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginServlet extends HttpServlet {

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

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String auto = request.getParameter("auto"); // 是否自动登录

		if ("admin".equals(username) && "123".equals(password)) {// 如果登录成功
			request.getSession().setAttribute("username", username);
			if (auto == null) {// 未勾选自动登录
				Cookie cookie = new Cookie("auto", null);
				cookie.setMaxAge(60 * 60 * 24);// cookie有效时间
				response.addCookie(cookie);
			} else {// 勾选自动登录
				Cookie cookie = new Cookie("auto", username + "_" + password);
				cookie.setMaxAge(60 * 60 * 24);// cookie有效时间
				response.addCookie(cookie);
			}
			// 登录成功,跳转
			response.sendRedirect("index.jsp");
		} else {
			// 未登录成功,重新登录
			response.sendRedirect("login.jsp");
		}
	}

}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
欢迎你:${sessionScope.username }
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<html>
<head>
<meta charset = "utf-8" />
<title>Title</title>
</head>
<body>
	<form method="post" action="login.do">
		用户名:<input type="text" name="username"><br> 
		密码:<input type="text" name="password"><br> 
		自动登录:<input type="checkbox" name="auto" value="auto"><br> 
		<input type="submit" value="登录">
	</form>
</body>
</html>

 2.解决全站字符乱码(POST和GET中文编码问题)
    
    Filter传给后面Servlet的Request对象肯定不能是原先的,不然request.getParameter()还是会乱码

     

   public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
//        拦截所有的请求,解决全站中文乱码
//        指定request和response的编码
        request.setCharacterEncoding("utf-8");//只对消息体有效
        response.setContentType("text/html;charset=utf-8");
//        对request进行包装
        CharacterRequest characterRequest = new CharacterRequest(request);
        //        放行
        chain.doFilter(characterRequest, response);
    }
    public void init(FilterConfig fConfig) throws ServletException {
    }
 
}


 
//继承,默认包装类HttpServletRequestWrapper
 

class CharacterRequest extends HttpServletRequestWrapper{
    private HttpServletRequest request;
    public CharacterRequest(HttpServletRequest request) {
        super(request);
        this.request=request;
    }


//    子类继承父类一定会重写一些方法,此处用于重写

public String getParameter(String name) {
//		调用包装对象的getParameter()方法,获得请求参数
		String value = super.getParameter(name);
		if(value==null) {
			return null;
		}
//		判断请求方式
		String method = super.getMethod();
		if("get".equalsIgnoreCase(method)) {
			try {
				value = new String(value.getBytes("iso-8859-1"),"utf-8");
			}
			catch(UnsupportedEncodingException e){
				throw new RuntimeException(e);
			}
		}
//		解决乱码后返回结果
		return value;
	}


Listener监听器


是什么???

 主要功能是负责监听Web的各种操作,当相关的事件触发后将产生事件,并对事件进行处理。

分什么???

监听器分为3种:
    application监听器
    session监听器
    request监听器

事件:点击、移动、键盘、触摸

1.application监听器  servlet---ServletContext

  实现:ServletContextListener  (常用)
  重写: 

 //容器启动时调用
  public void contextInitialized(ServletContextEvent event){
    
  }
  //容器消毁时调用
  public void contextDestroyed(ServletContextEvent event){
    
  }

  ServletContextEvent事件方法:
    .getServletContext()    //取得ServletContext对象,即上下文

  例示:
    event.getServletContext().getContextPath();

2.Session监听器
  实现:HttpSessionListener  (偶尔用)
  重写:
 

 //session创建时调用
  public void sessionCreated(HttpSessionEvent event){
  }
  //session销毁时调用
  public void sessionDestroyed(HttpSessionEvent event){
  }

  HttpSessionEvent事件方法:
    .getSession()    //取得当前的session
    例示:
    event.getSession().getId();    //得到session的ID

  

  实现:HttpSessionAttributeListener (不用,性能差)
  重写:
  //增加属性时触发
  public void attributeAdded(HttpSessionBindingEvent event){
    
  }
  //删除属性时触发
  public void attributeRemoved(HttpSessionBindingEvent event){
    
  }
  //替换属性时触发
  public void attributeReplaced(HttpSessionBindingEvent event){
    
  }

 

 HttpSessionBindingEvent事件方法:
    .getSession()    //取得session
    .getName()    //取得属性的名称
    .getValue()    //取得属性的内容    

例示:
    event.getSession()    //取得session
    event.getName()        //取得属性的名称
    event.getValue()    //取得属性的内容

    

3.request监听器
  实现:ServletRequestListener (不用,性能差)
  重写:

  //请求开始时调用
  public requestInitialized(ServletRequestEvent event){
  }

  //请求结束时调用
  public requestDestroyed(ServletRequestEvent event){

  }

  ServletRequestEvent事件方法:
    .getServletRequest()    //取得ServletRequest对象
    .getServletContext()    //取得ServletContext对象

    例示:
    event.getServletRequest().getRemoteAddr();    //得到IP地址
    event.getServletContext().getContextPath();    //得到当前路径

=======================================================================
为什么说session监听器和request监听器一般都不用?
答:以request监听器为例,如果采用request监听,那就意味着每次请求都要触发一次监听,这大大降低了程率的效率,因此很少用。

=======================================================================
 

web.xml
<listener>
   <listener-class>com.listener.Application</listener-class>
</listener>

实例:监听在线人数
    
分析:创建一个会话就+1,销毁了会话则-1
      (在会话被创建时,往全局变量中+1;会话被关闭时,全局变量-1)
      服务器停止则移除 count
 

public class AppListrener implements ServletContextListener,HttpSessionListener {
    
    ServletContext app=null;
    
    //容器销毁时调用
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub
        System.out.println("容器销毁了");
        
    }
    //容器初始化时调用
    public void contextInitialized(ServletContextEvent sce) {
        // TODO Auto-generated method stub
        System.out.println("容器初始化了");
        app=sce.getServletContext();
        Integer count=0;
        app.setAttribute("cut", count);
        System.out.println(count+"___");
    }
    
    //session创建时调用
    public void sessionCreated(HttpSessionEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("session创建时调用");
        Integer count=(Integer)app.getAttribute("cut");
        
        if(count==null){
            count=0;
        }
        count++;
        System.out.println("创建时:"+count);
        app.setAttribute("cut", count);
    }
    
    //session销毁时调用
    public void sessionDestroyed(HttpSessionEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("session销毁时调用");
        Integer count=(Integer)app.getAttribute("cut");
        
        if(count==null){
            count=0;
        }
        count--;
        System.out.println("注销时:"+count);
        app.setAttribute("cut", count);
    }


web.xml

  <listener>
      <listener-class>com.servlet.AppListrener</listener-class>
  </listener>


http://193.168.2.224:8080/listenerDemo/index.jsp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值