Filter过滤器&Listener监听器
2020-07-29 17:07
120 查看
Filter快速入门:
- 过滤器的作用:
一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…
- 步骤: 定义一个类,实现接口Filter
- 复写方法
- 配置拦截路径
* web.xml
* 注解 eg:@WebFilter("/*") //访问所有资源之前,都会执行过滤器
/* * 过滤器快速入门 * 注意:不要导错包javax.servlet * */ //使用注解配置 @WebFilter("/*") //访问所有资源之前,都会执行过滤器 public class FilterDemo1 implements Filter { ... @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter执行。。。。。"); //放行 filterChain.doFilter(servletRequest,servletResponse); } ... }
- 过滤器细节:
- web.xml配置
<filter> <filter-name>demo1</filter-name> <filter-class>cn.itcast.web.filter.FilterDemo1</filter-class> </filter> <filter-mapping> <filter-name>demo1</filter-name> <!-- 拦截路径 --> <url-pattern>/*</url-pattern> </filter-mapping>
-
过滤器执行流程
1. 执行过滤器
2. 执行放行后的资源
3. 回来执行过滤器放行代码下边的代码 -
过滤器生命周期方法
1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
2. doFilter:每一次请求被拦截资源时,会执行。执行多次
3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
过滤器配置详解
- 1 拦截路径配置:
1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
@WebFilter("/index.jsp") //1具体资源路径 @WebFilter("/user/*") //2 拦截目录 访问/user下的所有资源时会执行过滤器 @WebFilter("*.jsp") //3 后缀名拦截
-
2 拦截方式配置:资源被访问的方式
1 - 注解配置: 设置dispatcherTypes属性:
1. REQUEST:默认值。浏览器直接请求资源
2. FORWARD:转发访问资源
3. INCLUDE:包含访问资源
4. ERROR:错误跳转资源
5. ASYNC:异步访问资源
* 设置参数标签即可
3 过滤器链(配置多个过滤器)
执行顺序:如果有两个过滤器:过滤器1和过滤器2
1. 过滤器1
2. 过滤器2
3. 资源执行
4. 过滤器2
5. 过滤器1
过滤器先后顺序问题:
1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
* 如: AFilter 和 BFilter,AFilter就先执行了。
2. web.xml配置: 谁定义在上边,谁先执行
案例
案例1_登录验证(改造之前的用户信息展示小案例)- 需求:
1. 访问day17_case案例的资源。验证其是否登录
2. 如果登录了,则直接放行。
3. 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。
/* * 完成登录验证的过滤器 * */ @WebFilter("/*") public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //0 强转 HttpServletRequest request = (HttpServletRequest) req; //1 获取资源请求路径 String uri = request.getRequestURI(); //HttpServletRequest才有的方法 //2 判断是否包含登录相关的资源,要注意排除css/js/图片/验证码资源 if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts/") || uri.contains("/checkCodeServlet")){ //包含,用户请求登录 -- 放行 chain.doFilter(req, resp); }else { //不包含,需要验证用户是否登录 Object user = request.getSession().getAttribute("user"); if(user != null){ //登录了 --- 放行 chain.doFilter(req, resp); }else { //未登录,跳转登录页面 request.setAttribute("login_msg","未登录,请先登录!"); request.getRequestDispatcher("/login.jsp").forward(request,resp); } } } ... }代理模式
- 设计模式:一些通用的解决固定问题 的方式
01 装饰模式
02 代理模式: 概念:
1. 真实对象:被代理的对象
2. 代理对象:
3. 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的 - 实现方式:
1. 静态代理:有一个类文件描述代理模式
2. 动态代理:在内存中形成代理类 实现步骤:
1. 代理对象和真实对象实现相同的接口
2. 代理对象 = Proxy.newProxyInstance();
3. 使用代理对象调用方法。
4. 增强方法 - 增强方式:
1. 增强参数列表
2. 增强返回值类型
3. 增强方法体执行逻辑
//真实类实现的接口 public interface SaleComputer { public String sale(double money); public void show(); } ------------------------------------------------------------------- /* * 真实类 * 将来会有一个真实类对应的真实对象,真实对象被代理对象代理,来增强它的功能 * */ public class Lenovo implements SaleComputer { @Override public String sale(double money) { System.out.println("花了"+money+"买了一台联想电脑"); return "联想电脑"; } @Override public void show() { System.out.println("展示电脑..."); } } --------------------------------------------------------------- //代理 public class proxyTest { public static void main(String[] args) { //1 创建真实对象 Lenovo lenovo = new Lenovo(); //2 动态代理增强lenovo对象诈 --- 返回代理对象 /* * 三个参数: * 1 类加载器:真实对象.getClass().getClassLoader() * 2 接口数组:真实对象.getClass().getInterfaces() --- 保证代理对象和真实对象实现相同的接口 * 3 处理器new InvocationHandler() --- 匿名内部类,负责核心业务逻辑处理 * */ //可以将代理对象转换为接口,将来可以直接使用代理对象调用方法 SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() { /* 代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法的执行 参数: 1 proxy:代理对象 2 method:代理对象调用的方法被封装为一个对象 3 args:代理对象调用方法时,传递的实际参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* System.out.println("该方法执行了...."); System.out.println(method.getName()); //sale System.out.println(args[0]); //8000*/ //判断是否为sale方法 --- (不是所有方法都需要增强) if (method.getName().equals("sale")) { //1 增强参数 Double money = (Double) args[0]; money = money * 0.85; System.out.println("专车接你...."); //3 方法体逻辑增强 //使用真实对象调用该方法 String obj = (String) method.invoke(lenovo, money);//调用类中bai的方法,invoke(class, method) System.out.println("免费送货...."); //2 增强返回值 return obj + "_鼠标垫"; }else { //不是sale方法原样调用 Object obj = method.invoke(lenovo, args);//调用类中bai的方法,invoke(class, method) return obj; } } });//创建代理实例 //2 调用方法 // String computer = lenovo.sale(8000); String computer = proxy_lenovo.sale(8000); //接受代理方法传递回来的对象 System.out.println(computer); //联想电脑_鼠标垫 --- 增强过的 proxy_lenovo.show(); //展示电脑... } }案例2_敏感词汇过滤
-
需求:
1. 对day17_case案例录入的数据进行敏感词汇过滤
2. 敏感词汇参考《敏感词汇.txt》— (笨蛋、坏蛋)
3. 如果是敏感词汇,替换为 *** -
分析:
1. 对request对象进行增强。增强获取参数相关方法 —> 产生一个新的request对象。
2. 放行。传递代理对象(新的request对象) -
增强对象的功能:代理模式
/* * 敏感词过滤器 * */ @WebFilter("/*") public class SensitiveWordsFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //1 创建代理对象,增强getParameter方法 ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //2 增强getParameter方法 //判断是否是 if(method.getName().equals("getParameter")){ //增强返回值 //获取返回值 --- 过滤敏感词 String value = (String) method.invoke(req,args); if(value!=null){ for (String str : list) { if(value.contains(str)){ value = value.replaceAll(str,"***"); } } } return value; } return method.invoke(req,args); //不需要过滤正常秩序 } }); //2 放行 chain.doFilter(proxy_req, resp); } private List<String> list = new ArrayList<String>(); //敏感词汇集合 public void init(FilterConfig config) throws ServletException { try{ //1 加载文件真实路径 ServletContext servletContext = config.getServletContext(); String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt"); //获取src下的文件 //2 读取文件 BufferedReader br = new BufferedReader(new FileReader(realPath)); //3 将文件的每一行数据添加到list中 String line; while ((line = br.readLine())!=null){ list.add(line); } br.close(); //释放资源 System.out.println(list); }catch (Exception e){ e.printStackTrace(); } } ...... }
在request获取getParameter()中如果存在敏感词汇都会被替换,当然还有其他获取参数的方法,getParameterMap、getParameterValue都需要进行过滤。
Listener:监听器
-
概念:web的三大组件之一。
事件监听机制
* 事件 :一件事情
* 事件源 :事件发生的地方
* 监听器 :一个对象
* 注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码
ServletContextListener:监听ServletContext对象的创建和销毁
-
方法:
* void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
* void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法
1. 定义一个类,实现ServletContextListener接口
2. 复写方法
3. 配置:使用web.xml或者注解
<!--配置监听器 注册监听--> <listener> <listener-class>cn.itcast.linterner.ContextLoaderListener</listener-class> </listener> <!--指定初始化参数--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/applicationContext.xml</param-value> </context-param>
//定义类 --- 实现接口方法 @WebListener //注解方式 public class ContextLoaderListener implements ServletContextListener { /** * 监听servletContext对象创建。 * servletContext对象服务器启动后自动创建 * * 服务器启动后自动调用 * @param servletContextEvent */ @Override public void contextInitialized(ServletContextEvent servletContextEvent) { //加载资源文件 //1 获取ServletContext对象 ServletContext servletContext = servletContextEvent.getServletContext(); //2 加载资源文件 String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation"); //根据键获取 //3 获取真实路径 String realPath = servletContext.getRealPath(contextConfigLocation); //4 加载进内存 try { FileInputStream fis = new FileInputStream(realPath); System.out.println(fis); } catch (Exception e) { e.printStackTrace(); } System.out.println("servletContext对象被创建了..."); } /** * 在服务器关闭后,servletContext对象被销毁,当服务器正常关闭后该方法被调用 * @param servletContextEvent */ @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("servletContext对象被销毁了..."); } }
相关文章推荐
- Python病毒篇:漏洞测试及Chrome浏览器漏洞测试
- ARM裸机的知识点总结--------- 3、安装交叉编译工具链 、使用优化 、Makefile 、mkv210_image.c
- Python病毒篇:实现引导木马和url路由详解
- Python黑客实战篇:WHUCTF攻击Signup网站
- Python引导木马病毒(拓展篇)
- 质量流量计的正确安装
- Python 基础篇:详细讲解tkinter(GUI库)
- Python病毒篇:中级篇(超多攻击实例,附csdn感言)
- 大小端模式转换
- C语言 实验8-2-10 IP地址转换 (20分)
- python反爬之破解动态页面(三)
- Python病毒篇:进阶版
- Python病毒篇:Web篇(SQL注入以及攻击网站实例)
- java(GUI)Panel面板
- Java web第七天-Tomcat下载安装与使用
- 实验2-2-4 计算分段函数[2] (10分)
- Python病毒篇:高级篇
- 青书学堂刷课软件青书学堂自动挂课插件
- python脚本读取文件数据写入mysql
- 学习笔记(2):零基础掌握 Python 入门到实战-选择合适的编程语言(二)