JavaWeb中的异卵双胞胎——监听器与过滤器

时间:2022-07-22
本文章向大家介绍JavaWeb中的异卵双胞胎——监听器与过滤器,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

监听器与过滤器

监听器

作用

监听request、session、application三个域对象的创建,销毁和数据的变更

使用

1、创建一个普通java类实现指定的接口

public class MyListener implements ServletRequestListener{
	//监听Request对象的创建和销毁
	@Override
	public void requestDestroyed(ServletRequestEvent arg0) {
		System.out.println("requset对象被销毁了");
		
	}
	@Override
	public void requestInitialized(ServletRequestEvent arg0) {
		System.out.println("request对象被创建了");
		
	}
	}

2、在web.xml进行配置,使其生效(放在dispalyname标签的上面)

 <!-- 监听器的配置 -->
  <listener>
  	<listener-class>监听器所在java类的全限定类名(包名+类名)</listener-class>
  </listener>

示例:

监听器可以继承的的接口

1、ServletRequestListener

监听request的创建和销毁

 requestInitialized(ServletRequestEvent sre)
 requestDestroyed(ServletRequestEvent sre)

形参:

ServletRequestEvent可以获取当前监听到的request对象,对request对象的中的资源进行操作。

2、 ServletRequestAttributeListener

监听request作用域数据变更(添加移除替换)

attributeAdded(ServletRequestAttributeEvent srae)
attributeRemoved(ServletRequestAttributeEvent srae)
attributeReplaced(ServletRequestAttributeEvent srae)

形参:

ServletRequestAttributeEvent:可以获取当前被监听到的request中的数据。 getName(): 返回监听到的数据的键和getValue()返回监听的到的数据的值。

3、HttpSessionListener

监听session的创建和销毁

sessionCreated(HttpSessionEvent se)
sessionDestroyed(HttpSessionEvent se)

形参:

获取当前被监听到的session对象

4、HttpSessionAttributeListener

监听session的作用域数据变更

    attributeAdded(HttpSessionBindingEvent event)
    attributeRemoved(HttpSessionBindingEvent event)
    attributeReplaced(HttpSessionBindingEvent event)

形参:

获取当前监听到的session中的数据 getName()返回数据的键名 getValue()返回数据的值

5、ServletContextListener

监听application对象的创建和销毁

contextInitialized(ServletContextEvent sce)
contextDestroyed(ServletContextEvent sce)

形参:

获取application对象

6、ServletContextAttributeListener

监听application对象的数据变更

attributeAdded(ServletContextAttributeEvent event)
attributeRemoved(ServletContextAttributeEvent event)
attributeReplaced(ServletContextAttributeEvent event)

形参:

获取当前被监听的数据 getName()返回数据的键名,getValue()返回数据的值

案例:利用监听器实现在线用户的统计

1、后台代码的编写

package com.szxy.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyListener implements ServletContextListener,HttpSessionListener{

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		// TODO Auto-generated method stub
		
	}
	
	//监听application对象初始化的方法
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("MyListener.contextInitialized()");
		//设置一个计数器
		int count=0;
		//获取application对象
		ServletContext sc = sce.getServletContext();
		//将计数器放入application对象中
		sc.setAttribute("count", count);
		
	}
	
	//监听session对象创建的方法
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		System.out.println("MyListener.sessionCreated()");
		//获取application中的计数器
		ServletContext sc = se.getSession().getServletContext();
		int count = (int) sc.getAttribute("count");
		//计数器自增
		++count;
		//将其放到application中去
		sc.setAttribute("count", count);
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		System.out.println("MyListener.sessionDestroyed()");
		//获取application中的计数器
				ServletContext sc = se.getSession().getServletContext();
				int count = (int) sc.getAttribute("count");
				//计数器自减
				--count;
				//将其放到application中去
				sc.setAttribute("count", count);
	}
	
}

2、web.xml的配置

<!-- 配置监听器 -->
  <listener>
    <listener-class>com.szxy.listener.MyListener</listener-class>
  </listener>

过滤器

过滤器用于对用户请求进行拦截,对符合我们需求的资源进行放行处理

问题

