Java Web过滤器和监听器

目录

 

 

过滤器

小露身手:创建过滤器ABCFilter


 

Java Web三大组件:Servlet 、过滤器Filter和监听器Listener

过滤器

过滤器的作用:向被访问的资源加一层外壳:
        1.请求到达资源前的“请求的预处理器”;
        2.响应离开资源后的“响应的后处理器”

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-v6Z2g55qE5oiQ5bm055S35a2Q,size_20,color_FFFFFF,t_70,g_se,x_16

 

注意:响应处理的过滤器更像是一种加工机器,真正的响应由Servlet产生

Web服务器资源共有5种访问方式,分别是:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST

Filter是在资源外面加一层外壳,应该提前准备资源,由于:不存在的资源也是一个资源,所以先从请求访问一个不存在的资源,快速上手Filter

小露身手:创建过滤器ABCFilter

创建Web项目fal

在Java Resource的src处右键创建Filter

package填filter

class name 填ABCFilter

注意:请留意一下ABCFilter的Filter Mapping,保持默认值

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-v6Z2g55qE5oiQ5bm055S35a2Q,size_14,color_FFFFFF,t_70,g_se,x_16

 

package filter;

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.annotation.WebFilter;


//@WebFilter("/ABCFilter")
@WebFilter(filterName = "ABCFilter",urlPatterns = {"/ABCFilter","*.do","/test/*"})
public class ABCFilter implements Filter {


    public ABCFilter() {
        System.out.println("执行ABCFilter的构造方法");
    }


	public void destroy() {
		System.out.println("执行ABCFilter的destroy方法");
	}


	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("执行ABCFilter的doFilter之前的代码");
		chain.doFilter(request, response);
		System.out.println("执行ABCFilter的doFilter之后的代码");
	}


	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("执行ABCFilter的init()方法");
	}

}

需要注意的是:如果删除了chain那语句,那么符合filter的网址都会空白

chain的语句时将该 经过 该过滤器的request和response响应对象传至目的资源,此时浏览器显示空白页面(Content-Lenght=0)

Web服务器根据请求类型和请求的URL是否与urlPartterns匹配,判断是否触发过过滤器的doFilter()方法

过滤器的主要用途顾名思义,原本多个Servlet程序相近的代码(敏感词等)现在都可以集中在Filter里面进行

小露身手:过滤器链的使用

复制ABCFilter,另一份取名为BCDFilter 

创建web.xml:右键项目名,找到javaEE tool然后点击Genertate Deployment Descriptor Stub

@WebFilter的注解复制粘贴的时候多注意修改下 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-v6Z2g55qE5oiQ5bm055S35a2Q,size_20,color_FFFFFF,t_70,g_se,x_16

 

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-v6Z2g55qE5oiQ5bm055S35a2Q,size_8,color_FFFFFF,t_70,g_se,x_16

 结论:某个请求URL匹配了多个Filter按照<filter-mapping>在web.xml配置文件中出现的先后顺序,过滤器按照“从外到内的顺序”组装成一条过滤器链,

通过注解@WebFilter不能配置过滤器链的先后顺序,web.xml配置文件没有<filter-mapping>的话,则会按照过滤器类名在ASCII表出现的先后顺序配置!(名字的限制)

过滤器综合应用1:URL级别的权限访问控制

权限访问控制是资源安全保护的一种重要手段

中心思想:划分角色,不同的角色访问不同的资源,为受保护的资源文件分配url路径

如果受保护资源是JSP程序,同一种角色的受保护JSP程序,放在一个文件夹下,例如任何浏览器用户都可以登陆访问login.jsp

如果是Servlet程序,urlPattern相同或者兼容

小露身手:使用过滤器实现URL级别的权限访问控制

步骤:WebContent下创建admin文件夹,该文件夹创建admin.jsp,输入如下代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<h3>这是管理员隐私界面</h3>

同理user

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<h3>这是注册用户隐私界面</h3>

WebContent目录下创建登录表单程序login.jsp并输入下列代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
String contextPath = request.getContextPath();
if(session.getAttribute("msg")!=null){
	String msg = (String)session.getAttribute("msg");
	out.println(msg + "<br/>");
	session.removeAttribute("msg");
}
%>
<form action="<%=contextPath%>/LoginServlet" method="post">
用户名:<input type="text" name="userName" /><br/>
密码<input type="password" name="password" /><br/>
<input type="submit" value="登录"	/>
</form>

然后是经典的创建controller然后LoginServlet

代码如下

package controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    
    public LoginServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	//处理登录表单提交的用户数据
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String userName = request.getParameter("userName");
		String password = request.getParameter("password");
		response.setContentType("Text/html;charset=UTF-8");
		if("admin".equals(userName) && "admin".equals(password)) {
			request.getSession().setAttribute("role", "admin");
			response.getWriter().append("admin登录成功");
		}else if("user".equals(userName) && "user".equals(password)) {
			request.getSession().setAttribute("role", "user");
			response.getWriter().append("user登录成功");
		}else {
			request.getSession().setAttribute("role", null);
			response.getWriter().append("登录失败");
		}
	}

}

