欢迎来到皮皮网网首页

【极客论坛源码】【刮刮彩源码】【老人管理系统源码】tomcat listener 源码

来源:E站模板源码 时间:2024-12-24 04:31:30

1.Java Web开发实战—Listener详解—Listener简介、源码Listener开发、源码Listener的源码API、Listener应用
2.Listener(倾听者)
3.Servlet源码和Tomcat源码解析
4.tomcat反序列化漏洞(cve-2016-8735)
5.org.springframework.beans.factory.BeanDefinitionStoreException
6.Web中间件漏洞之Tomcat篇

tomcat listener 源码

Java Web开发实战—Listener详解—Listener简介、源码Listener开发、源码Listener的源码极客论坛源码API、Listener应用

       深入探索Java Web开发实战:Listener的源码奥秘

       在Java Web开发的世界里,Listener扮演着至关重要的源码角色,它如同后台的源码观察者,默默地监听并响应Web应用程序中的源码各种关键事件。本篇文章将带你走进Listener的源码世界,从基础概念、源码开发实践到API应用,源码一一详解。源码

       Listener基础与机制

       Listener的源码核心在于其监听机制,它通过8种接口监听Web应用中的ServletContext、HttpSession和ServletRequest事件。在Eclipse中,只需选择对应的接口,如默认的javax.servlet.ServletContextListener,即可创建Listener,如TestListener,它将自动配置到web.xml中,确保监听器的执行顺序。

       创建Listener实战

       在Eclipse中,选择Listener接口,如TestListener,勾选后自动生成相应的类,Eclipse会自动在web.xml中添加和元素,支持多Listener配置

       Listener接口详解

       Java EE提供了一系列强大的Listener接口,如ServletContextListener关注ServletContext的生命周期,而ServletContextAttributeListener则关注属性的增删改。重点掌握这两大接口,如contextInitialized和contextDestroyed,分别在ServletContext创建和销毁时触发。

       示例代码展示

contextInitialized(ServletContextEvent): 当ServletContext创建时,执行TestListener的初始化逻辑,控制台输出"ServletContext对象被创建了"。

contextDestroyed(ServletContextEvent): ServletContext销毁时,执行销毁逻辑,控制台输出"ServletContext对象被销毁了"。

       后续的Listener接口如HttpSessionListener和ServletRequestListener同样具有类似的生命周期方法,如sessionCreated(HttpSessionEvent)和requestInitialized(ServletRequestEvent),它们各自负责监听和操作相应的生命周期事件。

       Listener应用实战

       例如,我们可以创建一个名为TestListener的类,继承HttpSessionBindingListener,刮刮彩源码用于存储用户信息。结合UserInfo单例模式,实现在线用户的管理。在Servlet中,监听用户登录和登出事件,实时更新显示信息。

       小结与提升

       通过理解Listener的原理和使用方法,你能灵活地编写程序实现Web应用的特殊功能,如用户登录状态管理、会话统计等。在Context的jsp目录中,实践这些Listener的应用,例如,jsp.jsp通过JSTL展示用户信息,Servlet的删除操作则触发TestListener中的清理逻辑。重启Tomcat,一步步见证Listener的力量。

       总而言之,掌握Listener是Java Web开发不可或缺的一部分,它能让你的应用更为智能,更加灵活。深入理解Listener的接口、机制和应用,将为你的Web开发之路增添无限可能。

