百味皆苦 java后端开发攻城狮

java复习过滤器和监听器


过滤器

  • 过滤器Filter就像一个一个哨卡,用户的请求需要经过Filter,并且可以有多个过滤器

编写

package filter;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

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;

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;
		//获取来路用户的ip地址
		String ip = request.getRemoteAddr();
        //获取用户访问的页面地址
		String url = request.getRequestURL().toString();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date d = new Date();
		String date = sdf.format(d);

		System.out.printf("%s %s 访问了 %s%n", date, ip, url);
        //过滤器放行,表示继续运行下一个过滤器,或者最终访问的某个servlet,jsp,html等等
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		//与Servlet需要配置自启动才会随着tomcat的启动而执行init()方法不一样。
        //Filter一定会随着tomcat的启动自启动。
        System.out.println("First Filter init()");
	}

}

web.xml

	<filter>
		<filter-name>FirstFilter</filter-name>
		<filter-class>filter.FirstFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>FirstFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

  • Filter是web应用非常重要的一个环节,如果Filter启动失败,或者本身有编译错误,不仅这个Filter不能使用整个web应用会启动失败,导致用户无法访问页面
  • 在启动tomcat过程中,也会看到这样的字样: 严重: Context [] startup failed due to previous errors这常常用于提示Filter启动失败了

中文处理

package filter;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

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;

public class EncodingFilter 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;

		request.setCharacterEncoding("UTF-8");

		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}

	<filter>
		<filter-name>EncodingFilter</filter-name>
		<filter-class>filter.EncodingFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>EncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

登录验证

package filter;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

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;

public class AuthFilter 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 uri = request.getRequestURI();
		if (uri.endsWith("login.html") || uri.endsWith("login") || uri.endsWith(".css") 			|| uri.endsWith(".js") || uri.endsWith(".jpg")) {
			chain.doFilter(request, response);
			return;
		}

		String userName = (String) request.getSession().getAttribute("userName");
		if (null == userName) {
			response.sendRedirect("login.html");
			return;
		}

		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}

	<filter>
		<filter-name>AuthFilter</filter-name>
		<filter-class>filter.AuthFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>AuthFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
		

监听器

  • Listener 的作用是用于监听 web应用的创建和销毁,以及在其上attribute发生的变化。
  • web应用即ServletContext对象(jsp的隐式对象application)
  • 除了对web应用的监听外,还能监听session和request的生命周期,以及他们的attribute发生的变化。

context

  • 对Context的监听分生命周期的监听,和Context上Attribute变化的监听两种。
  • 编写 ContextListener
package listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ContextListener implements ServletContextListener {
	//对应当前web应用的销毁
	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		System.out.println("web 应用销毁  ");
	}
	//对应当前web应用的初始化
	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		System.out.println("web 应用初始化 ");

	}
}

  • 配置 web.xml
	<listener>
		<listener-class>listener.ContextListener</listener-class>
	</listener>

在启动tomcat以及当前web应用重载的时候可以观察到
web应用的自动重载需要如下前提:
1. 配置: server.xml中对应的<context配置 的属性 @reloadable="true"
2. 某个servlet 发生了变化,导致这个web应用自动重启

  • 编写 ContextAttributeListener
package listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

public class ContextAttributeListener implements ServletContextAttributeListener {
	//监听属性的增加
	@Override
	public void attributeAdded(ServletContextAttributeEvent e) {
		System.out.println("增加属性 ");
		System.out.println("属性是" + e.getName());
		System.out.println("值是" + e.getValue());

	}
	//监听属性的移除
	@Override
	public void attributeRemoved(ServletContextAttributeEvent e) {
		// TODO Auto-generated method stub
		System.out.println("移除属性 ");
	}
	//监听属性的替换
	@Override
	public void attributeReplaced(ServletContextAttributeEvent e) {
		// TODO Auto-generated method stub
		System.out.println("替换属性");
	}

}

	<listener>
		<listener-class>listener.ContextAttributeListener</listener-class>
	</listener>

  • 测试

  • testContext.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
	application.setAttribute("test", 1);
	application.setAttribute("test", 2);
	application.removeAttribute("test");
%>

session

  • 对Session的监听分生命周期的监听,和Session上Attribute变化的监听两种。
  • 编写 SessionListener
package listener;

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

