当前位置: 首页 > news >正文

手写模拟SpringBoot核心流程(二):实现Tomcat和Jetty的切换

实现Tomcat和Jetty的切换

前言

上一篇文章我们聊到,SpringBoot中内置了web服务器,包括Tomcat、Jetty,并且实现了SpringBoot启动Tomcat的流程。

那么SpringBoot怎样自动切换成Jetty服务器呢?

接下来我们继续学习如何实现Tomcat和Jetty的自动切换。

定义WebServer接口并实现

package com.ber.springboot;  import org.springframework.web.context.WebApplicationContext;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 19:44  * @Version 1.0  */public interface WebServer {  void start(WebApplicationContext applicationContext);  
}

将BerSpringApplication类中startTomcat写到TomcatWebServer实现类中。

package com.ber.springboot;  import org.apache.catalina.*;  
import org.apache.catalina.connector.Connector;  
import org.apache.catalina.core.StandardContext;  
import org.apache.catalina.core.StandardEngine;  
import org.apache.catalina.core.StandardHost;  
import org.apache.catalina.startup.Tomcat;  
import org.springframework.web.context.WebApplicationContext;  
import org.springframework.web.servlet.DispatcherServlet;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 19:45  * @Version 1.0  */  
public class TomcatWebServer implements WebServer{  @Override  public void start(WebApplicationContext applicationContext) {  System.out.println("启动Tomcat");  Tomcat tomcat = new Tomcat();  Server server = tomcat.getServer();  Service service = server.findService("Tomcat");  Connector connector = new Connector();  connector.setPort(8023);  Engine engine = new StandardEngine();  engine.setDefaultHost("localhost");  Host host = new StandardHost();  host.setName("localhost");  String contextPath = "";  Context context = new StandardContext();  context.setPath(contextPath);  context.addLifecycleListener(new Tomcat.FixContextListener());  host.addChild(context);  engine.addChild(host);  service.setContainer(engine);  service.addConnector(connector);  tomcat.addServlet(contextPath, "dispatcher", new DispatcherServlet(applicationContext));  context.addServletMappingDecoded("/*", "dispatcher");  try {  tomcat.start();  } catch (LifecycleException e) {  e.printStackTrace();  }  }  
}

JettyWebServer类同样实现WebServer接口,不过具体启动Jetty代码省略,不在本文探讨范围内。

package com.ber.springboot;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 19:46  * @Version 1.0  */  
public class JettyWebServer implements WebServer{  @Override  public void start() {  System.out.println("启动Jetty");  }  
}

修改BerSpringApplication类