Listener(倾听者)

       终于轮到讲讲Filter、Listener,写完这两篇,关于JavaWeb我也就无话可说了。

       转行开发一年多了,很心疼去年浪费了这么多时间在SSM上。有一段时间,觉得自己好像什么都懂,但又什么都不懂。这种感觉是非常难受的。仿佛浑身充满了力气,却每一拳都打在棉花上。我想更深入地了解Java,写出更好更优雅的代码,结果买了书翻开的那一瞬间就发现不是自己想要的,书中所讲并没有直指我心里的疑问。

       我的疑问是什么呢?作为非科班,自知起步比别人已经晚了一大截。虽然希望最好能搞懂整个框架,却也知道欲速则不达。然而,哪怕窥得其中一二想必也会很满足。我以为这件事很简单,老人管理系统源码但却浪费了我大半年时间。

       去年年底一次偶然的机会,促使我开始了复习JavaWeb基础的漫漫长路。从此一发不可收拾,从动态代理、注解、ThreadLocal以及JDBC,一路过关斩将,收获颇丰。才发现,原来学习框架时感到无力,是特么基础不牢靠...真的是基础不牢,地动山摇,这话一点没错。

       如果当初学习JavaWeb时,我对反射、动态代理、注解、泛型、JDBC等知识点有现在这程度,学会使用SSM估计就是一星期的事情...基础实在太重要了(话虽这么说,JavaWeb对于零基础来说难度是客观存在的)。

       真的恨不得坐时光机回到去年抽自己一巴掌:滚回去好好学JavaWeb!望大家引以为戒!

       这篇先写Listener。看完这篇,你们就会发现,关于Listener,我讲解的切入点有多骚。

       主要内容:

       Listener复习

       大致来说,常用的监听器就是“6+2”:

       感知监听都是Session相关的,我已经在 Cookie与Session讲过,这里就不提了。

       6个常规监听器,分属三类,分别对应JavaWeb三大域对象(除去JSP的Page域):ServletContext、HttpSession、ServletRequest。共三对,每一对都包括1个生命周期监听和1个属性监听。

       所谓生命周期监听器,就是监听三大域对象的创建和销毁。每当Tomcat创建或销毁三大域对象,都会被这些监听器察觉,然后它们会做相应的操作(调用自身的特定方法)。

       属性监听器则专门监听三大域对象get/setAttribute()。每当我们给域对象设置值或者从里面取值,大型源码阅读工具都会被它们监听到,然后还是触发它们特定的方法。

       先复习一下Servlet如何处理请求:

       然后我们来看看监听器到底在什么时候做了什么事。

       为了帮助大家理解接下来这张图的细节,我问几个问题,大家带着问题去看:

       答案:

       问题一

       问题二

       只有当在Servlet中调用request.getSession(),且根据JSESSIONID找不到对于的Session时,才会创建新的Session对象,才会被监听到。第二次请求,浏览器会带上JSESSIONID,此时虽然还是request.getSession(),但是会返回上次那个。根据JSESSIONID去Session这个过程是隐式的,我们看到的就是getSession()。

       问题三

       对于图中的步骤7//,也就是get/setAttribute()时,会触发属性监听。

       搞清楚每一种监听器的作用以及触发时机是最重要的,使用其实很简单。去看崔老师视频吧,讲得很清楚了。

       观察者模式

       大家觉得Listener难在哪?

       是监听器种类太多记不清吗?不会吧,不就是“6+2”吗。

       是各个监听器的触发时机扑朔迷离吗?也不会啊,上面的图讲得很清楚了。

       其实!大家觉得监听器难,是因为根本不知道为啥它能起作用。监听器的底层原理其实涉及到一种设计模式:观察者模式(Observer)。

       先来看监听器的定义:

       监听器就是一个实现了特定接口的普通Java程序,这个程序专门用于监听另一个Java对象的方法调用或者属性改变。当被监听对象发生上述事件后,监听器某个方法将立即被执行。

       道理都懂,但是还是没讲到点子上。为啥监听器能监听?

       程序毕竟不是人,不像警察盯着小偷,看到他偷东西就动手抓人。在我看来,一个方法能执行,必然是被调用!有两种可能:

       监听器肯定不是通过定时任务实现的,毕竟它的方法调用时机是在“被监听对象特定行为发生时”。既然不是定时任务,那么肯定是被监听对象主动告诉监听器的!

       是发布thinkphp网站源码不是觉得很荒唐?被监听对象主动告诉Listener(对象方法调用),那还叫监听器?监听个鬼哦...

       但是大家有没有想过,监听器英文名叫Listener,我翻译成“倾听者”有何不可?就是说,Listener对象一直在侧耳倾听,等待被监听对象发号施令。这个翻译骚不骚?

       也就是说:被监听对象发生某个行为时,会主动告诉Listener(对象方法调用),让它执行对应的特定操作!

       代码结构

       被监听对象

       监听器接口

       事件(就是包装后的被监听对象)

       测试

       监听器案例

       明天写