Filter包添加如下代码,文件名自己看得到

package filter;

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


@WebFilter(urlPatterns= {"/user/*","/admin/*"})
public class PermissionFilter implements Filter {


    public PermissionFilter() {
        // TODO Auto-generated constructor stub
    }


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


	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest)request;
		HttpServletResponse httpServletResponse = (HttpServletResponse)response;
		//request应该是主要获取数据,response内装入返回的数据
		HttpSession session = httpServletRequest.getSession();
		Object o = session.getAttribute("role");
		String contextPath = httpServletRequest.getContextPath();
		if(o == null) {
			session.setAttribute("msg", "受资源保护,请先登录");
			httpServletResponse.sendRedirect(contextPath+"/login.jsp");
			return;
		}
		String role = (String)o;
		String requestURI = httpServletRequest.getRequestURI();
		if(requestURI.contains("/admin") && !"admin".equals(role)){
			session.setAttribute("msg", "admin的受保护资源,请先登录!");
			httpServletResponse.sendRedirect(contextPath+"/login.jsp");
			return;
		}
		if(requestURI.contains("/user") && !"user".equals(role)){
			session.setAttribute("msg", "user的受保护资源,请先登录!");
			httpServletResponse.sendRedirect(contextPath+"/login.jsp");
			return;
		}
		chain.doFilter(request, response);
	}


	public void init(FilterConfig fConfig) throws ServletException {

	}

}

过滤器的综合应用2:过滤器进行表单验证

B/S架构方法,表单验证分两个级别:JavaScript级别的表单验证,Web应用程序级别的表单验证。其中JavaScript级别的表单验证属于第一道防线,Web应用程序属于第二道防线

默认情况下浏览器的JavaScript功能是开启的,但用户可以手动关闭,所以JavaScript功能被禁用,表单验证将会失效

通常情况下,为了实现Web应用级别的表单验证,表单验证代码需要编写在Servlet程序中。结果就是导致,Servlet既要包含业务逻辑代码,又要包含表单验证代码,不利于代码日常维护的工作。

因此,过滤器作用诞生了

小露身手:使用过滤器进行表单验证

filter包中创建登录表单验证过滤器 LoginValidatorFilter.java

package filter;

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


@WebFilter("/LoginServlet")
public class LoginValidatorFilter implements Filter {


    public LoginValidatorFilter() {
        // TODO Auto-generated constructor stub
    }


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


	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest)request;
		HttpServletResponse res = (HttpServletResponse)response;
		HttpSession session = req.getSession();
		String userName = req.getParameter("userName");
		String password = req.getParameter("password");
		String msg="";
		if(userName != null) {
			if(userName.trim().length() > 20 || userName.trim().length() < 4 ) {
				msg = msg+"用户名长度4~20位<br/>";
				
			}
		}
		if(password != null) {
			if(password.trim().length() > 20 || password.trim().length() < 4 ) {
				msg = msg+"密码长度4~20位<br/>";
			}
		}
		if("".equals(msg)) {
			chain.doFilter(req, res);
		}
		else {
			session.setAttribute("msg", msg);
			res.sendRedirect(req.getHeader("referer"));
			//技巧,上行代码用于获取本次HTTP请求来自哪个URL。代码res.sendRedirect(req.getHeader("referer"))将请求按原路径返回
		}
	}


	public void init(FilterConfig fConfig) throws ServletException {

	}

}

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-v6Z2g55qE5oiQ5bm055S35a2Q,size_14,color_FFFFFF,t_70,g_se,x_16

 

监听器

javaWeb监听器比较多,自行查找,由于写者学过相关监听器知识,所以文字内容较少

监听器分为状态监听器和属性监听器

小露身手:演示 Java Web状态监听器和属性监听器

Java resource的src,右键创建listener 包,class name填写ABCListener

选择监听器的话,除了session migration、object binding 和 async events

package listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionIdListener;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class ABCListener implements ServletContextListener, ServletContextAttributeListener, HttpSessionListener, HttpSessionAttributeListener, HttpSessionIdListener, ServletRequestListener, ServletRequestAttributeListener {

    public ABCListener() {
    	System.out.println("构造方法");
    }

    public void sessionCreated(HttpSessionEvent se)  { 
    	System.out.println(se.getSession().getId()+"的Session被创建");
    }

    public void attributeRemoved(ServletContextAttributeEvent scae)  { 
    	System.out.println("ServletContext的属性" + scae.getName() + "被解除绑定");
    
    }

    public void sessionIdChanged(HttpSessionEvent arg0, String arg1)  { 
    	System.out.println(arg0.getSession().getId()+"的SessionID被修改成" + arg1);
    }

    public void attributeAdded(ServletRequestAttributeEvent srae)  { 
    	System.out.println("向request请求对象绑定名是" + srae.getName() + ",值是" + srae.getValue() + "的属性");
    	
    }

    public void attributeReplaced(HttpSessionBindingEvent se)  { 
    	System.out.println("Session属性" + se.getName() + "的值被改变 ,原来的值是:" + se.getValue());
    	
    }

    public void contextInitialized(ServletContextEvent sce)  { 
    	System.out.println("ServletContext 全局对象被Web服务器初始化了");
    }

    public void attributeAdded(ServletContextAttributeEvent scae)  { 
    	System.out.println("向ServletContext对象绑定名是,"+scae.getName()+",值是"+scae.getValue());
    }

    public void requestDestroyed(ServletRequestEvent sre)  { 
    	System.out.println("来自" + sre.getServletRequest().getRemoteAddr() + "的request请求对象被删除了");
    }


    public void attributeRemoved(ServletRequestAttributeEvent srae)  { 
    	System.out.println("request请求对象的" + srae.getName() + "属性被解除绑定了");
    	
    }

    public void requestInitialized(ServletRequestEvent sre)  { 
    	System.out.println("来自" + sre.getServletRequest().getRemoteAddr() + "的request请求对象被创建了");
    }


    public void sessionDestroyed(HttpSessionEvent se)  { 
    	System.out.println(se.getSession().getId()+"的Session被删除");
    }

    public void contextDestroyed(ServletContextEvent sce)  { 
    	System.out.println("ServletContext 全局对象被Web服务器销毁了");
    }

    public void attributeReplaced(ServletRequestAttributeEvent srae)  { 
    	System.out.println("request 的属性"+srae.getName()+"的值改变了,原来的值是:"+srae.getValue());
    }

    public void attributeAdded(HttpSessionBindingEvent se)  { 
    	System.out.println("向Session绑定了属性名是" + se.getName() + "的属性");
    }

    public void attributeRemoved(HttpSessionBindingEvent se)  { 
    	System.out.println("session的属性 " + se.getName() + "被解绑了");
    }

    public void attributeReplaced(ServletContextAttributeEvent scae)  { 
    	System.out.println("ServletContext 的属性"+scae.getName()+"的值改变了,原来的值是:"+scae.getValue());
    }
	
}
package controller;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/TestServlet")
public class ABCListenerServlet extends HttpServlet {
	public ABCListenerServlet() {
		System.out.println("执行TestServlet的构造方法!");
	}
	public void init(ServletConfig config) throws ServletException {
		System.out.println("执行TestServlet的init方法!");
	}
	public void destroy() {
		System.out.println("执行TestServlet的destroy方法!");
	}
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletContext sc= request.getServletContext();
		sc.setAttribute("scName", "scValue1");//绑定属性
		sc.setAttribute("scName", "scValue2");//修改属性
		sc.removeAttribute("scName");//删除属性		
		
		request.setAttribute("requestName", "requestValue1");
		request.setAttribute("requestName", "requestValue2");
		request.removeAttribute("requestName");
		
		HttpSession session = request.getSession();
		session.setMaxInactiveInterval(5);//要使当前会话时间维持5秒
		session.setAttribute("sessionName", "sessionValue1");
		session.setAttribute("sessionName", "sessionValue2");
		session.removeAttribute("sessionName");
		request.changeSessionId();
		session.invalidate();
	}
}

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-v6Z2g55qE5oiQ5bm055S35a2Q,size_20,color_FFFFFF,t_70,g_se,x_16

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-v6Z2g55qE5oiQ5bm055S35a2Q,size_20,color_FFFFFF,t_70,g_se,x_16

注意:一定要在Servers里面 关闭!

结论:简而言之,Web服务器的内存对象,按照产生时间的顺序排序,监听器对象>ServletContext对象>request请求对象>Servlet对象(“>”表示早于)

小露身手:利用HttpSessionListener统计在线人数

在listener包下创建OnlineListener

Next按钮后选择HttpSessionListener

Finish按钮,将生产的HttpSessionListener.java修改成如下代码

package listener;

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

@WebListener
public class OnlineListener implements HttpSessionListener {

    public OnlineListener() {
    }

    public void sessionCreated(HttpSessionEvent se)  { 
    	Object o = se.getSession().getServletContext().getAttribute("OnLineNum");
    	if(o==null) {
    		se.getSession().getServletContext().setAttribute("onLineNum", 1);
    	}else {
    		int onLineNum = (int)o;
    		se.getSession().getServletContext().setAttribute("onLineNum", onLineNum+1);
    	}
    }

    public void sessionDestroyed(HttpSessionEvent se)  { 
    	//将在线人数存入ServletConText全局变量中
    	int onLineNum = (int)se.getSession().getServletContext().getAttribute("onLineNum");
    	se.getSession().getServletContext().setAttribute("onLineNum", onLineNum-1);
    }
	
}

创建index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
在线人数是:<%=request.getSession().getServletContext().getAttribute("onLineNum") %>

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-v6Z2g55qE5oiQ5bm055S35a2Q,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可靠的成年男子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值