package com.ber.springboot;  import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;  import java.util.Map;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 14:08  * @Version 1.0  */  
public class BerSpringApplication {  public static void run(Class clazz) {  // 1. 创建Spring 容器  AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();  applicationContext.register(clazz);  applicationContext.refresh();  // 2. 获取特定WebServer类型的Bean  WebServer webServer = getWebServer(applicationContext);  // 3. 调用start方法  webServer.start(applicationContext);  }  private static WebServer getWebServer(AnnotationConfigWebApplicationContext applicationContext) {  // key为beanName, value为Bean对象  Map<String, WebServer> webServers = applicationContext.getBeansOfType(WebServer.class);  if (webServers.isEmpty()) {  throw new NullPointerException();  }  if (webServers.size() > 1) {  throw new IllegalStateException();  }  return webServers.values().stream().findFirst().get();  }  
}

在run方法中,获取到特定的web服务器,并通过start方法进行 启动。

getWebServer方法实现判断web服务器,并处理特殊情况——没有web服务器或者出现多个web服务器。

条件注解

package com.ber.springboot;  import org.springframework.context.annotation.Conditional;  import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 20:06  * @Version 1.0  */  
@Target({ElementType.TYPE, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Conditional(BerOnClassConsition.class)  
public @interface BerConditionalOnClass {  String value() default "";  
}

具体步骤为:

  1. 拿到@BerConditionalOnClass中的value属性
  2. 类加载器进行加载,加载到了特定的类名,则符合条件;否则不符合条件
package com.ber.springboot;  import org.springframework.context.annotation.Condition;  
import org.springframework.context.annotation.ConditionContext;  
import org.springframework.core.type.AnnotatedTypeMetadata;  import java.util.Map;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 20:08  * @Version 1.0  */  
public class BerOnClassConsition implements Condition {  @Override  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {  Map<String, Object> annotationAttributes =  metadata.getAnnotationAttributes(BerConditionalOnClass.class.getName());  // 1. 拿到@BerConditionalOnClass中的value属性  String className = (String) annotationAttributes.get("value");  // 2. 类加载器进行加载  try {  // 2.1 加载到了特定的类名,则符合条件 true            context.getClassLoader().loadClass(className);  return true;  } catch (ClassNotFoundException e) {  // 2.2 加载不到,则不符合条件 false            return false;  }  }  
}

自动配置类

package com.ber.springboot;  import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 20:34  * @Version 1.0  */  
@Configuration  
public class WebServiceAutoConfiguration implements AutoConfiguration{  @Bean  @BerConditionalOnClass("org.apache.catalina.startup.Tomcat")  public TomcatWebServer tomcatWebServer() {  return new TomcatWebServer();  }  @Bean  @BerConditionalOnClass("org.eclipse.jetty.server.Server")  public JettyWebServer jettyWebServer() {  return new JettyWebServer();  }  
}

自动配置类在Spring Boot应用程序中起着关键的作用,它们是实现自动化配置的核心组件。

这里定义满足各自条件的Bean,当org.apache.catalina.startup.Tomcat类存在时,TomcatWebServer的Bean才存在,另一个亦是如此。

当spring容器存在Bean时,就可以通过BerSpringApplication类getWebServer方法中的applicationContext.getBeansOfType(WebServer.class)获取到,并由此可以进行对web服务器是否存在的判断。

SPI机制发现WebServiceAutoConfiguration

刚刚我们定义了自动配置类,但运行user模块的Userapplication启动类时,发现是无法发现WebServiceAutoConfiguration配置类的。

这是因为我们传入了Userapplication作为配置类,扫描路径为Userapplication所在的包路径,是无法扫描到WebServiceAutoConfiguration类的。

在springboot中实现了类似SPI的思想,就是项目中的spring.factories文件,提供了一种可插拔的扩展机制,使开发人员能够轻松地定制应用程序的行为和功能,同时又能保持主应用程序的稳定性。

这里我们可以借助JDK的SPI机制实现发现WebServiceAutoConfiguration类。

在springboot模块中增加resources/META-INF/services/com.ber.springboot.AutoConfiguration文件,具体路径如图所示:

JDK的SPI.png

com.ber.springboot.WebServiceAutoConfiguration

增加AutoConfiguration接口类和实现类。

package com.ber.springboot;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 21:08  * @Version 1.0  */  
public interface AutoConfiguration {  
}
package com.ber.springboot;  import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 20:34  * @Version 1.0  */  
@Configuration  
public class WebServiceAutoConfiguration implements AutoConfiguration{  @Bean  @BerConditionalOnClass("org.apache.catalina.startup.Tomcat")  public TomcatWebServer tomcatWebServer() {  return new TomcatWebServer();  }  @Bean  @BerConditionalOnClass("org.eclipse.jetty.server.Server")  public JettyWebServer jettyWebServer() {  return new JettyWebServer();  }  
}

并在注解类@BerSpringBootApplication上增加@Import(BerImportSelect.class)注解,BerImportSelect类从com.ber.springboot.AutoConfiguration文件中获取类名,然后添加到spring容器。

package com.ber.springboot;  import org.springframework.context.annotation.DeferredImportSelector;  
import org.springframework.core.type.AnnotationMetadata;  import java.util.ArrayList;  
import java.util.List;  
import java.util.ServiceLoader;  /**  * @Author 鳄鱼儿  * @Description * @date 2023/8/19 21:15  * @Version 1.0  */  
public class BerImportSelect implements DeferredImportSelector {  @Override  public String[] selectImports(AnnotationMetadata importingClassMetadata) {  /** 使用Java的ServiceLoader机制加载实现了AutoConfiguration接口的类  * AutoConfiguration是Spring Boot中用于自动配置的接口  * AutoConfiguration的实现类通常包含了一些配置信息,帮助应用程序在不需要显式配置的情况下自动完成一些功能  */  ServiceLoader<AutoConfiguration> serviceLoader = ServiceLoader.load(AutoConfiguration.class);  List<String> list = new ArrayList<>();  for (AutoConfiguration autoConfiguration : serviceLoader) {  list.add(autoConfiguration.getClass().getName());  }  // 返回包含所有加载的AutoConfiguration实现类名的字符串数组  return list.toArray(new String[0]);  }  
}

添加Jetty依赖

修改user模块的依赖如下:

<?xml version="1.0" encoding="UTF-8"?>  
<project xmlns="http://maven.apache.org/POM/4.0.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <parent>  <artifactId>simulate-springboot</artifactId>  <groupId>org.example</groupId>  <version>1.0-SNAPSHOT</version>  </parent>  <modelVersion>4.0.0</modelVersion>  <artifactId>user</artifactId>  <properties>  <maven.compiler.source>8</maven.compiler.source>  <maven.compiler.target>8</maven.compiler.target>  </properties>  <dependencies>  <dependency>  <groupId>org.example</groupId>  <artifactId>springboot</artifactId>  <version>1.0-SNAPSHOT</version>  <exclusions>  <exclusion>  <groupId>org.apache.tomcat.embed</groupId>  <artifactId>tomcat-embed-core</artifactId>  </exclusion>  </exclusions>  </dependency>  <dependency>  <groupId>org.eclipse.jetty</groupId>  <artifactId>jetty-server</artifactId>  <version>9.4.43.v20210629</version>  </dependency>  </dependencies>  </project>

这里需要排除tomcat依赖,因为springboot中已经添加了tomcat的依赖。

不排除就会出来既有tomcat又有Jetty,就会出现IllegalStateException异常。

到此运行user模块的UserApplication类就可以啦。

相关文章:

手写模拟SpringBoot核心流程(二):实现Tomcat和Jetty的切换

实现Tomcat和Jetty的切换 前言 上一篇文章我们聊到&#xff0c;SpringBoot中内置了web服务器&#xff0c;包括Tomcat、Jetty&#xff0c;并且实现了SpringBoot启动Tomcat的流程。 那么SpringBoot怎样自动切换成Jetty服务器呢&#xff1f; 接下来我们继续学习如何实现Tomcat…...

Python土力学与基础工程计算.PDF-土的三项组成

5.3 Python求解 Python 求解代码如下&#xff1a; 1. # 定义已知参数 2. G_s 2.7 # 比重 3. w 0.2 # 含水量 4. e 0.6 # 孔隙比 5. gamma_w 9.81 # 水的重度 6. 7. # 根据公式计算饱和度 8. S_r G_s * w / e 9. print("饱和度为", S_r) 10. 11.…...

危化安全生产信息化平台在煤化领域的应用

一、背景介绍 煤化工行业是一个集煤炭、石油、化工等多种产业于一体的综合性行业&#xff0c;其特点是工艺流程复杂、设备繁多、安全隐患大。近年来&#xff0c;随着煤化工行业的快速发展&#xff0c;安全生产问题日益凸显。为了有效提高危化安全生产水平&#xff0c;某煤化工…...

Linux(CentOS)运维脚本工具集合

使用说明 备份指定目录 # 备份指定目录文件到指定目录,备份文件名称为&#xff1a;备份目录最后一层目录"_"日期.tar.gz # 第一个参数&#xff1a;backdir 第二参数&#xff1a;备份文件保存目录 第三个参数&#xff1a;备份目录/文件 sh script.sh backdir /root/…...

【Java alibabahutool】JSON、Map、实体对象间的相互转换

首先要知道三者的互转关系&#xff0c;可以先将JSON理解成是String类型。这篇博文主要是记录阿里巴巴的JSONObject的两个方法。toJSONString()以及parseObject()方法。顺便巩固Map与实体对象的转换技巧。 引入依赖 <!-- 阿里巴巴 JSON转换 以下二选一即可 没有去细研究两者…...

按软件开发阶段的角度划分:单元测试、集成测试、系统测试、验收测试

1.单元测试&#xff08;Unit Testing&#xff09; 单元测试&#xff0c;又称模块测试。对软件的组成单位进行测试&#xff0c;其目的是检验软件基本组成单位的正确性。测试的对象是软件里测试的最小单位&#xff1a;模块。 测试阶段&#xff1a;编码后或者编码前&#xff08;…...

【python】Leetcode(primer-dict-list)

文章目录 260. 只出现一次的数字 III&#xff08;字典 / 位运算&#xff09;136. 只出现一次的数字&#xff08;字典&#xff09;137. 只出现一次的数字 II&#xff08;字典&#xff09;169. 求众数&#xff08;字典&#xff09;229. 求众数 II&#xff08;字典&#xff09;200…...

网络安全(黑客)入门

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全…...

在CSS中,盒模型中的padding、border、margin是什么意思?

在CSS中&#xff0c;盒模型&#xff08;Box Model&#xff09;是用来描述和布局HTML元素的基本概念。它将每个HTML元素看作是一个矩形的盒子&#xff0c;这个盒子包括了内容&#xff08;content&#xff09;、内边距&#xff08;padding&#xff09;、边框&#xff08;border&a…...

有线耳机插入电脑没声音

有线耳机插入电脑没声音 首先确保耳机和电脑都没问题&#xff0c;那就有可能是声音输出设备设置错误 右击任务栏的声音图标-打开声音设置-选择输出设备。...

【面试 反思】Retrofit源码与设计 7 连问

前言 在实际项目中往往是使用Retrofit来做网络请求工作。Retrofit采用RESTful风格&#xff0c;本质上只是对OkHttp进行封装&#xff0c;今天我们根据几个问题来进一步学习一下Retrofit的源码与设计思想。 1. 使用方法 直接看一下官方介绍的使用方法。 public final class S…...

flutter 雷达图

通过CustomPainter自定义雷达图 效果如下 主要代码 import package:flutter/material.dart; import dart:math; import dash_painter.dart; import model/charts_model.dart;class RadarChart extends StatelessWidget {final List<ChartModel> list;final double maxV…...

机器学习之损失函数(Loss Function)

损失函数&#xff08;Loss Function&#xff09;是机器学习和深度学习中的关键概念&#xff0c;它用于衡量模型的预测与实际目标之间的差异或误差。损失函数的选择对于模型的训练和性能评估至关重要&#xff0c;不同的任务和问题通常需要不同的损失函数。 以下是一些常见的损失…...

创邻科技张晨:图数据库,激活数据要素的新基建

“数据经济时代&#xff0c;数据要素产业链的各细分领域均蕴含机遇&#xff0c;图技术作为网络协同和数据智能的底层发动机&#xff0c;将深度掘金数字中国价值潜能”。 8月22日&#xff0c;在2023中国&#xff08;南京&#xff09;国际软件产品和信息服务交易博览会的信息技术…...

使用端口映射实现Spring Boot服务端接口的公网远程调试:详细配置与步骤解析

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…...

stm32之点亮LED

今天&#xff0c;记录一下stm32如何点亮一个LED,程序本身十分简单&#xff0c;但主要是学习编程的格式。 led.h #ifndef _led_H #define _led_H#include "system.h"/* LED时钟端口、引脚定义 */ #define LED1_PORT GPIOB #define LED1_PIN GPIO_Pin_5 #d…...

SA8000认证的难点及注意事项

SA8000认证是什么&#xff1f; SA8000即“社会责任标准”&#xff0c;是Social Accountability 8000的英文简称&#xff0c;由社会责任国际组织(SAI)制定与执行&#xff0c;是全球首个道德规范国际标准。自1997年问世以来&#xff0c;它创建了一个衡量社会责任的共同语言&#…...

Java可视化物联网智慧工地SaaS平台源码:人脸识别考勤

基于微服务JavaSpring Cloud Vue UniApp MySql实现的智慧工地云平台源码 智慧工地是指利用云计算、大数据、物联网、移动互联网、人工智能等技术手段&#xff0c;为建筑施工现场提供智能硬件及物联网平台的解决方案&#xff0c;以实现建筑工地的实时化、可视化、多元化、智慧化…...

告别数字化系统“物理叠加”,华为云推动智慧门店价值跃迁

文|智能相对论 作者|叶远风 有大屏幕滚动播放广告&#xff1b; 有人脸识别系统让消费者自助结账&#xff1b; 有订单管理系统综合分析一段时间内总体经营情况&#xff1b; 有全门店监控直连总部机房&#xff1b; …… 以搭载数字化系统的硬件设备为表面特征的智慧门店&a…...

k8s 常用命令(四)

12、删除pod中的nginx服务及service [rootmaster ~]# kubectl delete deployment nginx -n kube-public [rootmaster ~]# kubectl delete svc -n kube-public nginx-service 13、查看endpoint的信息 [rootmaster ~]# kubectl get endpoints 14、修改/更新&#xff08;镜像、…...

大语言模型的分布式训练

什么是大语言模型 大语言模型(Large Language Model,缩写LLM),也称大型语言模型,是一种人工智能模型,旨在理解和生成人类语言。它们在大量的文本数据上进行训练,可以执行广泛的任务,包括文本总结、翻译、情感分析等等。LLM的特点是规模庞大,包含数十亿的参数,帮助它们学习语言…...

【JavaEE】Spring全家桶实现AOP-统一处理

【JavaEE】AOP&#xff08;2&#xff09; 文章目录 【JavaEE】AOP&#xff08;2&#xff09;1. 统一登录校验处理1.1 自定义拦截器1.2 将自定义拦截器加入到系统配置1.3 测试1.4 对于静态资源的处理1.5 小练习&#xff1a;统一登录拦截处理1.6 拦截器原理1.6.1 执行流程1.6.2 源…...

HQL解决连续三天登陆问题

1.背景 统计连续登录天数超过3天的用户&#xff0c;输出信息包括&#xff1a;用户id&#xff0c;登录天数&#xff0c;起始时间&#xff0c;结束时间&#xff1b; 2.准备数据 -- 建表 create table if not exists user_login_3days(user_id STRING,login_date date );--插入…...

(一)Docker简介(一篇足以)

一、简介 一个项目环境配置相当麻烦&#xff0c;如果换一台机器跑起来&#xff0c;所有配置就要重来一次&#xff0c;费力费时。很多人想到&#xff0c;能不能从根本上解决问题&#xff0c;软件可以带环境安装&#xff1f;也就是说&#xff0c;安装的时候&#xff0c;把原始环…...

RK3568 安卓源码编译

一.repo安卓编译工具 项目模块化/组件化之后各模块也作为独立的 Git 仓库从主项目里剥离了出去&#xff0c;各模块各自管理自己的版本。Android源码引用了很多开源项目&#xff0c;每一个子项目都是一个Git仓库&#xff0c;每个Git仓库都有很多分支版本&#xff0c;为了方便统…...

第4篇:vscode+platformio搭建esp32 arduino开发环境

第1篇:Arduino与ESP32开发板的安装方法 第2篇:ESP32 helloword第一个程序示范点亮板载LED 第3篇:vscode搭建esp32 arduino开发环境 1.配置默认安装路径&#xff0c;安装到D盘。 打开环境变量&#xff0c;点击新建 输入变量名PLATFORMIO_CORE_DIR与路径&#xff1a;D:\PLATF…...

2023前端面试笔记 —— CSS3

系列文章目录 内容链接2023前端面试笔记HTML52023前端面试笔记CSS3 文章目录 系列文章目录前言一、CSS选择器的优先级二、通过 CSS 的哪些方式可以实现隐藏页面上的元素三、px、em、rem之间有什么区别&#xff1f;四、让元素水平居中的方法有哪些五、在 CSS 中有哪些定位方式六…...

iOS 如何对整张图分别局部磨砂,并完全贴合

官方磨砂方式 - (UIVisualEffectView *)effectView{if(!_effectView){UIBlurEffect *blur [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];_effectView [[UIVisualEffectView alloc] initWithEffect:blur];}return _effectView; }使用这种方式对一张图的上半部分和…...

Packet_Tracer的使用

一、实验目的&#xff1a; 通过该实验了解Packet Tracer的使用方法&#xff0c;能够用Packet Tracer建立和模拟网络模型。 二、主要任务&#xff1a; 1.熟悉PT的界面&#xff0c;了解按键用途。 2.尝试自己建立一个小型网络&#xff0c;并测试连通性。 3.学习P…...

WPF如果未定义绑定的属性,程序如何处理

问题&#xff1a;wpf中&#xff0c;<Button IsEnabled"{Binding IsValid1}"></Button>&#xff0c;如果没定义绑定的属性IsValid1&#xff0c;可以正常用吗 解答&#xff1a;在 WPF 中&#xff0c;如果没有定义绑定的属性 IsValid1&#xff0c;会导致绑…...

做网站的软件wd的叫啥/百度网址链接是多少

前几天我在我的Blog上发布了NGuestBook&#xff08;点击这里下载&#xff09;&#xff0c;得到了很多反馈&#xff0c;在这里非常感谢大家的关注和支持。一些朋友在E-mail中提到&#xff0c;这个NGuestBook和我那个系列文章《基于.NET平台的分层架构实战》中讲的Demo有非常多不…...

品牌网站建设策划书/seo描述快速排名

没有急停&#xff0c;需要花费0.5秒 有急停&#xff0c;需要花费0.25秒&#xff1b; 是否存在模拟急停的可能性&#xff1f; 结论是&#xff0c;存在 这种可能性。但是现在的代码框架行不通&#xff0c;进不到中断里边&#xff0c; 中断里&#xff0c;应该只干标志位就好&am…...

夺宝网站建设/如何做好口碑营销

简介&#xff1a;图像二值化就是将图像上的像素点的灰度值设置为0或255&#xff0c;也就是将整个图像呈现出明显的黑白效果的过程。 普通图像二值化 代码如下&#xff1a; import cv2 as cv import numpy as np #全局阈值 def threshold_demo(image): gray cv.cvtColor(image,…...

wordpress的登录界面/网络热词有哪些

文章目录前言1.awk命令1.1 BEGIN的作用1.2 END的作用1.3 FS内置变量的作用1.4 关系表达式作为条件2. 总结前言 awk标准输出就是printf命令。如下如这种情况下&#xff0c;用cut命令就不能解决&#xff0c;这是就需要awk命令来解决这个问题。 awk的功能比cut的功能要强大的多。…...

Java做新闻网站/百度竞价收费标准

做这题 来为上年 上海的那个状压bfs做铺垫 _ 这题 不难 就是 多开一维 存下 钥匙的状态就好了 表示在 (x,y)这个坐标点 已经收集到了哪些钥匙 多做点 状压的题目 就会来感觉的. 1 #include <iostream>2 #include <queue>3 #include <cstring>4 using namespa…...

有赞微商城官网登入/石家庄seo培训

一、检测Web异常操作 1.数据搜集&#xff1a;一样 2.特征化 使用词集模型&#xff0c;统计全部操作命令&#xff0c;去重后形成字典或词汇表&#xff1a; with open(filename) as f:for line in f:lineline.strip(\n)dist.append(line) fdist FreqDist(dist).keys() 以此词汇…...