Filter过滤器是一种对客户端访问的过滤技术,简单来说就是我们浏览器访问服务器文件时,如果设置了特定的过滤配置,则会先经过过滤器,然后再将请求放给服务器去执行,最常见的就是我们过滤用户是否登录的使用。
listener监听器,见名得意,他就是起到一个监听的作用,主要是用来监听web应用的创建和销毁,以及他们attribute的创建、移除和更新等。 当然也包括用来监听session、request的生命周期以及他们attribute的动态。
一:Filter过滤器
这里我们以过滤器验证用户是否登录为例,进行解释。
首先完整的使用Filter我们需要在web.xml中配置filter的相关信息,告诉服务器我要过滤什么请求还是所有请求都过滤。然后映射到过滤器的类文件中。
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这里配置的是过滤所有请求,当然也可以针对有一个或者某一类请求进行过滤。例如*.mml那所有的.mml结尾的请求都会过滤到过滤器中去处理。
2. 然后新建FirstFilter类文件,需要实现Filter接口,并重写该接口的三个方法。
执行销毁方法:destory()、
执行过滤操作的方法:doFilter()、
初始化方法:init()。
其中doFilter()方法使我们过滤器执行实际过滤过程的方法,我们的实际业务逻辑就是写在这个方法里面的。该方法中有三个参数。
init()方法是过滤器的初始化方法,他跟servlet的init方法不一样,servlet需要配置自启动才会随着tomcat的启动执行init方法。二Filter的init方法一定会随着tomcat的启动而执行该方法的。
在这里我们通过该过滤器打印出一句话,来验证当我们请求时,会执行过滤器操作。代码如下:
//拦截器与servlet的执行顺序,当访问一个servlet请求时,先对servlet进行实例化、初始化、进入过滤器,
//执行过滤器的过滤,过滤器放行之后,再执行servlet的service方法。
public class FirstFilter implements Filter {
@Override
public void destroy() {
}
//执行拦截的方法
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String url = request.getRequestURI().toString();
System.out.printf("访问了 %s%n",url);
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
//拦截器的init初始化方法一定会随着tomcat的启动而启动,不需要配置
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
因为doFilter方法中的参数是servletRequest类型的,我们先把参数转化成HttpServletRequest类型的,然后获取到请求的URL,打印在控制台。通过chain.doFilter(request,response)这个方法,放行该请求,他就可以访问服务器上的资源了。代表着过滤器完成了过滤。
此时我们启动tomcat,请求一个地址,就会看到控制台上打印了我们输出的URL地址。
这就是简单使用过滤器的过程,下面我们在doFilter方法中加入验证登录的过滤逻辑。
3. 验证用户是否登录,我们的核心思想就是
用户打开浏览器访问该网址(此时服务器自动创建一个session对象),当用户登录并验证成功之后,会在session中创建一个key为login的值为"yes"的键值对,
然后如果用户请求的是login.jsp或者login结尾的登录页面,过滤器放行。否则就判断session存在login的值是否为空,如果为空,说明用户没有登录过,就跳转到登录页面,如果不为空,则放行。代码如下:
先是login的servlet验证:如果验证成功,就session中存一个键值对。
public class Login extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
if("root".equals(request.getParameter("userName")) && "root".equals(request.getParameter("password"))) {
request.getSession().setAttribute("user", request.getParameter("userName"));
response.sendRedirect("heroList");
}else {
response.sendRedirect("login.html");
}
}
}
然后是Filter过滤器的逻辑:
public class FirstFilter implements Filter {
//执行拦截的方法
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String url = request.getRequestURI().toString();
System.out.printf("访问了 %s%n",url);
request.setCharacterEncoding("UTF-8");
if(url.endsWith("login.html") || url.endsWith("login")) {
chain.doFilter(request, response);
return;
}
String isUser = (String)request.getSession().getAttribute("user");
if(null == isUser || "" == isUser) {
response.sendRedirect("login.html");
return;
}
chain.doFilter(request, response);
}
}
这样设置完成之后,我们打开浏览器,如果先访问heroList请求,则过滤器没有获取到session中的值,会调到登录页面,直到我们登录验证通过了,session中才会存入值,才会通过过滤器的已经登录的验证。
二:listener监听器:
1. 首先也需要在web.xml中告诉服务器设置了监听类:
<listener>
<listener-class>listener.OnlineNumberListener</listener-class>
<listener-class>listener.RequestListener</listener-class>
<listener-class>listener.SessionListener</listener-class>
<listener-class>listener.SessionListenerAttrute</listener-class>
</listener>
2. 首先新建RequseListener用来监听request的生命周期和attribute的动态。代码如下:如果创建了reques对象就会执行该类中的对应的方法(相当于发起一次请求,就会执行该方法,因为request对象是请求对象,每重新发起请求都会创建一个request),创建attribute也一样。
package listener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class RequestListener implements ServletRequestListener, ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent arg0) {
System.out.println("创建了attribute:");
System.out.println("name:"+arg0.getName());
System.out.println("value:"+arg0.getValue());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent arg0) {
syso:监听attribute的移除
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent arg0) {
syso:监听attribute的替换
}
@Override
public void requestDestroyed(ServletRequestEvent arg0) {
syso:监听request的销毁
}
@Override
public void requestInitialized(ServletRequestEvent arg0) {
System.out.println("创建了Request");
}
}
3. 新建SessionListener、SessionListenerAttrute类监听session和attribute的动态,因为session比较特殊,需要用两个监听器分别来监听。代码如下:
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("监听到session创建:Id是"+arg0.getSession().getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
}
}
public class SessionListenerAttrute implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent arg0) {
System.out.println("监听到创建了session的attribute,是:"+arg0.getName()+arg0.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent arg0) {
System.out.println("******************退出了登录***********************");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent arg0) {
}
}
使用session的创建和销毁可以模糊的统计在线人数,因为打开浏览器访问页面,就会创建session,也就是一次会话,就相当于一个在线人数,可以用作粗略统计。
感谢阅读!