Servlet源码和Tomcat源码解析

       画的不好,请将就。

       我一般用的IDEA,很久没用Eclipse了,所以刚开始怎么继承不了HttpServlet类,然后看了一眼我创建的是Maven项目,然后去Maven仓库粘贴了Servlet的坐标进来。

       maven坐标获取,直接百度maven仓库,选择第二个。

       然后搜索Servlet选择第二个。

       创建一个类,不是接口,继承下HttpServlet。

       Servlet接口包括:init()、service()、destroy()和getServletInfo()。其中init()方法负责初始化Servlet对象,容器创建好Servlet对象后会调用此方法进行初始化;service()方法处理客户请求并返回响应,容器接收到客户端要求访问特定的Servlet请求时会调用此方法;destroy()方法负责释放Servlet对象占用的资源;getServletInfo()方法返回一个字符串,包含Servlet的创建者、版本和版权等信息。

       ServletConfig接口包含:getServletName()、getServletContext()、getInitParameter(String var1)和getInitParameterNames()。其中getServletName()用于获取Servlet名称,getServletContext()获取Servlet上下文对象,getInitParameter(String var1)获取配置参数,getInitParameterNames()返回所有配置参数的名字集合。

       GenericServlet抽象类实现了Servlet接口的同时,也实现了ServletConfig接口和Serializable接口。它提供了一个无参构造方法和一个实现init()方法的构造方法。GenericServlet中的init()方法保存了传递的ServletConfig对象引用,并调用了自身的无参init()方法。它还实现了service()方法,这是Servlet接口中的唯一没有实现的抽象方法,由子类具体实现。

       HttpServlet是Servlet的默认实现,它是与具体协议无关的。它继承了GenericServlet,并实现了Servlet接口和ServletConfig接口。HttpServlet提供了一个无参的init()方法、一个无参的destroy()方法、一个实现了getServletConfig()方法的方法、一个返回空字符串的getServletInfo()方法、以及一个实现了service()方法的抽象方法。service()方法的实现交给了子类,以便在基于HTTP协议的Web开发中具体实现。

       Tomcat的底层源码解析如下:

       Server作为整个Tomcat服务器的代表,包含至少一个Service组件,用于提供特定服务。配置文件中明确展示了如何监听特定端口(如)以启动服务。

       Service是逻辑功能层,一个Server可以包含多个Service。Service接收客户端请求,解析请求,完成业务逻辑,然后将处理结果返回给客户端。Service通常提供start方法打开服务Socket连接和监听服务端口,以及stop方法停止服务并释放网络资源。

       Connector称为连接器,是Service的核心组件之一。一个Service可以有多个Connector,用于接收客户端请求,将请求封装成Request和Response,然后交给Container进行处理。Connector完成请求处理后,将结果返回给客户端。

       Container是Service的另一个核心组件,按照层级有Engine、Host、Context、Wrapper四种。一个Service只有一个Engine,它是整个Servlet引擎,负责执行业务逻辑。Engine下可以包含多个Host,一个Tomcat实例可以配置多个虚拟主机,默认情况下在conf/server.xml配置文件中定义了一个名为Catalina的Engine。Engine包含多个Host的设计使得一个服务器实例可以提供多个域名的服务。

       Host代表一个站点,可以称为虚拟主机,一个Host可以配置多个Context。在server.xml文件中的默认配置为appBase=webapps,这意味着webapps目录中的war包将自动解压,autoDeploy=true属性指定对加入到appBase目录的war包进行自动部署。

       Context代表一个应用程序,即日常开发中的Web程序或一个WEB-INF目录及其下面的web.xml文件。每个运行的Web应用程序最终以Context的形式存在,每个Context都有一个根路径和请求路径。与Host的区别在于,Context代表一个应用,如默认配置下webapps目录下的每个目录都是一个应用,其中ROOT目录存放主应用,其他目录存放子应用,而整个webapps目录是一个站点。

       Tomcat的启动流程遵循标准化流程,入口是BootStrap,按照Lifecycle接口定义进行启动。首先调用init()方法逐级初始化,接着调用start()方法启动服务,同时伴随着生命周期状态变更事件的触发。

       启动文件分析Startup.bat:

       设置CLASSPATH和MAINCLASS为启动类,并指定ACTION为启动。

       Bootstrap作为整个启动时的入口,在main方法中使用bootstrap.init()初始化容器相关类加载器,并创建Catalina实例,然后启动Catalina线程。

       Catalina Lifecycle接口提供了一种统一管理对象生命周期的接口,通过Lifecycle、LifecycleListener、LifecycleEvent接口,Catalina实现了对Tomcat各种组件、容器统一的启动和停止方式。在Tomcat服务开启过程中,启动的一系列组件、容器都实现了org.apache.catalina.Lifecycle接口,其中的init()、start()和stop()方法实现了统一的启动和停止管理。

       加载方法解析server.xml配置文件,加载Server、Service、Connector、Container、Engine、Host、Context、Wrapper一系列容器,加载完成后调用initialize()开启新的Server实例。

       使用Digester类解析server.xml文件,通过demon.start()方法调用Catalina的start方法。Catalina实例执行start方法,包括加载server.xml配置、初始化Server的过程以及开启服务、初始化并开启一系列组件、子容器的过程。

       StandardServer实例调用initialize()方法初始化Tomcat容器的一系列组件。在容器初始化时,会调用其子容器的initialize()方法,初始化子容器。初始化顺序为StandardServer、StandardService、StandardEngine、Connector。每个容器在初始化自身相关设置的同时,将子容器初始化。

