监听器
作用
监听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中相关资源
没有配置过滤器之前
配置过滤器之后