目前我们访问Servlet,是可以直接进行访问的,没有进行任何防护。 可能会造成服务器资源的浪费,以及安全性不高。 我们希望真的在请求被Servlet处理之前,进行一次请求的校验,符合要求再调用对应Servlet进行请求处理

解决

使用过滤器

使用

1、创建一个普通java类并实现过滤器接口Filter

2、在web.xml中配置过滤器

<filter>
		<filter-name>配置的过滤器名称</filter-name>
		<filter-class>要配置的过滤器的全限定路径:包名.类名</filter-class>
</filter>
<filter-mapping>
		<filter-name>配置的过滤器名称</filter-name>
		<url-pattern>过滤器拦截请求地址的范围</url-pattern>
</filter-mapping>

示例

过滤器中的方法

doFilter方法

作用: 服务器在接收到浏览器发过来的请求后,先解析请求信息,创建对象request和response然后根据请求URL地址判断如果符合过滤器的过滤范围,则会调用过滤器中的doFilter来进行请求拦截,并将request和response对象作为实参传递给doFilter方法。我们可以在doFilter方法中声明过滤器拦截代码。

参数: ServletRequest:接收此次拦截的请求的request实参 ServletResponse:接收此次拦截的请求的response实参 FilterChain:可以进行请求放行 chain.doFilter(request, response);

init方法和destory方法

init方法:服务器启动时调用 destory方法:服务器关闭时调用 证明:过滤器的生命周期为从服务器开启到服务器关闭

过滤器之拦截范围配置

(见上图实例) 拦截所有: /* 拦截部分Servlet的请求: *.do 拦截指定Servlet的请求:和要拦截的指定的Servlet的url-pattern配置完全一致即可,例如:/my.do

注意: 多个过滤器拦截顺序 过滤器之间会出现多重拦截,web服务器根据Filter在web.xml中的注册顺序,决定先调用哪个Filter. 当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法,在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第二个filter,如果没有,则调用目标资源。

三种过滤器综合使用小案例

1)MyServlet(访问别名my .do)

2) 三个过滤器(MyFilter/MyFilter2/MyFilter3)

3) 运行结果

项目案例——判断用户是否登录

通过过滤器实现判断用户是否登录:如登录则进行登录资源放行,否则则会返回登录界面,防止用户通过url直接访问其他资源

1、新建一个UserLoginFilter类实现Filter接口(import javax.servlet.Filter;)

2、类的具体内容

package com.szxl.web.Filter.UserLoginFilter
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.HttpSession;

import com.bjsxt.pojo.Users;
/**
 * 用于判断用户是否登录
 * @author chy
 *
 */
public class UserLoginFilter implements Filter{

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

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain chain) throws IOException, ServletException {
		
		//获取用户访问的uri(统一资源标识符)
		HttpServletRequest req=(HttpServletRequest) arg0;
		String uri = req.getRequestURI();
		//判断当前访问的uri是否是用户登陆资源,如果是则放行
		//indexOf:比较uri这个字符串中是否存在login字符串。-1为indexOf的返回值,返回不到返回-1
		if (uri.indexOf("login")!=-1 || uri.indexOf("userlogin")!= -1) {
			chain.doFilter(arg0, arg1);
		}else {
			//用户是否登录的判断
			HttpSession session = req.getSession();
			Users user = (Users) session.getAttribute("user");
			if (user!=null && user.getUsername().length()>0) {
				chain.doFilter(arg0, arg1);//放行
			}else {
				req.setAttribute("msg", "请登录");
				req.getRequestDispatcher("/login").forward(arg0, arg1);
			}
		}
	}

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

}

注:session中必须要有名为user的对象,必须要有login.jsp页面(登录)以及userlogin(用户登陆的servlet的访问别名@RequestMapping("/userlogin"))

3、在web.xml中添加该过滤器

<!-- 定义判断用户是否登录的过滤器 -->
  	<filter>
			<filter-name>UserLoginFilter</filter-name>
			<filter-class>com.szxl.web.Filter.UserLoginFilter</filter-class>
	</filter>
	<filter-mapping>
			<filter-name>UserLoginFilter</filter-name>
			<url-pattern>/*</url-pattern>
	</filter-mapping>

4、测试该过滤器

不登录,直接访问index中相关资源

没有配置过滤器之前

配置过滤器之后