tomcat反序列化漏洞(cve--)

       在项目开发中,Apache Tomcat中间件的使用日益普遍。为了增强知识体系,我计划整理并复现一些关键的高危漏洞,这里先介绍CVE--漏洞的复现过程。感谢Bearcat师傅、残忆师傅和李师傅等人的指导与分享。

       CVE--漏洞源于JmxRemoteLifecycleListener的反序列化功能,由于Oracle的修复未及时应用于Tomcat,导致远程代码执行风险。漏洞影响了Apache Tomcat多个版本,包括9.0.0.M1至M,8.5.0至8.5.6,以及更早版本。利用该漏洞,需要外部开启特定端口(和)来实现远程代码执行。

       复现漏洞需要特定环境设置,包括Apache Tomcat 8.5.2与Jdk1.7.0_。首先在server.xml中启用JmxRemoteLifecycleListener监听功能,然后下载catalina-jmx-remote.jar和groovy-2.3.9.jar到lib目录,并修改catalina.bat脚本以限制远程访问。启动Tomcat并监听RMI服务端口,确保监听成功。

       利用漏洞的方式包括在webapp目录下写文本文件验证漏洞,或通过wget/copy等命令上传恶意代码获取webshell权限。为防范此类漏洞,建议关闭相关功能,限制网络访问,并强化认证。同时,定期更新Tomcat到最新版本是有效的修复措施。

       更多漏洞复现和安全实践的文章可以在我的系列链接中找到,如Tomcat PUT上传漏洞(CVE--)和Tomcat后台弱口令上传war包漏洞的复现。