public class SessionListener implements HttpSessionListener {
	//表示session创建的时候执行
	@Override
	public void sessionCreated(HttpSessionEvent e) {

		System.out.println("监听到 session 创建, sessionid 是: " + e.getSession().getId());
	}
	//表示session销毁的时候执行
	@Override
	public void sessionDestroyed(HttpSessionEvent e) {

		System.out.println("监听到 session 销毁, sessionid 是: " + e.getSession().getId());
	}
}

  • 配置web.xml
	<listener>
		<listener-class>listener.SessionListener</listener-class>
	</listener>

  • 测试

  • 编写 SessionAttributeListener
package listener;

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

public class SessionAttributeListener implements HttpSessionAttributeListener {
	//当在session中增加属性时触发
	@Override
	public void attributeAdded(HttpSessionBindingEvent e) {

		System.out.println("session 增加属性 ");
		System.out.println("属性是" + e.getName());
		System.out.println("值是" + e.getValue());

	}
	//当在session中移除属性时触发
	@Override
	public void attributeRemoved(HttpSessionBindingEvent e) {
		// TODO Auto-generated method stub
		System.out.println("session 移除属性 ");

	}
	//当替换session中的属性时触发
	@Override
	public void attributeReplaced(HttpSessionBindingEvent e) {
		// TODO Auto-generated method stub
		System.out.println("session 替换属性 ");

	}
}

	<listener>
		<listener-class>listener.SessionAttributeListener</listener-class>
	</listener>	

  • testSession.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
	session.setAttribute("test", 1);
	session.setAttribute("test", 2);
	session.removeAttribute("test");
%>

  • 测试

request

  • 对Request的监听分生命周期的监听,和Request上Attribute变化的监听两部分。
  • 编写 RequestListener
package listener;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class RequestListener implements ServletRequestListener, ServletRequestAttributeListener {
	//当本次请求结束的时候触发
	@Override
	public void requestDestroyed(ServletRequestEvent arg0) {
		System.out.println("销毁了一个Request ");
	}
	/**
	当新创建了一个Request的时候触发,只要访问了服务端的资源,就会创建一个Request,无论是jsp,servlet还	 是html
	*/
	@Override
	public void requestInitialized(ServletRequestEvent arg0) {
		System.out.println("创建了一个Request ");
        
	}
	//当有新增属性时触发
	@Override
	public void attributeAdded(ServletRequestAttributeEvent e) {
		System.out.println("request 增加属性 ");
		System.out.println("属性是" + e.getName());
		System.out.println("值是" + e.getValue());
	}
	//当有移除属性时触发
	@Override
	public void attributeRemoved(ServletRequestAttributeEvent arg0) {
		System.out.println("request 移除属性 ");
		
	}
	//当有替换属性时触发
	@Override
	public void attributeReplaced(ServletRequestAttributeEvent arg0) {
		System.out.println("request 替换属性 ");
		
	}
}

	<listener>
		<listener-class>listener.RequestListener</listener-class>
	</listener>	

  • testRequest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
	request.setAttribute("test", 1);
	request.setAttribute("test", 2);
	request.removeAttribute("test");
%>

  • 测试

在线人数

  • HTTP协议是短链接的,所以无法在服务端根据建立了多少连接来统计当前有多少人在线
  • 不过可以通过统计session有多少来估计在线人数
  • 一旦一个用户访问服务器,就会创建一个session. 如果该用户持续访问,那么该session会持续有效。
  • 如果经历了30分钟,该用户也没有做任何操作,就表示该用户“下线” 了,其对应的session也会被销毁。
  • 所以可以通过统计有多少session被保留来估计当前在线人数。
  • 编写 OnlineNumberListener
package listener;

import javax.servlet.ServletContext;

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

public class OnlineNumberListener implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent e) {

		ServletContext application = e.getSession().getServletContext();

		Integer online_number = (Integer) application.getAttribute("online_number");

		if (null == online_number)
			online_number = 0;
		online_number++;
		application.setAttribute("online_number", online_number);
		
		System.out.println("新增一位在线用户");
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent e) {

		ServletContext application = e.getSession().getServletContext();

		Integer online_number = (Integer) application.getAttribute("online_number");

		if(null==online_number){
			online_number = 0;
		}
		else
			online_number--;
		application.setAttribute("online_number", online_number);
		System.out.println("一位用户离线");
	}
}

  • 配置web.xml
	<listener>
		<listener-class>listener.OnlineNumberListener</listener-class>
	</listener>	

  • checkOnlineNumber.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
 
 当前 在线人数 : ${online_number}

  • 测试


上一篇 java复习MVC

下一篇 java复习gradle

Comments

Content