每日学习Java之一万个为什么
文章目录
- 16.前后端分离是怎么实现的?
- 17.Servlet 和 Socket 区别
- 18.为什么对于特别复杂的需求Servlet很难处理,怎么提前创建
- 19.什么是JavaWeb中特别复杂的需求?
- 20.为什么@WebServlet可以代替配置文件?
- 21.Tomcat 处理servlet流程
- 22.web.xml的映射关系
- 23.servlet的动态加载过程
- 24.servlet的三种映射路径配置
- 25.servlet容器的service()方法有什么用?区别于servlet.service()容器的 service() 方法主要负责将请求分配给正确的 Servlet 实例,并调用其 service() 方法。
- 26.servletResponse对象的getWriter()方法为什么不是setString
- 27.为什么Http2.0大幅提升了Web性能?
- 28.Tomcat三大域 分别有什么用?
- 30.SevletContext如果是所有servlet共享,那么网络聊天是怎么实现的?
- 31.@WebServlet("/targetUrl")默认servlet-name是什么?
- 32.[Ajax](https://blog.csdn.net/Oriental_/article/details/104863762?ops_request_misc=%257B%2522request%255Fid%2522%253A%25224d44ca7347228f2c14c560d2b4ba3a18%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=4d44ca7347228f2c14c560d2b4ba3a18&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-104863762-null-null.142%5Ev101%5Epc_search_result_base5&utm_term=Ajax&spm=1018.2226.3001.4187)
- 33.ES6概述
- 34.[Node](https://blog.csdn.net/m0_55557411/article/details/124255896?ops_request_misc=%257B%2522request%255Fid%2522%253A%252234e834198c6153eef8e5b486f9c540f1%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=34e834198c6153eef8e5b486f9c540f1&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-4-124255896-null-null.142%5Ev101%5Epc_search_result_base5&utm_term=Node.js&spm=1018.2226.3001.4187)概述
- 35.[NPM](https://juejin.cn/post/7376825731908124735?searchId=202502241034103AF5675BFD443D644059)概述
- 36.[Vue3](https://blog.csdn.net/m0_63231347/article/details/135438085)概述
- 37.[Vue Router](https://blog.csdn.net/Litt_White/article/details/126435871?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522df63d64b450717b4f54cbde697bfda2e%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=df63d64b450717b4f54cbde697bfda2e&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-126435871-null-null.142%5Ev101%5Epc_search_result_base5&utm_term=Vue%20Router%E8%AF%A6%E8%A7%A3&spm=1018.2226.3001.4187)
- 38.[Promise](https://blog.csdn.net/h18377528386/article/details/122741648?ops_request_misc=%257B%2522request%255Fid%2522%253A%25229c03e257bbb481f6d32e3839d78ef8d1%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=9c03e257bbb481f6d32e3839d78ef8d1&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-122741648-null-null.142%5Ev101%5Epc_search_result_base5&utm_term=Promise%E8%AF%A6%E8%A7%A3&spm=1018.2226.3001.4187)
- 39.[Axios](https://blog.csdn.net/m0_59792745/article/details/127206214?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522da8e0dd6a5006c6e8472b054f1119ec8%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=da8e0dd6a5006c6e8472b054f1119ec8&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-6-127206214-null-null.142%5Ev101%5Epc_search_result_base5&utm_term=Axios%E8%AF%A6%E8%A7%A3&spm=1018.2226.3001.4187)
- 40.[Pinia](https://blog.csdn.net/m0_37911706/article/details/127118441?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522f5de241a49bdf0d6c96630216f922b34%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=f5de241a49bdf0d6c96630216f922b34&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-4-127118441-null-null.142%5Ev101%5Epc_search_result_base5&utm_term=Pinia%E8%AF%A6%E8%A7%A3&spm=1018.2226.3001.4187)
- 41.Mime
- 42.请求头中的key有哪些并标注常用的
- 42.tomcat8解决获取请求参数乱码
- 43.tomcat请求对象的初始化过程
16.前后端分离是怎么实现的?
-
API 设计与文档化
RESTful API 或 GraphQL 的设计:前后端通过API进行通信是前后端分离的核心特征之一。这通常包括定义清晰的资源路径、HTTP方法(GET, POST, PUT, DELETE等)以及请求和响应的数据格式(通常是JSON)。
API 文档化:使用工具如Swagger、Postman或GraphQL Playground生成详细的API文档,确保前端开发人员能够清楚地了解如何调用后端服务。 -
前端独立部署
前端项目独立构建和打包:前端项目使用构建工具(如Webpack、Vite、Parcel等)进行打包,并且可以独立于后端进行部署。这可能意味着前端代码被托管在CDN上,或者作为一个静态网站部署在服务器上。
SPA (Single Page Application):采用单页应用架构(如React、Vue.js、Angular等框架),页面之间的导航主要通过JavaScript动态加载内容,而不是重新加载整个页面。 -
跨域资源共享配置(CORS)
CORS 配置:由于前后端可能运行在不同的域名或端口上,需要正确配置跨域资源共享(CORS),以允许前端从特定的源访问后端资源。
-
使用版本控制系统并行开发
Git 分支管理:前后端团队使用版本控制系统(如Git)并行开发,前端和后端分别有自己的代码库或分支。通过良好的分支策略(如Git Flow)来协调集成和发布流程。
CI/CD 流水线:前后端各自拥有持续集成和持续交付(CI/CD)流水线,自动化测试、构建和部署过程。 -
安全机制的应用
身份验证与授权:采用现代的身份验证机制,如OAuth 2.0、JWT(JSON Web Token),确保只有经过认证的用户才能访问受保护的资源。
HTTPS 加密传输:所有通信都通过HTTPS加密,防止数据在传输过程中被窃听或篡改。 -
数据持久化与状态管理
前端状态管理:对于复杂的前端应用,可能会引入专门的状态管理库(如Redux、Vuex、MobX等)来管理和维护应用状态。
后端数据库操作:后端负责处理数据的持久化操作,通过ORM(对象关系映射)工具(如Hibernate、Sequelize、Mongoose等)简化数据库交互。
实际案例中的标志事件
假设一个电商网站正在实施前后端分离:
API 发布:后端团队首先完成了一套完整的RESTful API,涵盖了商品列表获取、购物车管理、订单处理等功能,并发布了详细的API文档。
前端独立部署:前端团队使用Vue.js搭建了用户界面,并通过Webpack构建了一个生产环境版本,部署在阿里云OSS上,实现了静态资源的快速加载。
跨域配置:由于前端部署在阿里云OSS,而后端部署在ECS上,因此配置了CORS,使得前端能够安全地访问后端API。
并行开发与CI/CD:前后端团队分别在各自的Git仓库中开发,每天都有自动化的构建和测试任务运行,保证代码质量。
安全措施:所有API请求均通过HTTPS传输,用户登录信息通过JWT存储在前端,每次请求时附带JWT到后端进行验证。
实现前后端分离的关键步骤和技术点:
-
技术栈选择
前端:通常使用HTML5、CSS3、JavaScript等技术构建用户界面。现代前端框架如React、Vue.js、Angular等极大地提高了开发效率和用户体验。
后端:可以采用各种编程语言和框架,如Java(Spring Boot)、Python(Django/Flask)、Node.js(Express/Koa)、Ruby on Rails等,专注于提供API接口和处理业务逻辑。 -
API设计与实现
前后端通过API进行通信,API的设计至关重要。常见的API类型有RESTful API和GraphQL:
RESTful API:基于HTTP协议的API设计风格,利用HTTP方法(GET, POST, PUT, DELETE等)对资源进行操作。每个资源都有一个唯一的URL标识。
GraphQL:一种查询语言和运行时环境,允许客户端精确地请求所需的数据,避免了过度获取或不足获取的问题。
- 数据交换格式
前后端之间常用的数据交换格式包括:
JSON:轻量级的数据交换格式,易于阅读和编写,广泛应用于Web应用中。
XML:较早的数据交换格式,现在用得相对较少,但在某些特定场景下仍然有用。
- 跨域资源共享(CORS)
由于浏览器的安全策略限制,跨域请求可能会被阻止。为了解决这个问题,后端需要正确配置CORS,允许特定来源的请求访问资源。
5. 开发流程与工具
版本控制:Git是最常用的版本控制系统,支持团队协作开发。
构建工具:如Webpack、Gulp等用于自动化前端项目的构建过程,包括代码压缩、合并、转译等。
部署:前后端可以独立部署,前端项目可以通过CDN加速,后端则部署在云服务器或容器环境中。
- 安全措施
确保API的安全性非常重要,常见的安全措施包括:
身份验证与授权:OAuth2.0、JWT(JSON Web Token)等机制用于保护API不受未经授权的访问。
HTTPS:加密传输数据,防止中间人攻击。
实现案例
假设我们正在开发一个博客系统:
前端:使用Vue.js创建用户界面,用户可以查看文章列表、阅读具体文章、发表评论等。
后端:使用Node.js + Express搭建RESTful API,提供文章管理、评论管理等功能。
通信:前端通过AJAX或Fetch API调用后端提供的RESTful接口,获取数据并动态更新页面内容。
这种方式使得前端开发者可以专注于UI/UX设计,而后端开发者可以专注于业务逻辑和数据处理,两者可以并行开发,互不干扰,大大提高了开发效率。同时,这样的架构也便于后期维护和扩展。
应用场景:
复杂的用户界面
如果应用需要提供非常复杂且动态的用户界面(如单页应用SPA),前后端分离可以提高用户体验,减少页面刷新次数,并允许更灵活的前端开发。
多客户端支持
当你需要为多个不同类型的客户端(如Web、移动App、桌面应用等)提供服务时,使用API与后端通信可以使各个客户端共享相同的业务逻辑和服务,从而减少重复开发的工作量。
团队规模较大
在大型项目中,前后端分离可以让前端和后端团队并行开发,各自专注于自己的领域,提高开发效率和协作效果。例如,前端团队可以使用现代框架和技术栈(如React、Vue.js),而后端团队则可以自由选择最适合的技术来处理业务逻辑和数据存储。
频繁迭代和快速发布
前后端分离有助于实现更快的迭代周期,因为前端和后端可以独立部署和更新。这使得新功能可以更快地推向市场,同时降低了对现有系统的风险。
高并发和分布式系统
对于需要处理大量并发请求或构建分布式系统的应用场景,前后端分离可以更好地优化性能和可扩展性。例如,通过微服务架构将不同的业务模块拆分为独立的服务,每个服务都可以拥有自己的前端展示层。
17.Servlet 和 Socket 区别
1.设计目的:
- Servlet是为了解决服务端处理客户端请求的问题,特别是针对Web应用程序。通常用于构建动态(查数据库)网页内容或者提供RESTful服务。
- Socket套接字是用于在网络中建立两个进程之间的通信连接,用于用来实现各种网络协议,不仅仅限于HTTP。
2.协议支持:
- Servlet主要支持Http,也支持其他基于文本的协议
- Socket支持TCP/IP和UDP协议,允许开发者根据需求选择合适的传输层协议
3.使用场景:
- 当你需要开发一个响应HTTP请求(如GET,POST等)的Web应用时,Servlet是一个合适的选择
- 更加通用,适用于需要定制化网络协议的APP,如即时通讯软件、在线游戏服务器。
4.部署环境:
- Servlet需要在支持JavaEE的应用服务器上运行,比如Tomcat、Jetty等
18.为什么对于特别复杂的需求Servlet很难处理,怎么提前创建
- 代码复杂性和可读性
问题:
低层次的抽象:Servlet API 提供的是相对较低层次的抽象,开发者需要手动处理很多细节,如请求解析、响应生成、会话管理等。
冗长的代码:处理复杂的业务逻辑时,代码量会迅速增加,导致代码变得冗长且难以维护。
示例:
在 Servlet 中处理一个复杂的表单提交可能需要手动解析请求参数、验证输入、处理业务逻辑、生成响应内容等,每一步都需要编写大量代码。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String param1 = request.getParameter("param1");
String param2 = request.getParameter("param2");
// 参数验证
if (param1 == null || param1.isEmpty()) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "param1 is required");
return;
}
// 处理业务逻辑
try {
service.someComplexBusinessLogic(param1, param2);
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
return;
}
// 生成响应
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>Success</h1>");
out.println("</body></html>");
}
- 缺乏模板引擎支持
问题:
视图层分离不足:Servlet 主要用于处理请求和生成响应,但生成 HTML 等视图内容通常需要嵌入到 Java 代码中,这使得视图层与业务逻辑层难以分离。
视图渲染困难:直接在 Servlet 中拼接 HTML 字符串不仅容易出错,还难以维护和扩展。
解决方案:
现代框架如 Spring MVC 提供了模板引擎(如 Thymeleaf、Freemarker)来分离视图和控制器,使代码更清晰和易于维护。
3. 状态管理和会话管理
问题:
手动管理状态:在 Servlet 中,会话管理需要手动处理,如获取和设置会话属性、处理会话超时等。
状态一致性:复杂的业务场景中,保持多个请求之间的状态一致性和同步是一个挑战。
示例:
在一个购物车系统中,手动管理用户的购物车状态可能会涉及大量的代码来处理添加商品、删除商品、更新数量等操作。
4. 依赖注入和支持库
问题:
缺乏依赖注入支持:Servlet 不直接支持依赖注入(DI),这使得管理依赖关系变得更加复杂。
缺少高级功能:缺乏对事务管理、缓存、安全性等功能的支持,开发者需要自己实现这些功能。
解决方案:
Spring 框架提供了强大的依赖注入机制和其他高级功能,简化了依赖管理和业务逻辑的实现。
5. 异步处理和非阻塞I/O
问题:
同步处理限制:Servlet 默认是同步处理请求的,对于高并发场景,同步处理会导致性能瓶颈。
异步编程复杂性:虽然 Servlet 3.0 引入了异步支持,但在传统 Servlet 编程中实现异步处理仍然较为复杂。
示例:
在一个需要处理长时间运行的任务(如文件上传或外部API调用)的应用中,使用传统的 Servlet 可能会导致线程阻塞,影响应用的整体性能。
6. 测试和调试
问题:
单元测试困难:由于业务逻辑和请求处理代码紧密耦合,编写单元测试变得困难。
集成测试复杂:集成测试需要模拟完整的 HTTP 请求和响应,增加了测试的复杂度。
解决方案:
现代框架通常提供更好的测试支持,如 Spring 提供了 MockMvc 工具,方便进行单元测试和集成测试。
总结
尽管 Servlet 是构建 Web 应用的基础技术,但对于特别复杂的需求,它存在以下局限性:
代码复杂性和可读性差
视图层和业务逻辑难以分离
状态管理和会话管理复杂
缺乏依赖注入和高级功能支持
异步处理和非阻塞I/O实现困难
测试和调试不便
因此,在处理复杂需求时,通常会选择更高层次的框架,如 Spring Boot 或 Spring MVC,它们提供了更多的抽象、依赖注入、模板引擎、异步处理等功能,能够显著提高开发效率和代码质量。这些框架基于 Servlet 规范之上,进一步简化了开发过程,并提供了更丰富的功能支持。
Servlet默认情况下,我们第一次访问servlet的时候,tomcat会初始化;高并发会慢;
提前创建:
<load-on-startup>创建序号</load-on-startup> //此标签已经实现了此前创建
19.什么是JavaWeb中特别复杂的需求?
-
复杂的业务逻辑
示例:电商平台多模块集成:需要处理用户管理、商品管理、订单管理、支付系统、物流跟踪等多个模块。
交易流程:从商品浏览、加入购物车、结算、支付到订单确认、发货、退货等,每个步骤都有严格的业务规则和状态转换。
促销活动:支持多种促销方式(如满减、折扣、优惠券),并且这些促销活动可能有复杂的叠加规则。
特点:
多层次的业务逻辑:不同模块之间的交互频繁且复杂。
事务一致性:确保在分布式环境下数据的一致性和完整性。
高并发处理:需要应对大量用户的并发访问,尤其是在促销活动期间。
-
大规模数据处理与分析
示例:大数据分析平台数据收集与存储:从多个数据源(如数据库、日志文件、外部API)收集数据,并将其存储在分布式存储系统中。
数据分析:对海量数据进行实时或离线分析,生成报表和可视化结果。
机器学习模型部署:将训练好的机器学习模型部署到生产环境中,提供预测服务。
特点:
大数据处理框架:需要使用Hadoop、Spark等大数据处理框架来处理海量数据。
实时性要求:某些场景下需要实时处理数据并反馈结果。
高性能计算:需要优化算法和硬件资源以提高计算效率。
-
高并发和高性能要求
示例:社交网络平台用户注册与登录:支持大量用户的注册、登录和身份验证。
动态内容发布:允许用户发布动态、评论、点赞等操作,并实时更新给其他用户。
消息推送:实现即时通讯功能,支持一对一和群组聊天。
特点:
高并发请求:需要处理大量并发请求,保证系统的响应速度。
负载均衡:通过负载均衡技术分发请求,避免单点故障。
缓存机制:利用Redis等缓存技术减少数据库查询压力,提高响应速度。
-
微服务架构
示例:企业级应用模块化设计:将不同的业务模块拆分为独立的服务,如用户服务、订单服务、库存服务等。
服务间通信:服务之间通过RESTful API、gRPC等方式进行通信。
服务治理:实现服务注册与发现、负载均衡、熔断降级等功能。
特点:
分布式系统:各个服务可以独立部署和扩展,但增加了系统的复杂度。
服务协调:需要使用服务网格(如Istio)、服务注册中心(如Eureka)等工具进行服务管理和协调。
监控与日志:需要完善的监控和日志系统来跟踪服务运行状态,及时发现问题。
-
安全性与合规性
示例:金融交易平台用户认证与授权:实现多因素认证(MFA)、OAuth2.0等安全认证机制。
数据加密:对敏感数据进行加密存储和传输,防止数据泄露。
审计与合规:记录所有关键操作的日志,确保符合行业标准和法规要求。
特点:
严格的安全措施:需要遵循一系列安全标准和最佳实践。
权限管理:精细的权限控制,确保不同角色只能访问其应有的资源。
合规审计:定期进行安全审计,确保系统符合相关法律法规。
-
跨平台与移动端支持
示例:移动办公应用跨平台开发:支持多种操作系统(如iOS、Android)和设备类型(手机、平板)。
同步与离线支持:在没有网络连接时也能正常使用部分功能,并在网络恢复后自动同步数据。
推送通知:实现实时的消息推送功能,提醒用户重要事件。
特点:
响应式设计:界面需要适应不同的屏幕尺寸和分辨率。
本地存储:利用SQLite等本地数据库存储临时数据,提升用户体验。
数据同步:确保数据在不同设备间的一致性和同步性。
-
国际化与本地化
示例:全球电商网站多语言支持:提供多种语言版本的界面和内容,方便不同国家和地区用户使用。
货币与支付方式:支持多种货币和支付方式,满足不同地区的用户需求。
文化差异:考虑不同国家和地区的文化和法律差异,如日期格式、隐私政策等。
特点:
语言包管理:需要维护多个语言包,并根据用户选择的语言动态加载相应的资源。
区域设置:根据不同地区调整显示内容和功能。
法律法规:遵守各地的法律法规,如GDPR(欧盟《通用数据保护条例》)。
总结
特别复杂的需求通常具有以下几个共同特征:
多层次的业务逻辑:涉及多个模块和子系统的协同工作。
高并发和高性能要求:需要处理大量并发请求,并保证系统的快速响应。
分布式架构:采用微服务或其他分布式架构,增加系统的灵活性和扩展性。
安全性与合规性:需要严格的安全措施和合规审计,确保数据和系统的安全。
用户体验:注重用户体验,提供跨平台支持、多语言支持等高级功能。
20.为什么@WebServlet可以代替配置文件?
Servlet 容器启动时的扫描
当 Servlet 容器(如 Tomcat)启动时,它会扫描应用中的所有类,查找带有 @WebServlet 注解的类。这个过程通常称为“类路径扫描”或“注解扫描”。
具体步骤:
初始化容器:Servlet 容器在启动时会加载并初始化 Web 应用程序。
扫描类路径:容器会扫描应用的类路径,查找所有的 .class 文件。
查找注解:对于每个找到的类,容器会检查其是否包含 @WebServlet 注解。
注册 Servlet:如果发现某个类带有 @WebServlet 注解,容器会根据注解中的信息注册该 Servlet,并将其与指定的 URL 模式关联。
2.2 反射机制
Servlet 容器使用 Java 的反射机制来读取注解信息,并动态地创建和管理 Servlet 实例。
具体步骤:
获取注解信息:通过反射 API 获取类上的 @WebServlet 注解。
Class<?> clazz = HelloServlet.class;
if (clazz.isAnnotationPresent(WebServlet.class)) {
WebServlet annotation = clazz.getAnnotation(WebServlet.class);
String name = annotation.name();
String[] urlPatterns = annotation.urlPatterns();
// 使用这些信息注册 Servlet
}
实例化 Servlet:根据注解中的信息,容器会创建该类的一个实例,并将其注册到 Servlet 映射表中。
处理请求:当有 HTTP 请求到达时,容器会根据 URL 路径匹配相应的 Servlet,并调用其 doGet, doPost 等方法来处理请求。
- 注解属性详解
@WebServlet 注解提供了多个属性,用于配置 Servlet 的行为。以下是一些常用的属性:
3.1 name
作用:指定 Servlet 的名称。
默认值:如果没有指定,默认名称为类的全限定名。
3.2 urlPatterns
作用:指定该 Servlet 的 URL 映射模式。可以是一个字符串数组,表示多个映射路径。
示例:
@WebServlet(urlPatterns = {“/hello”, “/greeting”})
3.3 loadOnStartup
作用:指定 Servlet 的加载顺序。正值表示在容器启动时加载;负值或未指定表示按需加载。
示例:
@WebServlet(urlPatterns = “/hello”, loadOnStartup = 1)
3.4 asyncSupported
作用:启用异步支持。默认为 false。
示例:
@WebServlet(urlPatterns = "/hello", asyncSupported = true)
3.5 initParams
作用:定义初始化参数。可以传递给 Servlet 的 init 方法。
示例:
@WebServlet(urlPatterns = "/hello", initParams = {
@WebInitParam(name = "param1", value = "value1"),
@WebInitParam(name = "param2", value = "value2")
})
21.Tomcat 处理servlet流程
tomcat启动——扫描tomcat中的web.xml文件——读入内存——开启配置端口——等待客户端连接。
客户端(浏览器)发送请求——tomcat接收请求——分析请求路径——检查webapps目录下WEB-INF下的xml文件是否有路径相关映射 (如下)——创建request和response对象——根据映射动态加载servlet-name.class——调用service()方法,传递request、response对象——执行完毕——tomcat从缓冲区获取信息和http响应信息拼接——返回给浏览器
浏览器解析响应信息——页面展示
22.web.xml的映射关系
url-pattern -> servlet-name -> servlet.class
23.servlet的动态加载过程
同@WebServlet工作原理,类路径扫描
24.servlet的三种映射路径配置
分类 | 格式 | 说明 |
---|---|---|
精准匹配(完全匹配) | /servlet1 | 访问的时候必须通过servlet1访问 |
目录匹配(需要到Filter会用到) | /目录名/* | 访问的时候路径上必须带我们写的目录名,想用于用目录名给多个请求分类了 |
后缀名匹配(需要到spingmvc会用到) | *.action | 只要是路径上带.action的都可以访问到对应的servlet |
25.servlet容器的service()方法有什么用?区别于servlet.service()容器的 service() 方法主要负责将请求分配给正确的 Servlet 实例,并调用其 service() 方法。
主要职责:
请求分发:根据请求的 URL 模式匹配到相应的 Servlet 实例。
调用 Servlet 的 service() 方法:将请求对象和响应对象传递给对应的 Servlet 实例的 service() 方法。
具体流程:
接收请求:容器接收到客户端的 HTTP 请求。
查找映射:根据请求的 URL 路径查找匹配的 Servlet 实例。
调用 service() 方法:将请求和响应对象传递给找到的 Servlet 实例的 service() 方法。
-
区别与联系
区别:位置不同:
Servlet 接口和 HttpServlet 类中的 service() 方法是属于 Servlet 实现类的一部分,由开发者实现或扩展。
容器中的 service() 方法是容器内部的逻辑,负责请求的分发和调用。功能不同:
Servlet 类中的 service() 方法主要用于处理具体的请求逻辑,决定调用哪个具体的 doXXX() 方法(如 doGet(), doPost())。
容器中的 service() 方法主要用于将请求分发给正确的 Servlet 实例,并调用其 service() 方法。
联系:
协同工作:容器的 service() 方法最终会调用 Servlet 实例的 service() 方法,从而完成整个请求处理过程。
统一入口:无论是通过 web.xml 配置还是注解配置,所有的请求都会经过容器的 service() 方法,再传递给具体的 Servlet 实例的 service() 方法。
- 示例代码
26.servletResponse对象的getWriter()方法为什么不是setString
getWriter().write()事实上会输出一个OutputStream对象 而不是String对象
27.为什么Http2.0大幅提升了Web性能?
HTTP/2.0(简称 HTTP/2)引入了多项技术改进,显著提升了 Web 性能。以下是 HTTP/2 相对于其前身 HTTP/1.1 的主要改进及其对性能提升的具体原因:
- 多路复用(Multiplexing)
改进:
在 HTTP/1.1 中,每个请求和响应都需要建立一个新的 TCP 连接,或者使用持久连接(Keep-Alive)。然而,即使使用持久连接,浏览器仍然受限于每个主机的并发连接数(通常为6个),这会导致队头阻塞(Head-of-Line Blocking),即一个请求的延迟会影响后续请求的处理。
HTTP/2 引入了多路复用技术,允许在一个 TCP 连接上同时发送多个请求和响应。这意味着多个请求可以交错发送,并且响应也可以交错接收,而不需要等待前一个请求完成。
性能提升:
减少延迟:由于不再需要为每个请求建立新的连接,减少了连接建立的时间。
消除队头阻塞:通过多路复用,单个请求的延迟不会影响其他请求的处理。
- 头部压缩(Header Compression)
改进:
HTTP 请求和响应通常包含大量的头部信息(如 User-Agent、Cookies 等),这些头部信息在每次请求中都会重复传输,增加了不必要的带宽消耗。
HTTP/2 使用 HPACK(HTTP Header Compression for HTTP/2)算法对头部进行压缩。HPACK 利用静态表和动态表来编码和解码头部字段,减少了传输的数据量。
性能提升:
减少带宽消耗:通过压缩头部信息,减少了传输的数据量,尤其是在移动网络等带宽有限的情况下效果尤为明显。
加快页面加载速度:减少了传输时间,使得页面能够更快地加载。
- 服务器推送(Server Push)
改进:
在传统的 HTTP/1.1 中,客户端必须显式发起请求才能获取资源。例如,当浏览器请求一个 HTML 页面时,它需要解析该页面并发现其中引用的 CSS 和 JavaScript 文件,然后分别发起请求。
HTTP/2 引入了服务器推送机制,允许服务器在收到客户端请求之前主动推送资源到客户端缓存中。例如,当服务器检测到客户端即将请求某个资源时,可以提前将该资源推送到客户端。
性能提升:
减少往返次数:通过预先推送资源,减少了客户端发起额外请求的次数,从而减少了网络往返时间(RTT)。
提高首次渲染速度:关键资源(如 CSS 和 JavaScript 文件)可以在页面加载初期就准备好,提高了页面的首次渲染速度。
- 二进制协议(Binary Protocol)
改进:
HTTP/1.1 使用基于文本的协议,解析和处理文本协议相对复杂且容易出错。此外,文本协议在传输过程中可能会遇到字符编码等问题。
HTTP/2 采用了二进制协议格式,使得数据帧更加紧凑且易于解析。二进制协议还支持更复杂的帧结构,如数据帧、控制帧等,提供了更多的灵活性。
性能提升:
高效解析:二进制协议比文本协议更容易解析,减少了 CPU 开销。
减少错误:避免了文本协议中的字符编码问题,减少了潜在的错误。
- 流优先级(Stream Prioritization)
改进:
在 HTTP/1.1 中,所有请求的优先级相同,无法根据实际需求调整不同资源的加载顺序。例如,在加载网页时,CSS 和 JavaScript 文件可能比图片更重要,但它们的加载顺序无法灵活控制。
HTTP/2 允许为不同的请求设置优先级,确保关键资源(如 HTML、CSS 和 JavaScript 文件)优先加载,而非关键资源(如图片)可以在后台加载。
性能提升:
优化资源加载顺序:通过设置优先级,确保关键资源优先加载,提高了页面的首次渲染速度。
改善用户体验:用户可以更快地看到页面内容,减少了等待时间。
- 更好的安全性
虽然不是直接提升性能的因素,但 HTTP/2 通常与 HTTPS 一起使用,强制要求加密通信。HTTPS 提供了更高的安全性,同时也带来了一些间接的性能优势:
TLS 协议优化:现代 TLS 实现经过优化,能够在初始握手后提供高效的加密通信,减少了额外的开销。
减少中间人攻击的风险:安全的通信减少了中间人攻击的可能性,保证了数据的完整性和机密性。
- 减少连接管理开销
改进:
在 HTTP/1.1 中,为了支持并发请求,浏览器通常会为同一个域名打开多个 TCP 连接。每个连接都需要进行三次握手(TCP 握手)和 SSL/TLS 握手(如果使用 HTTPS),这增加了连接管理的开销。
HTTP/2 通过多路复用技术,只需要一个 TCP 连接就可以处理多个请求和响应,减少了连接管理的开销。
性能提升:
减少握手次数:通过减少连接数量,减少了 TCP 和 SSL/TLS 握手的次数,降低了连接建立的时间。
降低网络拥塞:减少了并发连接的数量,降低了网络拥塞的可能性。
总结
HTTP/2 引入了多项技术改进,从多路复用、头部压缩、服务器推送、二进制协议到流优先级,这些改进共同作用,大幅提升了 Web 性能。具体来说:
减少延迟:通过多路复用和减少连接数量,减少了请求和响应的延迟。
节省带宽:通过头部压缩和更高效的协议格式,减少了传输的数据量。
提高加载速度:通过服务器推送和流优先级,优化了资源的加载顺序和效率。
28.Tomcat三大域 分别有什么用?
- ServletContext
容器快照,存放信息 - HttpSession
存放用户信息 - HttpServletRespons
存放请求信息
30.SevletContext如果是所有servlet共享,那么网络聊天是怎么实现的?
WebSocket
跟tomcat中的EndPoint有什么联系和区别
31.@WebServlet(“/targetUrl”)默认servlet-name是什么?
是Servlet的全限定名
32.Ajax
33.ES6概述
ES6,全称ECMAScript 2015,是JavaScript语言的一个重要版本更新。它引入了许多新特性,使JavaScript更加现代化和强大。
发展历程:
2015年:正式发布,带来了诸如let和const关键字、箭头函数、模板字符串、解构赋值、模块化(import/export)、类语法等。
后续版本:每年都会发布一个新版本(如ES7, ES8等),持续增加新的功能和改进现有功能。
34.Node概述
Node.js是一个基于Chrome V8引擎的JavaScript运行环境,允许开发者使用JavaScript编写服务器端代码。
发展历程:
2009年:由Ryan Dahl首次发布,最初目的是为了实现非阻塞I/O操作。
2010年:npm(Node Package Manager)被集成到Node.js中,极大地简化了包管理和依赖关系处理。
近年来:Node.js已经成为构建高效网络应用和服务的标准之一,广泛应用于企业级开发。
35.NPM概述
概述:
NPM是Node.js默认的包管理工具,用于安装、分享和管理JavaScript库和框架。
发展历程:
2010年:随着Node.js的推出而出现,最初是为了方便Node.js生态系统的扩展。
2014年:NPM注册表成为世界上最大的软件注册表之一。
现在:不仅是Node.js项目的包管理器,也被广泛用于前端项目和其他JavaScript相关项目。
36.Vue3概述
概述:
Vue.js是一个渐进式JavaScript框架,用于构建用户界面。Vue 3是其最新主要版本,带来了性能优化和新的API设计。
发展历程:
2014年:Vue.js首次发布。
2020年:Vue 3正式发布,带来了Composition API、Teleport、Fragments等功能,并显著提升了性能。
目前:Vue 3已经成为许多现代Web应用的选择,特别是在需要快速开发和灵活组件结构的情况下。
37.Vue Router
概述:
Vue Router是官方推荐的Vue.js路由管理器,用于支持单页应用(SPA)中的导航和视图切换。
发展历程:
早期版本:随着Vue.js的发展,Vue Router也逐步完善,提供了历史模式、嵌套路由、导航守卫等功能。
Vue 3版本:与Vue 3同步更新,提供更好的兼容性和性能优化。
38.Promise
概述:
Promise是处理异步操作的一种方式,代表一个异步操作的最终完成(或失败)及其结果值。
发展历程:
ES6:Promise作为标准的一部分被引入,旨在简化异步编程模型。
之前:通过回调函数实现异步操作,但容易导致“回调地狱”问题。
现在:Promise已成为JavaScript异步编程的基础,结合async/await进一步简化了代码。
39.Axios
概述:
Axios是一个基于Promise的HTTP客户端,可用于浏览器和Node.js进行HTTP请求。
发展历程:
2014年:由Matt Zabriskie创建并开源。
近年来:因其易用性和丰富的功能(如拦截器、自动转换JSON数据等)而广受欢迎,成为处理AJAX请求的首选库之一。
40.Pinia
概述:
Pinia是Vue.js的下一代状态管理库,旨在提供更简洁、直观的状态管理模式。
发展历程:
2021年:由Eduardo San Martin Morote(Vue核心团队成员)发起并开发。
特点:相比Vuex,Pinia具有更少的概念和更自然的API设计,支持插件系统和TypeScript友好性。
现状:正在逐渐取代Vuex成为Vue.js项目中的主流状态管理解决方案,尤其是在Vue 3项目中。
41.Mime
1、MIME是什么
MIME(Multipurpose Internet Mail Extensions)是一种互联网标准,通用互联网邮件扩充,用于扩展电子邮件的格式,使其能够处理不仅仅是ASCII文本的多种内容类型。随着互联网的发展,MIME的应用已超越了电子邮件,广泛用于Web和其他协议中,以便正确地传输和识别不同类型的数据。
2、MIME类型的结构
MIME类型通常由两部分组成:主类型和子类型,格式为 主类型/子类型。例如:
text/html:表示HTML文档。
image/jpeg:表示JPEG格式的图片。
application/json:表示JSON格式的数据。
3、实际应用示例
在Web开发中,服务器会根据返回的内容类型设置HTTP响应头中的Content-Type字段。例如,当用户请求一个HTML页面时,服务器会返回如下响应头:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
这告诉浏览器,接收到的内容是HTML文档,并使用****字符集编码。浏览器接收到此信息后,会根据指定的MIME类型正确处理内容。
4、处理文件上传
当用户上传文件时,浏览器会在请求中发送文件的MIME类型。例如,用户上传了一张PNG格式的图片,浏览器可能会发出如下请求:
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
在上传的表单数据中,PNG文件的MIME类型通常会被指定为:
arduino 代码解读复制代码Content-Type: image/png
服务器处理时可以根据MIME类型确定文件的格式,从而进行相应的存储和处理。
5、MIME在HTTP中的重要性
在HTTP协议中,MIME类型不仅用于内容的标识,还影响内容的渲染和处理。例如,文本文件以text/plain MIME类型返回时,浏览器会以纯文本的方式显示。而如果是application/json,浏览器则会将其作为JSON对象处理,而不会直接显示。
42.请求头中的key有哪些并标注常用的
常用请求头字段
Host: 必需。指定请求的目标主机和端口。这是HTTP/1.1协议中要求必须提供的头部。
User-Agent: 标识发起请求的客户端软件的信息,包括浏览器类型、版本号等。这对于服务器根据不同的用户代理提供特定内容非常有用。
Accept: 客户端可以接受的内容类型列表,如text/html, application/json等。这有助于服务器决定返回何种格式的数据。
Accept-Language: 客户端偏好的自然语言设置,帮助服务器选择合适的语言版本响应请求。
Accept-Encoding: 客户端支持的内容编码方式,如gzip, deflate等,用于告知服务器可以对响应体进行压缩以减少传输量。
Connection: 指定该连接是保持打开状态还是关闭。值为keep-alive时,表示希望保持连接一段时间以便后续请求复用。
Content-Type: 当使用POST或PUT方法发送数据时,用来说明请求体中的数据格式,比如application/x-www-form-urlencoded, multipart/form-data, 或者application/json。
Content-Length: 表示请求体的大小(字节数)。对于一些不使用chunked传输编码的请求是必需的。
其他常见请求头字段
Referer: 包含当前页面的来源URL(即从哪个页面链接过来的),可用于统计分析、防盗链等用途。
Origin: 在跨域请求中,用于指示请求的来源域,配合CORS(跨源资源共享)机制使用。
Authorization: 用于传递认证凭据,通常与Basic Auth或Bearer Token一起使用。
Cookie: 客户端向服务器发送的存储在本地的cookie信息,用于维持会话状态或个性化设置。
If-Modified-Since / If-Unmodified-Since: 这些条件请求头部允许客户端仅在资源自指定日期以来已修改或未修改的情况下获取资源的新副本。
Cache-Control: 控制缓存的行为,如no-cache, no-store, max-age等指令来指导中间缓存如何处理响应。
42.tomcat8解决获取请求参数乱码
1.为啥会乱码:
编码和解码遵循的编码规则不一样
2.乱码原因和tomcat的解码方式有关系:
tomcat10直接采用的UTF-8
tomcat解码主要是解析url中的参数
3.tomcat8开始对get请求做了优化:
如果是get请求,参数在url上,直接用UTF-8解析
但是post请求,tomcat无法解析,中文就会乱码
4.解决:
让服务器知道具体用什么编码去解析请求
request.setCharacterEnCoding("UTF-8");//将获取到的请求参数变为UTF-8格式
response.setContentType("text/html;charset=UTF-8");
43.tomcat请求对象的初始化过程
请求处理流程
接收请求:
当客户端发送一个 HTTP 请求到服务器时,Tomcat 的 Connector 组件会首先接收到这个请求。Connector 负责将网络字节流转换为 Tomcat 内部可以处理的对象。
解析请求:
Connector 将原始的网络数据包解析为标准的 HTTP 请求,并将其封装成一个 Request 对象(注意,这里的 Request 是 Tomcat 内部的一个类,而不是 HttpServletRequest)。
创建 HttpServletRequest 和 HttpServletResponse 对象:
在 CoyoteAdapter 类中,Tomcat 会将内部的 Request 对象包装成符合 Servlet 规范的 HttpServletRequest 对象。具体来说,CoyoteAdapter 会调用 org.apache.catalina.connector.Connector 的 createRequest() 方法来创建 HttpServletRequest 实例。
同样地,也会创建一个 HttpServletResponse 对象,用于封装响应信息。
传递给容器:
创建好 HttpServletRequest 和 HttpServletResponse 对象后,这些对象会被传递给 Container 层进行进一步处理。Tomcat 的容器层次结构包括 Engine, Host, Context, 和 Wrapper,每个层次负责不同的职责。
分派请求:
最终,请求会被分派到具体的 Servlet 进行处理。在这个过程中,Servlet 可以使用 request.getRequestDispatcher().forward() 来转发请求到另一个资源。
HttpServletRequest 对象的创建与初始化
创建时机:HttpServletRequest 对象是在请求到达 Tomcat 的 Connector 层时创建的,具体是在 CoyoteAdapter 中完成的。
初始化内容:初始化过程中,HttpServletRequest 对象会被填充各种请求相关的数据,如请求方法、请求URI、请求头、请求参数等。
生命周期管理:HttpServletRequest 对象的生命周期从请求到达 Tomcat 开始,直到请求处理完毕并生成响应为止。
request.getRequestDispatcher().forward() 的执行流程
当你在 Servlet 中调用 request.getRequestDispatcher().forward(request, response) 时:
获取 RequestDispatcher:
request.getRequestDispatcher() 方法会根据提供的路径找到对应的资源(如 JSP 页面或另一个 Servlet),并返回一个 RequestDispatcher 对象。
转发请求:
调用 forward() 方法时,当前的 HttpServletRequest 和 HttpServletResponse 对象会被传递给目标资源。
目标资源会继续处理请求,并生成相应的响应。注意,forward() 不会结束当前请求,而是让请求在新的资源上继续处理。
总结
虽然 HttpServletRequest 对象最终是由 Service 容器中的某个层次(具体是 CoyoteAdapter 和 Connector)创建并初始化的,但它并不是直接由 Service 容器本身创建的。整个过程涉及多个组件的合作,包括 Connector 解析请求、CoyoteAdapter 包装请求、以及 Container 层处理请求并将它们分派给合适的 Servlet 或其他资源。
这种设计确保了请求可以在不同层次之间高效地传递和处理,同时也遵循了 Servlet 规范的要求。