org.springframework.beans.factory.BeanDefinitionStoreException

       1. 在配置spring到tomcat里面的时候我们需要加一个listener,添加一个listener以后还要告诉tomcat去哪里找spring的applications。xml文件,所以还要添加一个context-param

       å³æœ‰å¦‚下配置:

       <listener>

        <listener-class>

        org.springframework.web.context.ContextLoaderListener

        </listener-class>

        </listener>

        <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>

       /WEB-INF/applicationContext-*.xml,classpath:applicationContext*.xml

        </param-value>

        </context-param>

       è¿™æ ·tomcat就知道去哪里加载spring的配置文件了

       2.在web.xml中没有引入applicationContext.xml,及其applicationContext-*.xml文件,或者是引入的路径错误。

       <context-param>

       <param-name>contextConfigLocation</param-name>

       <param-value>/WEB-INF/applicationContext*.xml, /WEB-INF/applicationContext-*.xml</param-value>

       </context-param>

       wrong:

<context-param>

       <param-name>contextConfigLocation</param-name>

       <param-value>/WEB-INF/com/applicationContext*.xml, /WEB-INF/com/applicationContext-*.xml</param-value>

       </context-param>

Web中间件漏洞之Tomcat篇

       Tomcat简介

       Tomcat服务器是免费开放源代码的Web应用服务器,专为轻量级应用设计,在中小型系统和并发访问用户不多的场合广泛使用。对于新手,它可作为开发和调试JSP程序的首选服务器。运行在Windows主机上时,Tomcat作为Apache服务器的扩展独立运行,可响应HTML页面的访问请求。

       远程代码执行漏洞及修复

       通过构造攻击请求,利用Tomcat在Windows主机上运行且启用HTTP PUT请求方法,攻击者可以上传包含任意代码的JSP文件,从而实现任意代码执行。此漏洞影响的版本为Apache Tomcat 7.0.0至7.0.。复现步骤包括配置漏洞、开启PUT方法上传文件功能、插入相关配置文件、重启服务、通过burp抓包并修改请求方式为PUT,创建并上传包含命令执行代码的JSP文件,最后验证代码执行成功。

       修复措施包括检测当前版本是否受影响并禁用PUT方法,或者更新至最新版。

       后台弱口令war包部署漏洞及修复

       Tomcat支持后台部署war文件,直接在web目录部署webshell。若后台管理页面存在弱口令,则攻击者可通过爆破获取密码,进而上传和执行webshell。修复方法包括在系统上以低权限运行Tomcat,创建专门的Tomcat服务用户并设置最小权限,增加本地和基于证书的身份验证,部署账户锁定机制,并针对特定目录设置最小权限访问限制,避免使用弱口令。

       反序列化漏洞及修复

       此漏洞与Oracle发布的mxRemoteLifecycleListener反序列化漏洞相关,由使用JmxRemoteLifecycleListener的监听功能引起。在Oracle发布修复后,Tomcat未能及时修复更新,导致远程代码执行。漏洞影响的版本包括9.0.0.M1到9.0.0.M、8.5.0到8.5.6、8.0.0.RC1到8.0.、7.0.0到7.0.、6.0.0到6.0.。复现步骤需要外部开启JmxRemoteLifecycleListener监听的端口,修改配置文件和脚本,下载并部署相关jar包,验证远程代码执行。

       修复措施包括关闭JmxRemoteLifecycleListener功能或对远程端口进行网络访问控制,增加严格的认证方式,并根据官方更新相应版本。

