首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
搜索
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
AI面试、笔试、校招、雇品
HR免费试用AI面试
最新面试提效必备
登录
/
注册
在看牛客的番石榴很成熟
河南科技大学 Java
发布于河南
关注
已关注
取消关注
@JavaEdge:
不知道这些Servlet规范、还敢说自己是Java程序员?
1 遥远的CGI 实现Web动态内容的技术,最早使用的是CGI(Common Gateway Interface,通用网关接口)技术,根据用户输入的请求动态地传送HTML数据。CGI并不是开发语言,而只是能够利用为它编写的程序来实现Web服务器的一种协议。可用来实现电子商务网站、搜索引擎处理和在线登记等功能。当用户在Web页面中提交输入的数据时,Web浏览器就会将用户输入的数据发送到Web服务器上。在服务器上,CGI程序对输入的数据进行格式化,并将这个信息发送给数据库或服务器上运行的其他程序,然后将结果返回给Web服务器。最后,Web服务器将结果发送给Web浏览器,这些结果有时使用新的Web页面显示,有时在当前Web页面中显示。 编写自定义CGI脚本需要相当多的编程技巧,多数CGI脚本是由Perl,Java,C和C++等语言编写的,服务器上通常很少运行用JavaScript编写的服务器脚本,不管使用何种语言,Web页面设计者都需要控制服务器,包括所需要的后台程序(如数据库),这些后台程序提供结果或来自用户的消息。即使拥有基于服务器的网站设计工具,编写CGI程序也要求程序设计者有一定的经验。 由于每一次对于动态内容的请求都需要启动一个新的CGI程序,因而会增加Web服务器的负担,所以CGI的一个很大缺陷是容易影响Web服务器的运行速度。 脚本编程 由于CGI程序与HTML文档需要分开编写、分开运行,要将两者融合在一起并不容易,因此,CGI程序的维护与编写比较困难。为了解决这一问题,一些厂商推出了脚本语言来增强网页开发功能。 脚本语言是一种文本型编程语言,可嵌入到HTML文档中。脚本语言分客户端和服务器端两种类型,分别在Web浏览器和Web服务器中运行。 客户端脚本语言主要有JavaScript、Jscript(Microsoft公司的JavaSCript版本)和VBscript等。当Web浏览器需要浏览使用客户端脚本语言编写的Web页面时,Web服务器将客户端脚本连同Web页面一起传送到Web浏览器,Web浏览器同时显示HTML的显示效果和客户端脚本的运行效果, 客户端脚本可减轻Web服务器的处理负担,提高Web页面的响应速度。 服务器端脚本语言主要有ASP,JSP,PHP和LiveWire等。当Web浏览器需要浏览使用服务器端脚本语言编写的Web页面时,Web服务器运行Web页面中的服务器端脚本,将由脚本语言的运行结果与Web页面的HTML部分生成的新的Web页面传送到Web浏览器,Web浏览器显示生成的新的Web页面, 服务器端脚本可减少不同Web浏览器的运行差异,提高Web页面的实用性。 这期间,Java 的 Servlet模型也就诞生了。 2 Servlet 一种基于Java技术的Web组件,用于生成动态内容,由容器管理。类似于其它Java技术组件,Servlet 是平台无关的Java类组成,并且由Java Web服务器加载执行。 通常由Servlet容器提供运行时环境。Servlet 容器,有时候也称作为Servlet引擎,作为Web服务器或应用服务器的一部分 。通过请求和响应对话,提供Web客户端与Servlets 交互的能力。容器管理Servlets实例以及它们的生命周期。 主要版本 核心组件 核心组件 API 说明 起始版本 Spring framework 代表实现 javax. servlet .Servlet 动态内容组件 1.0 DispatcherServlet javax. servlet .Filter Servlet过滤器 2.3 CharacterEncodingFilter javax. servlet .ServletContext Servlet应用上下文 javax. servlet .AsyncContext 异步上下文 3.0 无 javax. servlet .ServletContextistener ServletContext生命周期监听器 2.3 ContextLoaderListener javax . servlet . ServletRequestlistener ServletRequest生命周期监听器 2.3 RequestContextListener javax. servlet .http.HttpSessionListener 生命周期监听器 2.3 HttpSessionMutexListener javax. servlet .Asynclistener 异步上下文监听器 3.0 StandardServletAsyncWebRequest javax. servlet .ServletContainerInitializer Servlet容器初始化器 3.0 SpringServletContainerInitializer 浏览器发给服务端的是一个HTTP请求,HTTP服务器收到请求后,需调用服务端程序处理请求。 HTTP服务器怎么知道要调用哪个处理器方法? 最简单的就是在HTTP服务器代码写一堆if/else:若是A请求就调x类m1方法,若是B请求就调o类的m2方法。这种设计的致命点在于HTTP服务器代码跟业务逻辑耦合,若你新增了业务方法,竟然还得改HTTP服务器代码。面向接口编程算得上是解决耦合问题的银弹,我们可定义一个接口,各业务类都实现该接口,没错,他就是Servlet接口,实现了Servlet接口的业务类也叫作Servlet。 解决了业务逻辑和HTTP服务器的耦合问题,那又有问题了:对特定请求,HTTP服务器又如何知道: 哪个Servlet负责处理请求? 谁负责实例化Servlet? 显然HTTP服务器不适合负责这些,否则又要和业务逻辑耦合。 于是,诞生了Servlet容器。 3 Servlet容器 用于加载和管理业务类。 HTTP服务器不直接和业务类交互,而是把请求先交给Servlet容器,Servlet容器内部将请求转发到具体Servlet。若该Servlet还没创建,就加载并实例化之,然后调用该Servlet的接口方法。 因此Servlet接口其实是Servlet容器跟具体业务类之间的接口:左:HTTP服务器直接调用具体业务类,但紧耦合。右:HTTP服务器不直接调用业务类,而是把请求移交给容器,容器通过Servlet接口调用业务类。因此Servlet接口和Servlet容器,实现了HTTP服务器与业务类的解耦。 Servlet接口和Servlet容器这一整套规范叫作Servlet规范。Tomcat按Servlet规范要求实现了Servlet容器,又兼备HTTP服务器功能。若实现新业务,只需实现一个Servlet,并把它注册到Tomcat(Servlet容器),剩下的事情就由Tomcat帮忙。 4 Servlet接口 Servlet接口定义了下面五个方法: 具体业务类在service方法实现处理逻辑,入参这两个类是对通信协议的封装: ServletRequest封装请求信息 ServletResponse封装响应信息 HTTP协议中的请求和响应就对应 HttpServletRequest获取所有请求相关的信息,包括请求路径、Cookie、HTTP头、请求参数等。还能创建和获取Session HttpServletResponse封装HTTP响应 生命周期相关方法: initServlet容器在加载Servlet类的时候会调用,可能会在init方法里初始化一些资源。比如Spring MVC中的DispatcherServlet,就是在init方法里创建了自己的Spring容器。 destroy卸载时会调用,可能在destroy方法里释放这些资源 ServletConfig ServletConfig的作用就是封装Servlet的初始化参数。可以在web.xml给Servlet配置参数,并在程序通过getServletConfig拿到这些参数。 有接口一般就有抽象类,抽象类用来实现接口和封装通用的逻辑,因此Servlet规范提供了GenericServlet抽象类,可以通过扩展它来实现Servlet。虽然Servlet规范并不在乎通信协议是什么,但是大多数的Servlet都是在HTTP环境中处理的,因此Servet规范还提供了HttpServlet来继承GenericServlet,并且加入了HTTP特性。这样我们通过继承HttpServlet类来实现自己的Servlet,只需要重写两个方法:doGet和doPost。 5 Servlet容器 工作流程 当客户请求某个资源时 HTTP服务器用ServletRequest对象封装客户的请求信息 然后调用Servlet容器的service方法 Servlet容器拿到请求后,根据请求的URL和Servlet的映射关系,找到相应的Servlet 如果Servlet还没有被加载,就用反射创建该Servlet 调用Servlet的init方法来完成初始化 调用Servlet的service方法来处理请求 把ServletResponse对象返回给HTTP服务器,HTTP服务器会把响应发送给客户端 Web应用 Servlet容器会实例化和调用Servlet,那Servlet怎么注册到Servlet容器? 根据Servlet规范,Web应用程序有一定目录结构,放置了 Servlet的类文件 配置文件 静态资源 Servlet容器通过读取配置文件,就能找到并加载Servlet。Web应用的大致目录结构: | - MyWebApp | - WEB-INF/web.xml -- 配置文件,用来配置Servlet等 | - WEB-INF/lib/ -- 存放Web应用所需各种JAR包 | - WEB-INF/classes/ -- 存放你的应用类,比如Servlet类 | - META-INF/ -- 目录存放工程的一些信息 6 ServletContext 定义了一系列servlet用于与其servlet容器通信的方法。如获取文件的 MIME 类型、调度请求或写入日志文件。每个JVM的Web应用程序都有一个上下文。(Web 应用程序是安装在服务器 URL 名称空间(如/catalog)的特定子集下并可能通过 。war 文件安装的服务和内容的集合。如果在部署描述符中标 分布式系统下,则每个机器节点都有一个上下文实例。在这种情况下,上下文不能用作共享全局信息的位置(因为信息不会是真正的全局的)。应该改用数据库等外部资源。ServletContext对象包含在 ServletConfig 对象中,当服务器初始化时,Web 服务器会提供该对象。 Servlet规范定义了ServletContext接口对应一个Web应用。比如一个 SpringBoot 应用,那就只有一个ServletContext。不要和 Spring 的 applicationContext 混为一谈,因为一个应用中,可以有多个Spring 的 applicationContext。 Web应用部署好后,Servlet容器在启动时会加载Web应用,并为每个Web应用创建一个全局的上下文环境ServletContext对象,为后面的Spring容器提供宿主环境。 可将ServletContext看做一个全局对象,一个Web应用可能有多个Servlet,这些Servlet可通过全局ServletContext共享数据: Web应用的初始化参数 Web应用目录下的文件资源等 ServletContext 持有所有Servlet实例,所以也能实现Servlet请求的转发。 Tomcat&Jetty在启动过程中触发容器初始化事件,Spring的ContextLoaderListener会监听到这个事件,它的contextInitialized方***被调用,在这个方法中,Spring会初始化全局的Spring根容器,这个就是Spring的IoC容器。IoC容器初始化完毕后,Spring将其存储到ServletContext,便于以后获取。ServletContext就是用来共享数据的,比如SpringMVC需要从ServletContext拿到全局的Spring容器,把它设置成自己的父容器。 Tomcat&Jetty在启动过程中还会扫描Servlet,一个Web应用中的Servlet可以有多个,以SpringMVC中的DispatcherServlet为例,这个Servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个Servlet请求。 Servlet一般会延迟加载,当第一个请求达到时,Tomcat&Jetty发现DispatcherServlet还没有被实例化,就调用DispatcherServlet的init方法,DispatcherServlet在初始化的时候会建立自己的容器,叫做SpringMVC 容器,用来持有Spring MVC相关的Bean。同时,Spring MVC还会通过ServletContext拿到Spring根容器,并将Spring根容器设为SpringMVC容器的父容器,请注意,Spring MVC容器可以访问父容器中的Bean,但是父容器不能访问子容器的Bean, 也就是说Spring根容器不能访问SpringMVC容器里的Bean。说的通俗点就是,在Controller里可以访问Service对象,但是在Service里不可以访问Controller对象。 初始化工作 Tomcat/Jetty启动,对于每个WebApp,依次进行初始化工作:1、对每个WebApp,都有一个WebApp ClassLoader,和一个ServletContext2、ServletContext启动时,会扫描web.xml配置文件,找到Filter、Listener和Servlet配置 3、如果Listener中配有spring的ContextLoaderListener3.1、ContextLoaderListener就会收到webapp的各种状态信息。3.3、在ServletContext初始化时,ContextLoaderListener也就会将Spring IOC容器进行初始化,管理Spring相关的Bean。3.4、ContextLoaderListener会将Spring IOC容器存放到ServletContext中 4、如果Servlet中配有SpringMVC的DispatcherServlet4.1、DispatcherServlet初始化时(其一次请求到达)。4.2、其中,DispatcherServlet会初始化自己的SpringMVC容器,用来管理Spring MVC相关的Bean。4.3、SpringMVC容器可以通过ServletContext获取Spring容器,并将Spring容器设置为自己的根容器。而子容器可以访问父容器,从而在Controller里可以访问Service对象,但是在Service里不可以访问Controller对象。4.2、初始化完毕后,DispatcherServlet开始处理MVC中的请求映射关系。 Servlet默认单例模式,Spring的Bean默认也是单例模式,则Spring MVC是如何处理并发请求?DispatcherServlet中的成员变量都是初始化好后就不会被改变了,所以是线程安全的,那“可见性”怎么保证呢?由Web容器比如Tomcat保证,Tomcat在调用Servlet的init方法时,用synchronized。 若还没有至少一个已初始化的实例,则加载并初始化该 servlet 的一个实例。 例如,这可用于加载deployment descriptor中标记为在服务器启动时加载的 servlet。实现说明:类名以org.apache.catalina.开头的 Servlet org.apache.catalina. (所谓的 servlet容器)由加载此类的同一类加载器加载,而非由当前 Web 应用程序的类加载器加载。 这使此类可以访问 Catalina 内部结构,而对于为 Web 应用程序加载的类,这种访问权限是被阻止的扩展机制 引入了Servlet规范后,无需关心Socket网络通信、HTTP协议或你的业务类是如何被实例化和调用的,因为这些都被Servlet规范标准化了,我们只需关心怎么实现业务逻辑。 有规范看着很方便,但若规范不能满足你的个性需求,就没法用了,因此设计一个规范或者一个中间件,要充分考虑到可扩展性。Servlet规范提供了两种扩展机制:Filter和Listener。 Filter 过滤器,该接口允许你对请求和响应做一些统一的定制化处理。Filter是基于过程的,它是过程的一部分,是基于过程行为的。比如: 根据请求频率限制访问 根据地区不同修改响应内容 过滤器是 Servlet 的重要标准之一: 请求和响应的统一处理 访问日志记录 请求权限审核......都发挥重要作用 工作原理 Web应用部署完成后,Servlet容器需要实例化Filter并把Filter链接成一个FilterChain。当请求进来时,获取第一个Filter并调用doFilter方法,doFilter方法负责调用这个FilterChain中的下一个Filter。 Listener 监听器,Listener是基于状态的,任何行为改变同一个状态,触发的事件是一致的。当Web应用在Servlet容器中运行时,Servlet容器内部会不断的发生各种事件,如Web应用的启动和停止、用户请求到达等。 Servlet容器提供了一些默认的监听器来监听这些事件,当事件发生时,Servlet容器会负责调用监听器的方法。当然,你可以定义自己的监听器去监听你感兴趣的事件,将监听器配置在web.xml中。比如Spring就实现了自己的监听器,来监听ServletContext的启动事件,目的是当Servlet容器启动时,创建并初始化全局的Spring容器。 X FAQ service方法为什么把request和response都当作输入参数,而不是输入参数只有request,response放到返回值里呢?方便责任链模式下层层传递。 在SpringBoot项目中,为什么没有web.xml了?SpringBoot是以嵌入式的方式来启动Tomcat。对于SpringBoot来说,Tomcat只是个JAR包。SpringBoot通过Servlet3.0规范中 @WebServlet 注解或者API直接向Servlet容器添加Servlet,无需web.xml。 分不清的xxx容器 Servlet容器 用于管理Servlet生命周期。 SpringMVC容器 管理SpringMVC Bean生命周期。 Spring容器 用于管理Spring Bean生命周期。包含许多子容器,其中SpringMVC容器就是其中常用的,DispatcherServlet就是SpringMVC容器中的servlet接口,也是SpringMVC容器的核心类。 Spring容器主要用于整个Web应用程序需要共享的一些组件,比如DAO、数据库的ConnectionFactory等,SpringMVC容器主要用于和该Servlet相关的一些组件,比如Controller、ViewResovler等。至此就清楚了Spring容器内部的关系。 Spring和SpringMVC分别有自己的IOC容器或上下文,为何分成俩容器?隔离管理的Bean,各管各的,职责明确。SpringMVC的容器直接管理跟DispatcherServlet相关的Bean,也就是Controller,ViewResolver等,并且SpringMVC容器是在DispacherServlet的init方法里创建的。而Spring容器管理其他的Bean比如Service和DAO。 并且SpringMVC容器是Spring容器的子容器,所谓的父子关系意味着什么呢,就是你通过子容器去拿某个Bean时,子容器先在自己管理的Bean中去找这个Bean,如果找不到再到父容器中找。但是父容器不能到子容器中去找某个Bean。 其实这个套路跟JVM的类加载器设计有点像,不同的类加载器也为了隔离,不过加载顺序是反的,子加载器总是先委托父加载器去加载某个类,加载不到再自己来加载。 并且通过父子关系,使得SpringMVC容器可以从父亲Spring容器那里拿Bean,因为Spring容器管理的是公共的Bean。当然可以用同一个容器来管理,SpringBoot就是这样做的。 Spring和SpringMVC是通过配置文件来明确指定各自管理的Bean。 Servlet容器跟Spring容器又有什么关系呢?有人说spring容器是servlet容器的子容器,但是这个servlet容器到底是tomcat实现的容器呢,还是jetty实现的容器呢?所以spring容器与servlet容器他们之间并没有直接的血缘关系,可以说spring容器依赖了servlet容器,spring容器的实现遵循了Servlet 规范。 spring容器只是servlet容器上下文(ServletContext)的一个属性,web容器启动时通过ServletContextListener机制构建出来。SpringBoot中只有一个Spring上下文: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext servlet容器初始化成功后被spring监听,创建spring容器放入servlet容器中,访问到达,初始化dispatcher servlet时创建springmvc容器,通过servletContext拿到spring容器,并将其作为自己的父容器,spring mvc容器会定义controller相关的bean,spring会定义业务逻辑相关的bean。 参考 https://blog.csdn.net/zhanglf02/article/details/89791797 https://docs.oracle.com/cd/E19146-01/819-2634/abxbh/index.html https://matthung0807.blogspot.com/2020/09/tomcat-how-servlet-construct.html https://github.com/heroku/devcenter-embedded-tomcat https://biang.io/blog/mixed/cgi
点赞 0
评论 0
全部评论
推荐
最新
楼层
暂无评论,快来抢首评~
相关推荐
05-26 10:32
华为_HR
Q&A——互联网OD
每日一更之互联网OD——Q&AQ1:现在大厂缩编、HC变少,普遍程序员到底卡在什么地方?真实的困境是什么?说白了就是企业招人要求越来越高了,不是说现在程序员的能力不行,而是在AI技术的冲击以及大量新人涌入行业的双重作用下,程序员不再像以前那样稀缺了。打个比方来说,以前本科毕业或许就能拿到offer,现在读了研究生,说不定面试都进不去,这就是现在行业的现状。Q2:大厂现在搞的多种用工方式,比如OD、外包这些,是行业未来的常态吗?先说是基本会成为行业常态。继华为之后,字节也出了OD政策,这也是各行各业的常态了。原因有三点:帮助企业更好地控制用人成本、规避用工风险,同时团队人员结构也能更加灵...
点赞
评论
收藏
分享
今天 14:44
已编辑
门头沟学院 测试工程师
债卫士科技——初级测试工程师(社招)
TimeLine:2025.11.25 一面(线下面) 2025.11.26 技术总监面(线下面)--------------------------------------------------------------一面(HR+技术面,30min):技术面: 1.自我介绍 2.问实习经历,主要做了什么 3.会不会写SQL,掌握的测试工具有哪些 4.工作中遇到最大的困难是什么 5.会写自动化脚本吗 6.测试用例是自己独立写的,还是只是执行测试用例 7.知道怎么进行大模型测试吗HR面: 1.自我介绍 2.校园经历 3.人生遇到最大的挫折 4.目前住哪里 5.期望薪资 6.反问介绍公司业务背景...
查看14道真题和解析
点赞
评论
收藏
分享
04-25 16:03
安阳学院 后端工程师
学院本真的没出路了吗
简历求拷打,大佬们救命啊,现在要干嘛,刷算法刷了几天感觉没啥用,没实习大三下了,要做项目还是要干嘛,boss沟通那么多就一个面试一个offer,还是偏远小公司
代码飞升AL:
同学院本建议你换一个项目 就算你不去特意搜也应该知道点评不能写吧 保持投递不要停 然后快速弄一个项目换上去 公司就别挑了 我第一段120一天 快速跳就行
点赞
评论
收藏
分享
不愿透露姓名的神秘牛友
04-21 17:34
我真蠢,上班三天才知道mt让看文档啥意思
第一次实习的时候啥也不懂mentor第一天跟我说的。我说好。我以为只是第一天这样。第二天——"你先看看文档。"第三天——"你先看看文档。"第五天我鼓起勇气问:"那我后面大概做什么方向?"他说:"不急,先熟悉。"我点开过的文档数了数,三十多篇。每一篇我都有认真看实在无聊,我打开同学群看看大家都干啥呢。有人说他入职第一天就改了bug。有人说他mentor每天带他review代码。有人说他们组上周聚餐了。我每天的成就是:又看了五篇文档。上了一周班后,晚上我收工位走出公司,那一刻我突然明白"你先看看文档"是什么意思。不是让我熟悉。是他也不知道让我干嘛。我真的谢
文聚星:
说明你这是大厂,小厂才会来了直接上手写
实习时最怕听到的一句话
点赞
评论
收藏
分享
05-27 14:42
门头沟学院 Java
学院本熬到上岸的这两个月
27届,3.16开始投递,boss打招呼来了惊人的 6k+,要简历的只有 360。从三月到五月,感觉像被扔进了一场没有终点的暴雨里:每天机械地投递、背八股、改简历、跑面试,盯着越来越少的 Java HC,看着 AI Agent 风口席卷一切,开始怀疑自己过去几年到底学了什么。每天又想着背八股、熟悉项目,一边又要投岗位,有时候一个小时过去了都不知道,时间压力、学习压力接踵而至……最难受的不是被挂,而是连面试机会都没有;不是累,而是长期努力得不到反馈后的失控感,投资回报率甚至得用负来表示。一边骂行业、骂市场、骂自己,一边又不肯真正躺下,哪怕情绪崩到恶心、麻木、脱敏,第二天还是继续投递。微信里每天都...
点赞
评论
收藏
分享
评论
点赞成功,聊一聊 >
点赞
收藏
分享
评论
提到的真题
返回内容
全站热榜
更多
1
...
27届暑期前端高频面试题汇总(字节百度阿里快手等多家大厂)
6134
2
...
字节三面
2009
3
...
美团计划裁员30%,测试和产品砍一半,测试全栈化时代来了!
1457
4
...
26前端的深夜
1334
5
...
继续实习VS暑假沉淀,怎么选....
996
6
...
字节实习一个月祛魅了
991
7
...
你说你用Claude,你用的是 CLI,还是 Agent、Opus?
947
8
...
今天陌陌的笔试怎么样
942
9
...
收到了字节的AIoffer
813
10
...
5.17华为od记录,两年过得好快
630
创作者周榜
更多
正在热议
更多
#
实习生的蛐蛐区
#
1012048次浏览
5151人参与
#
求职遇到的搞笑事件
#
198033次浏览
994人参与
#
发面经攒人品
#
8920833次浏览
98889人参与
#
体制内上岸心路历程
#
39236次浏览
223人参与
#
27届实习投递记录
#
168050次浏览
1688人参与
#
担心入职之后被发现很菜怎么办
#
307711次浏览
1223人参与
#
你收到了团子的OC了吗
#
1640123次浏览
11866人参与
#
万物皆可发面经
#
6052次浏览
75人参与
#
扒一扒那些奇葩实习经历
#
161079次浏览
1184人参与
#
现在还是0offer,延毕还是备考
#
1434482次浏览
7969人参与
#
招聘要求与实际实习内容不符怎么办
#
227170次浏览
1078人参与
#
实习,不懂就问
#
232921次浏览
1772人参与
#
HR问:你期望的薪资是多少?如何回答
#
103442次浏览
841人参与
#
AI了,我在打一种很新的工
#
212739次浏览
2382人参与
#
父母对你找工作是助力还是阻力?
#
54166次浏览
478人参与
#
查收我的offer竞争力报告
#
303828次浏览
1761人参与
#
地方国企笔面经互助
#
43486次浏览
113人参与
#
秋招盘点:机械人值得去的企业
#
109044次浏览
746人参与
#
实习最想跑路的瞬间
#
147988次浏览
787人参与
#
美团秋招笔试
#
222238次浏览
1203人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务