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

Spring Boot整合Tomcat底层源码分析

引言

Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置和起步依赖等特性,大大简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是其与Tomcat的整合。

一、Spring Boot的背景历史

1.1 Spring Boot的起源与发展

Spring Boot由Pivotal团队开发,最早于2014年发布。其目标是简化Spring应用的开发和部署,通过自动配置和起步依赖等特性,减少开发人员在配置文件上花费的时间和精力。

  • 起源与早期发展(2013-2014年)
    2013年,Spring Boot开始开发,2014年4月,Spring Boot 1.0.0正式发布,引入了核心特性如自动配置、起步依赖、命令行界面(CLI)等。
  • 逐步成熟(2015-2017年)
    2015年,Spring Boot 1.2和1.3版本相继发布,带来了更多的功能和改进。2016年,Spring Boot 1.4版本发布,进一步优化了性能和稳定性。2017年,Spring Boot 2.0发布,基于Spring Framework 5构建,支持Java 8及以上版本,并引入了响应式编程等新特性。
  • 持续发展(2018年至今)
    2018年及以后,Spring Boot不断进行小版本的更新和改进,以适应不断变化的技术需求。它在云原生应用开发、容器化部署、Serverless架构等方面发挥着重要作用。同时,Spring Boot的生态系统也在不断壮大,有越来越多的插件和工具可供选择。

1.2 Spring Boot的核心特点

Spring Boot的核心特点可以概括为以下几点:

  • 约定大于配置:Spring Boot通过提供大量默认配置,减少了开发人员的配置工作量。
  • 起步依赖:Spring Boot提供了一系列的起步依赖,方便快速引入所需的库和框架。
  • 自动配置:Spring Boot能根据类路径中的依赖和环境自动配置Spring应用程序。
  • 内嵌服务器:Spring Boot内置了Tomcat、Jetty或Undertow等服务器,应用可以直接运行在这些服务器上。
  • 生产就绪:Spring Boot提供了一些生产环境中的监控、健康检查、日志管理等功能。

二、Spring Boot的业务场景与功能点

2.1 业务场景

Spring Boot适用于多种业务场景,包括但不限于:

  • 微服务架构:Spring Boot适用于构建和部署微服务,可以快速创建独立的、可独立部署的微服务应用程序。
  • RESTful API开发:Spring Boot提供了丰富的支持和简化开发RESTful API的工具和功能。
  • Web应用程序开发:Spring Boot支持开发各种Web应用程序,如单页应用程序、多页应用程序、网站等。
  • 批处理应用程序:Spring Boot提供了对批处理应用程序的支持,包括任务调度、处理大数据量、事务管理等。
  • 数据访问:Spring Boot简化了与数据库和其他数据源的集成,通过自动配置和起步依赖简化了数据访问层的开发。
  • 云原生应用程序:Spring Boot适用于构建和部署云原生应用程序,和容器化应用程序的开发和管理。

2.2 功能点

Spring Boot的功能点非常丰富,包括但不限于:

  • 自动配置:根据classpath下的依赖和配置文件的内容,自动为应用程序进行配置。
  • 起步依赖:提供了一系列的起步依赖,用于快速引入常见的第三方库和框架。
  • 内嵌服务器:内置了Tomcat、Jetty、Undertow等多个服务器,开发者可以将应用程序打包成可执行的JAR或WAR文件,直接运行。
  • 监控和管理:提供了一些监控和管理的工具,可以帮助开发人员实时监控和管理应用程序的运行状态。
  • 外部化配置:支持外部化配置,可以通过配置文件、环境变量等方式灵活地配置应用程序。
  • 数据访问:简化了与数据库和其他数据源的集成,通过自动配置和起步依赖简化了数据访问层的开发。

三、Spring Boot整合Tomcat的底层原理

3.1 Spring Boot与Tomcat的整合方式

Spring Boot可以通过以下两种方式整合Tomcat:

  • 使用内置Tomcat:Spring Boot默认内置了Tomcat服务器,在开发和生产环境中可以直接使用。打包时,将Tomcat与项目代码一起打包成一个可执行的jar文件,然后通过命令直接运行该jar文件来启动服务器。
  • 使用外置Tomcat:将Spring Boot项目打包为war并部署到传统的Tomcat服务器中。

3.2 底层源码分析

3.2.1 配置Tomcat

在Spring Boot中,可以通过在配置文件中配置端口号、上下文路径、Session超时时间等来定制内嵌Tomcat服务器的配置。例如,在application.propertiesapplication.yml文件中进行如下配置:

properties复制代码
server.port=8080
server.servlet.context-path=/myapp
server.servlet.session.timeout=30m

在Spring Boot的源码中,这些配置会被读取并应用到Tomcat服务器实例上。具体来说,TomcatEmbeddedServletContainerFactory类负责创建和配置Tomcat服务器实例。

3.2.2 加载Servlet

在Spring Boot中,可以使用@ServletComponentScan注解来加载Servlet、Filter和Listener。在应用启动时,Spring Boot会自动扫描@ServletComponentScan注解指定的包,查找并注册Servlet、Filter和Listener。

例如,定义一个Servlet:

java复制代码
@WebServlet(urlPatterns = "/myservlet")
public class MyServlet extends HttpServlet {
// Servlet实现
}

在Spring Boot的源码中,ServletRegistrationBeanFilterRegistrationBeanServletContextInitializer等类负责将Servlet、Filter和Listener注册到Tomcat中。

3.2.3 实现Tomcat的自动配置

Spring Boot提供了一个名为EmbeddedServletContainerAutoConfiguration的自动配置类,它根据应用中所包含的类库和配置信息来自动配置内嵌的Servlet容器。具体来说,该类会检查类路径中是否存在Tomcat、Jetty或Undertow等服务器的依赖,并根据存在的依赖自动配置相应的Servlet容器。

在自动配置过程中,Spring Boot会扫描应用中所有的Servlet、Filter和Listener,然后根据这些组件的注解信息生成对应的ServletRegistrationBeanFilterRegistrationBeanServletContextInitializer对象,最终将这些组件注册到Tomcat中。

3.2.4 启动Tomcat

在Spring Boot中,可以使用SpringApplication类来启动Tomcat。在SpringApplicationrun方法中,会创建并启动Tomcat服务器实例。

具体来说,SpringApplication会执行以下步骤来启动Tomcat:

  1. 创建Spring应用上下文SpringApplication会创建一个AnnotationConfigServletWebServerApplicationContext实例,作为Spring应用上下文。
  2. 加载自动配置类SpringApplication会加载EmbeddedServletContainerAutoConfiguration等自动配置类,并根据这些配置类来配置Spring应用。
  3. 注册Servlet组件SpringApplication会扫描应用中的Servlet、Filter和Listener,并将它们注册到Tomcat中。
  4. 启动Tomcat服务器:最后,SpringApplication会将配置好的Tomcat服务器实例启动起来,并开始处理HTTP请求。

四、手写模拟Spring Boot启动过程

下面我们通过Java代码手写模拟Spring Boot的启动过程,特别是其与Tomcat的整合。

4.1 创建一个Spring Boot项目

首先,我们创建一个标准的Spring Boot项目结构,包括src/main/javasrc/main/resources等目录。

4.2 定义启动类

src/main/java目录下,定义一个启动类,并使用@SpringBootApplication注解标记:

java复制代码
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

4.3 配置Tomcat

src/main/resources目录下的application.properties文件中,配置Tomcat的相关属性:

properties复制代码
server.port=8080
server.servlet.context-path=/myapp
server.servlet.session.timeout=30m

4.4 定义Servlet

src/main/java目录下,定义一个Servlet类:

java复制代码
package com.example.demo.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("Hello, Spring Boot with Tomcat!");}
}

4.5 模拟Spring Boot启动过程

接下来,我们手写模拟Spring Boot的启动过程。首先,我们需要创建一个自定义的SpringApplication类,并在其中实现Tomcat的启动逻辑。

4.5.1 创建自定义SpringApplication

src/main/java目录下,创建一个自定义的SpringApplication类:

java复制代码
package com.example.demo;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example.demo")
public class CustomSpringApplication {
public static void main(String[] args) throws LifecycleException {
// 创建Tomcat实例
Tomcat tomcat = new Tomcat();tomcat.setPort(8080); // 设置端口号tomcat.setContextPath("/myapp"); // 设置上下文路径tomcat.setSessionTimeout(30); // 设置Session超时时间
// 添加Web应用tomcat.addWebapp("/", System.getProperty("user.dir") + "/src/main/webapp");
// 启动Tomcat服务器tomcat.start();tomcat.getServer().await();}
}
4.5.2 创建Web应用目录

src/main/webapp目录下,创建一个WEB-INF目录,并在其中创建一个web.xml文件(虽然Spring Boot通常不需要web.xml,但为了模拟传统Web应用的部署方式,我们在这里创建一个)。

web.xml文件内容如下:

xml复制代码
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.example.demo.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>

4.6 运行模拟的Spring Boot应用

现在,我们可以运行CustomSpringApplication类的main方法来启动模拟的Spring Boot应用。启动后,访问http://localhost:8080/myapp/hello,应该能够看到“Hello, Spring Boot with Tomcat!”的响应。

五、总结

本文通过深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,特别是其与Tomcat的整合方式,展示了Spring Boot的强大功能和灵活性。同时,通过手写模拟Spring Boot的启动过程,进一步加深了对Spring Boot内部工作机制的理解。希望本文能为读者在使用Spring Boot进行开发时提供有益的参考和帮助。

相关文章:

Spring Boot整合Tomcat底层源码分析

引言 Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置和起步依赖等特性&#xff0c;大大简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理&#xff0c;并通过Java代码手写模拟Spring…...

工具类-基于 axios 的 http 请求工具 Request

基于 axios 的 http 请求工具 基于 axios 实现一个 http 请求工具&#xff0c;支持设置请求缓存和取消 http 请求等功能 首先实现一个 简单的 http 请求工具 import axios, {AxiosError,AxiosInterceptorManager,AxiosRequestConfig,AxiosResponse, } from axios;// 接口返回…...

WPF的基础控件详解

WPF的基础控件详解 在WPF学习中 基本控件是最简单也是最基础的东西。也是很初学者容易忽略的 本此笔记教程主要针对WPF中基础控件使用和应用进行手把手教学&#xff0c;如果学习了此笔记对你有帮助记得一键三连哦~~~~ TextBlock 基本用法 长字串处理 LineBreak标籤在指定的地…...

qt学习:截图+键盘事件

效果 生成一个透明无边框全屏的窗口&#xff0c;然后按ctrlb键就可以选择区域进行截图保存 步骤 新建一个项目新建一个ctrlb类继承QMainWindow新建一个CaptureScreen类继承QWidget在main中启动ctrlb类 代码 ctrlb类.cpp #include "ctrlb.h" #include "cap…...

Scala中Arry

import scala.collection.mutable.ArrayBuffer //Arry:数组 //可修改的&#xff1a;ArryBuffer //不可修改的&#xff1a;Arryobject Test_1118_2 {//可修改的&#xff1a;ArrayBufferdef main(args: Array[String]): Unit {//1.新建val arr1ArrayBuffer(1,2,3)//2.添加arr14a…...

学习threejs,使用AnimationMixer实现变形动画

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.AnimationMixer 动画…...

两大新兴开发语言大比拼:Move PK Rust

了解 Move 和 Rust 的差异有助于开发者根据项目的具体需求选择最合适的语言。选择不恰当的语言可能会导致项目后期出现技术债务。不同语言有其独特的优势。了解 Move 和 Rust 的差异可以帮助开发者拓展技术视野&#xff0c;发现不同语言在不同领域的应用潜力。 咱们直奔主题&a…...

基于一种基于OCR图像识别技术的发票采集管理系统及方法

本发明涉及了一种基于OCR图像识别技术的发票采集管理系统及方法&#xff0c;该系统的发票信息采集单元采集发票图片信息数据&#xff0c;OCR图像识别单元基于OCR图像识别技术并结合人工智能深度学习算法对发票图片信息数据进行识别读取以获得OCR图像识别结果&#xff0c;发票信…...

基于深度学习的车牌检测系统的设计与实现(安卓、YOLOV、CRNNLPRNet)+文档

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

JavaWeb——JS、Vue

目录 1.JavaScript a.概述 b.引入方式 c.JS的基础语法 d.JS函数 e.JS对象 f.JS事件监听 2.Vue a.概述 b.Vue常用指令 d.生命周期 1.JavaScript a.概述 JavaScript是一门跨平台、面向对象的脚本语言。是用来控制网页行为的&#xff0c;它能使网页可交互。JavaScript和…...

Springboot 整合 Java DL4J 构建股票预测系统

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

ATmaga8单片机Pt100温度计源程序+Proteus仿真设计

目录 1、项目功能 2、仿真图 ​3、程序 资料下载地址&#xff1a;ATmaga8单片机Pt100温度计源程序Proteus仿真设计 1、项目功能 设计Pt100铂电阻测量温度的电路&#xff0c;温度测量范围是0-100摄氏度&#xff0c;要求LCD显示。画出电路图&#xff0c;标注元器件参数&am…...

FPGA通过MIPI CSI-2发送实时图像到RK3588,并HDMI显示

介绍FPGA通过MIPI CSI-2发送实时图像到RK3588&#xff0c;并HDMI显示。 FPGA本地产生动态图像模板&#xff0c;通过MIPI CSI-2接口发送到RK3588 MIPI CSI接口。RK3588注册成相机后&#xff0c;调用接口并在HDMI显示器上显示。 1、RK3588驱动调试 查看Media controller信息 Med…...

ELK8.15.4搭建开启安全认证

安装 Elastic &#xff1a;Elasticsearch&#xff0c;Kibana&#xff0c;Logstash 另外安装一个收集器filebeat 通过二进制安装包进行安装 创建一个专门放elk目录 mkdir /elk/ mkdir /elk/soft下载 es 、kibana、Logstash、filebeat二进制包 cd /elk/softwget https://art…...

原生微信小程序中封装一个模拟select 下拉框组件

1.首先在components 里面设置组件名称&#xff1a;van-select&#xff08;随便取名字&#xff09;&#xff1b; 2.新建文件写代码&#xff1a; wxml&#xff1a; <view class"w100 select_all_view"><!-- 标题&#xff0c;可以没有 --><view class…...

商品管理系统引领时尚零售智能化升级 降价商品量锐减30%

根据贝恩咨询公司2024年发布的消费品报告&#xff0c;当前消费品行业正面临增长放缓、全球市场波动及消费者期望变化的巨大压力。为保持市场竞争力&#xff0c;企业需要重新审视其增长战略&#xff0c;重视可持续创新、数字化转型和运营敏捷性。企业必须灵活应对供应链中断和消…...

UE5 5.1.1创建C++项目,显示error C4668和error C4067

因为工作要求&#xff0c;没法使用最新 5.5版本的ue5 而是要用ue5.1和5.2版本。 但是我在安装下载了visual studio2022后&#xff0c;使用 ue5.1编辑器 创建C项目&#xff0c;爆出如下错误。 error C4668: ?????__has_feature?????ΪԤ?????꣬???0????…...

spring boot 集成 redis 实现缓存的完整的例子

Cacheable 注解是 Spring Cache 抽象的一部分&#xff0c;用于声明式地管理缓存。Cacheable 注解本身并不直接指定缓存的存储位置&#xff0c;而是依赖于配置的缓存管理器&#xff08;CacheManager&#xff09;来决定缓存数据的存储位置。 常见的缓存存储方式: 1、内存缓存&a…...

json-bigint处理前端精度丢失问题

问题描述&#xff1a;前后端调试过程中&#xff0c;有时候会遇到精度丢失的问题&#xff0c;比如后端给过来的id超过16位&#xff0c;就会出现精度丢失的情况&#xff0c;前端拿到的id与后端给过来的不一致。 解决方案&#xff1a; 1、安装 npm i json-bigint 2、在axios中配置…...

【算法】【优选算法】前缀和(下)

目录 一、560.和为K的⼦数组1.1 前缀和1.2 暴力枚举 二、974.和可被K整除的⼦数组2.1 前缀和2.2 暴力枚举 三、525.连续数组3.1 前缀和3.2 暴力枚举 四、1314.矩阵区域和4.1 前缀和4.2 暴力枚举 一、560.和为K的⼦数组 题目链接&#xff1a;560.和为K的⼦数组 题目描述&#x…...

Node.js 23 发布了!

Node.js 23 现已推出&#xff0c;带来了新功能、性能改进和更好的开发者体验。此次版本提升了兼容性和稳定性&#xff0c;提供了更多工具来构建高效的应用程序。 此外&#xff0c;Node.js 22 将在 10 月 29 日当周被提升为长期支持 (LTS) 版本&#xff0c;进入长期维护阶段&am…...

如何通过低代码逻辑编排实现业务流程自动化?

随着数字化转型的加速&#xff0c;企业对高效、灵活的业务流程自动化需求日益增加。传统开发模式下的定制化解决方案往往周期长、成本高且难以适应快速变化的需求。低代码平台以其直观、简便的操作界面和强大的功能逐渐成为企业实现业务流程自动化的理想选择。本文将探讨低代码…...

thinkphp6模板调用URL方法生成的链接异常

var uul params.url ;console.log(params.url);console.log("{:Url(UserLog/index)}");console.log("{:Url("uul")}"); 生成的链接地址 UserLog/index /jjg/index.php/Home/UserLog/index.html /jjg/index.php/Home/Index/UserLog/index.html…...

Spring Boot汽车资讯:科技驱动的未来

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 4系统概要设计 4.1概…...

嵌入式硬件电子电路设计(五)LDO低压差线性稳压器全面详解

引言&#xff1a; LDO&#xff08;Low Dropout Regulator&#xff0c;低压差线性稳压器&#xff09;是一种常用的电源管理组件&#xff0c;用于提供稳定的输出电压&#xff0c;同时允许较小的输入电压与输出电压之间的差值。LDO广泛应用于各种电子设备中&#xff0c;特别是在对…...

qiankun主应用(vue2+element-ui)子应用(vue3+element-plus)不同版本element框架css样式相互影响的问题

背景&#xff1a;qiankun微前端架构实现多应用集成 主应用框架&#xff1a;vue2 & element-ui 子应用框架&#xff1a;vue3 & element-plus >> 问题现象和分析 登录页面是主应用的&#xff0c;在登录之后才能打开子应用的菜单页面&#xff0c;即加载子应用。 首…...

resnet50,clip,Faiss+Flask简易图文搜索服务

一、实现 文件夹目录结构&#xff1a; templates -----upload.html faiss_app.py 前端代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widt…...

使用OkHttp进行HTTPS请求的Kotlin实现

OkHttp简介 OkHttp是一个高效的HTTP客户端&#xff0c;它支持同步和异步请求&#xff0c;自动处理重试和失败&#xff0c;支持HTTPS&#xff0c;并且可以轻松地与Kotlin协程集成。OkHttp的设计目标是提供最简洁的API&#xff0c;同时保持高性能和低延迟。 为什么选择OkHttp …...

使用Mac下载MySQL修改密码

Mac下载MySQL MySQL官网链接MySQL​​​​​​ 当进入到官网后下滑到community社区&#xff0c;进行下载 然后选择community sever下载 这里就是要下载的界面&#xff0c;如果需要下载之前版本的话可以点击archives&#xff0c; 可能会因为这是外网原因&#xff0c;有时候下…...

运维面试题.云计算面试题集锦第一套

运维+网络安全学科基础升就业 测试题(总分100分) 一,单词翻译(10分,直接写在答题卡上) 二,单选题(每题2分,共30题): 1.如下哪个属于管道符?( ) A、|| B、<< C、// D、| 2.有一备份程序mybackup,需要在周一至周五下午1点和晚上8点各运行一次,下面哪条cront…...

宝安建设网站公司/营销推广活动策划方案

GraphQL 是一种用于 API 的查询语言&#xff0c;GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述&#xff0c;使得客户端能够准确地获得它需要的数据&#xff0c;而且没有任何冗余&#xff0c;也让 API 更容易地随着时间推移而演进&#xff0c;还能用于构建强大的开发…...

兴义网站建设网站建设/关键词点击优化工具

现在&#xff0c;大多数网站设计师都无法阻止探索设计和UI的世界。 这样就产生了好主意和更好的计划。 他们可能会提出更多特殊效果&#xff0c;这些效果将在当今的现代网站中使用。 现在&#xff0c;我这里是jQuery“ DragN Drop”插件列表。 从桌面应用程序以及涉及此类操作的…...

做搜狗pc网站优化/建立企业网站步骤

第一步在原有基础上引入依赖:org.jetbrains.kotlinkotlin-stdlib-jre8${kotlin.version}org.jetbrains.kotlinkotlin-reflect${kotlin.version}com.fasterxml.jackson.modulejackson-module-kotlin2.9.4.1版本号多去少补:trueUTF-8UTF-81.81.2.20构建方式修改:${project.basedi…...

2022年企业所得税税率/佛山百度快照优化排名

文档来源&#xff1a;w3cpro.cn 如果同个元素有两个或以上冲突的CSS规则&#xff0c;浏览器有一些基本的规则来决定哪一个非常特殊而胜出。 如果同个元素有两个或以上冲突的CSS规则&#xff0c;浏览器有一些基本的规则来决定哪一个非常特殊而胜出。 它可能不像其它那么重要&am…...

在哪些网站可以发布推广信息/seo引擎搜索

参考地址 JS 正则截取字符串 1、js截取两个字符串之间的内容&#xff1a; varstr "aaabbbcccdddeeefff"; str str.match(/aaa(\S*)fff/)[1]; alert(str);//结果bbbcccdddeee2、js截取某个字符串前面的内容&#xff1a; varstr "aaabbbcccdddeeefff"…...

mac怎么重新安装wordpress/西安关键词优化服务

大家最近都在热议古城钟楼的红火。不是加V号、不是官方号、不是皇冠会员。没有拟人化&#xff0c;没有段子、没有运营。1天之内从1万不到的粉丝新增了20多万并且还在持续传播和增长粉丝。我不研究它是怎么红起来的&#xff0c;但写个类似的程序实现它却很容易&#xff0c;程序才…...