如何在struts+spring+hibernate项目中实现对线程的监控?

       在Java Web项目中,经常要在项目开始运行时启动一个线程,每隔一定的时间就运行一定的代码,比如扫描数据库的变化等等。要实现这个功能,可以现在web.xml文件中定义一个Listener,然后在这个Listener中启动一个线程,在线程里面实现功能。

       1. 自定义Listener

       在Struts+Spring+Hibernate的Web项目中,web.xml里面一般都会有这样的代码:

       <listener>

       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

       </listener>

       这几句代码使得Web项目的容器(也就是Web服务器,比如Tomcat)在项目启动时实例化了一个org.springframework.web.context.ContextLoaderListener类。

       类似的,我们也可以在web.xml里面自己定义一个Listener,让Web服务器去实例化:

       <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="/xml/ns/javaee" xsi:schemaLocation="/xml/ns/javaee /xml/ns/javaee/web-app_2_5.xsd" version="2.5">

       <filter>

       <filter-name>struts2</filter-name>

       <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

       </filter>

       <filter-mapping>

       <filter-name>struts2</filter-name>

       <url-pattern>/*</url-pattern>

       </filter-mapping>

       <listener>

       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

       </listener>

       <listener>

       <listener-class>com.XXX.listener.WSListener</listener-class>

       </listener>

       <welcome-file-list>

       <welcome-file>index.jsp</welcome-file>

       </welcome-file-list>

       </web-app>

       在以上的web.xml文件中,我们就让Web服务器在启动时实例化我们自己定义的com.XXX.listener.WSListener类(一般自己定义的Listener类要写在org.springframework.web.context.ContextLoaderListener的后面),然后在该类中去启动线程:

       public class WSListener implements ServletContextListener{

       private WSThread wsThread;

       @Override public void contextDestroyed(ServletContextEvent event) { // TODO Auto-generated method stub

       if (wsThread != null && wsThread.isRunning){

       wsThread.stopThread();

       }

       }

       @Override public void contextInitialized(ServletContextEvent event) { // TODO Auto-generated method stub

       if (wsThread == null){

       wsThread = new WSThread(event);

       wsThread.start();

       }

       }

       }

       Listener类是由Web服务器管理的,当Web服务器启动时,将Listener类实例化并调用其contextInitialized(ServletContextEvent event)方法,当Web服务器关闭时,调用其contextDestroyed(ServletContextEvent event)方法,因此我们可以分别在这两个方法里面实现线程的启动和结束。

       2. 在Spring容器以外获得其内部的Bean的实例的引用

       被启动的线程用于间隔一定的时间扫描一次数据库,找出新增加的数据。在一般的Struts+Spring+Hibernate的Web项目中,Spring容器中的Bean是由Spring容器管理的,而我们这里启动的线程并不在Spring容器中,那么怎样获得Spring容器中Bean的实例的引用进而访问数据库呢?可以使用Spring的WebApplicationContextUtils工具类,该工具类获得Spring容器的引用,再获得其内部的Bean的实例的引用。

       线程的代码:

       public class WSThread extends Thread{ public volatile boolean isRunning = true; // 两次扫描之间休眠的时间

       public long s_time; private WebApplicationContext context; private PropService propService; private Prop prop; private Temp2Service temp2Service; private Temp2 temp2;

       private TempService tempService;

       ServletContextEvent event; public WSThread(ServletContextEvent e){ this.event = e; this.context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext()); this.propService = (PropService) context.getBean("propService"); this.temp2Service = (Temp2Service) context.getBean("temp2Service");

       }

       public void run(){ while (isRunning){ try { this.prop = propService.findByName("scan_time"); this.s_time = Integer.parseInt(prop.getValue())*;

       sleep(s_time);

       System.out.println("Run!!!!!!");

       } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace();

       }

       }

       }

       public void stopThread(){

       isRunning = false;

       }

       public boolean isRunning(){ return isRunning;

       }

       }

       在该线程的构造函数中,使用了从Listener传过来的ServletContextEvent变量,用该变量的getServletContext()方法,获取Web项目的servletContext,然后再以这个ServletContext作为参数,使用WebApplicationContextUtils的getRequiredWebApplicationContext()方法获取ApplicationContext对象,最后再通过ApplicationContext的getBean()方法获取到Bean的实例,实现对数据库的访问。