微前端基础

news2024/12/30 1:25:16

一、什么是微前端

微前端是一种软件架构,可以将前端应用拆解成一些更小的能够独立开发部署的微型应用,然后再将这些微应用进行组合使其成为整体应用的架构模式。微前端架构类似于组件架构,但不同的是,组件不能独立构建和发布,但是微前端中的应用是可以的。微前端架构与框架无关,每个微应用都可以使用不同的框架。

在这里插入图片描述

二、 微前端的价值

1. 增量迁移

迁移是一项非常耗时且艰难的任务,比如有一个管理系统使用 AngularJS 开发维护已经有三年时间,但是随时间的推移和团队成员的变更,无论从开发成本还是用人需求上,AngularJS 已经不能满足要求,于是团队想要更新技术栈,想在其他框架中实现新的需求,但是现有项目怎么办?直接迁移是不可能的,在新的框架中完全重写也不太现实。
使用微前端架构就可以解决问题,在保留原有项目的同时,可以完全使用新的框架开发新的需求,然后再使用微前端架构将旧的项目和新的项目进行整合。这样既可以使产品得到更好的用户体验,也可以使团队成员在技术上得到进步,产品开发成本也降到的最低。

2. 独立发布

在目前的单页应用架构中,使用组件构建用户界面,应用中的每个组件或功能开发完成或者bug修复完成后,每次都需要对整个产品重新进行构建和发布,任务耗时操作上也比较繁琐。
在使用了微前端架构后,可以将不能的功能模块拆分成独立的应用,此时功能模块就可以单独构建单独发布了,构建时间也会变得非常快,应用发布后不需要更改其他内容应用就会自动更新,这意味着你可以进行频繁的构建发布操作了。

3. 允许单个团队做出技术决策

因为微前端构架与框架无关,当一个应用由多个团队进行开发时,每个团队都可以使用自己擅长的技术栈进行开发,也就是它允许适当的让团队决策使用哪种技术,从而使团队协作变得不再僵硬。
在这里插入图片描述
微前端的使用场景:

  1. 拆分巨型应用,使应用变得更加可维护

  2. 兼容历史应用,实现增量开发

三、 如何实现微前端

1. 多个微应用如何进行组合?

在微前端架构中,除了存在多个微应用以外,还存在一个容器应用,每个微应用都需要被注册到容器应用中。
微前端中的每个应用在浏览器中都是一个独立的 JavaScript 模块,通过模块化的方式被容器应用启动和运行。
使用模块化的方式运行应用可以防止不同的微应用在同时运行时发生冲突。

2. 在微应用中如何实现路由 ?

在微前端架构中,当路由发生变化时,容器应用首先会拦截路由的变化,根据路由匹配微前端应用,当匹配到微应用以后,再启动微应用路由,匹配具体的页面组件。

3. 微应用与微应用之间如何实现状态共享?

在微应用中可以通过发布订阅模式实现状态共享,比如使用 RxJS。

4. 微应用与微应用之间如何实现框架和库的共享?

通过 import-map 和 webpack 中的 externals 属性。

四、. Systemjs 模块化解决方案

1 概述

在微前端架构中,微应用被打包为模块,但浏览器不支持模块化,需要使用 systemjs 实现浏览器中的模块化。

systemjs 是一个用于实现模块化的 JavaScript 库,有属于自己的模块化规范。

在开发阶段我们可以使用 ES 模块规范,然后使用 webpack 将其转换为 systemjs 支持的模块。

2 体验

案例:通过 webpack 将 react 应用打包为 systemjs 模块,在通过 systemjs 在浏览器中加载模块

npm install webpack@5.17.0 webpack-cli@4.4.0 webpack-dev-server@3.11.2 html-webpack-

plugin@4.5.1 @babel/core@7.12.10 @babel/cli@7.12.10 @babel/preset-env@7.12.

@babel/preset-react@7.12.10 babel-loader@8.2.
// package.json
{
"name": "systemjs-react",
"scripts": {
"start": "webpack serve"
},
"dependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"babel-loader": "^8.2.2",
"html-webpack-plugin": "^4.5.1",
"webpack": "^5.17.0",
"webpack-cli": "^4.4.0",
"webpack-dev-server": "^3.11.2"
}
}
// webpack.config.js
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.join(__dirname, "build"),
filename: "index.js",
libraryTarget: "system"
},
devtool: "source-map",
devServer: {
port: 9000 ,
contentBase: path.join(__dirname, "build"),
historyApiFallback: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/react"]
}
}
}

plugins: [
new HtmlWebpackPlugin({
inject: false,
template: "./src/index.html"
})
],
externals: ["react", "react-dom", "react-router-dom"]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>systemjs-react</title>
<script type="systemjs-importmap">
{
"imports": {
"react":
"https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js",
"react-dom": "https://cdn.jsdelivr.net/npm/react-dom/umd/react-
dom.production.min.js",
"react-router-dom": "https://cdn.jsdelivr.net/npm/react-router-
dom@5.2.0/umd/react-router-dom.min.js"
}
}
</script>
<script
src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/system.min.js"></script>
</head>
<body>
<div id="root"></div>
<script>
System.import("./index.js")
</script>
</body>
</html>

五、 微前端框架 single-spa

1 single-spa 概述

single-spa 是一个实现微前端架构的框架。

在 single-spa 框架中有三种类型的微前端应用:

  1. single-spa-application / parcel:微前端架构中的微应用,可以使用 vue、react、angular 等框架。

  2. single-spa root config:创建微前端容器应用。

  3. utility modules:公共模块应用,非渲染组件,用于跨应用共享 javascript 逻辑的微应用。

2 创建容器应用

  1. 安装 single-spa 脚手架工具:npm install create-single-spa@2.0.3 -g

在这里插入图片描述

  1. 创建微前端应用目录:mkdir workspace && cd “$_”

  2. 创建微前端容器应用:create-single-spa

    1. 应用文件夹填写 container

    2. 应用选择 single-spa root config

    3. 组织名称填写 study
      组织名称可以理解为团队名称,微前端架构允许多团队共同开发应用,组织名称可以标识应用由哪个团队开发。
      应用名称的命名规则为 @组织名称/应用名称,比如 @study/todos

  3. 启动应用:npm start

  4. 访问应用:localhost:9000

  5. 默认代码解析

    1. Root-config.js
// workspace/container/src/study-root-config.js
import { registerApplication, start } from "single-spa"
/*
注册微前端应用

1. name: 字符串类型, 微前端应用名称 "@组织名称/应用名称"
2. app: 函数类型, 返回 Promise, 通过 systemjs 引用打包好的微前端应用模块代码
(umd)
3. activeWhen: 路由匹配时激活应用
*/
registerApplication({
name: "@single-spa/welcome",
app: () =>
System.import(
"https://unpkg.com/single-spa-welcome/dist/single-spa-welcome.js"
),
activeWhen: ["/"]
})

  1. index.ejs
// start 方法必须在 single spa 的配置文件中调用
// 在调用 start 之前, 应用会被加载, 但不会初始化, 挂载或卸载.
start({
// 是否可以通过 history.pushState() 和 history.replaceState() 更改触发
single-spa 路由
// true 不允许 false 允许
urlRerouteOnly: true
})
<!-- 导入微前端容器应用 -->
<script>
System.import("@study/root-config")
</script>
<!--
import-map-overrides 可以覆盖导入映射
当前项目中用于配合 single-spa Inspector 调试工具使用.
可以手动覆盖项目中的 JavaScript 模块加载地址, 用于调试.
-->
<import-map-overrides-full show-when-local-storage="devtools" dev-libs>
</import-map-overrides-full>
 <!-- 模块加载器 -->
<script
src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/system.min.js">
</script>
<!-- systemjs 用来解析 AMD 模块的插件 -->
<script
src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/extras/amd.min.js"
></script>
<!-- 用于覆盖通过 import-map 设置的 JavaScript 模块下载地址 -->
<script src="https://cdn.jsdelivr.net/npm/import-map-
overrides@2.2.0/dist/import-map-overrides.js"></script>
<!-- 用于支持 Angular 应用 -->
<script
src="https://cdn.jsdelivr.net/npm/zone.js@0.10.3/dist/zone.min.js">
</script>
<!-- single-spa 预加载 -->
<link
rel="preload"
href="https://cdn.jsdelivr.net/npm/single-spa@5.8.3/lib/system/single-
spa.min.js"
as="script"
/>
<!-- JavaScript 模块下载地址 此处可放置微前端项目中的公共模块 -->
<script type="systemjs-importmap">
{
"imports": {
"single-spa": "https://cdn.jsdelivr.net/npm/single-
spa@5.8.3/lib/system/single-spa.min.js"
}
}
</script>

六、创建不基于框架的微应用

  1. 应用初始化:mkdir lagou && cd "$_"
  2. 配置 webpack
const { merge } = require("webpack-merge")
const singleSpaDefaults = require("webpack-config-single-spa")

module.exports = () => {
const defaultConfig = singleSpaDefaults({
// 组织名称
orgName: "study",
// 项目名称
projectName: "lagou"
})

return merge(defaultConfig, {
devServer: {
port: 9001
}
})
}
  1. 在 package.json 文件中添加应用启动命令
"scripts": {
"start": "webpack serve"
}
  1. 在应用入口文件中导出微前端应用所需的生命周期函数,生命周期函数必须返回 Promise
let lagouContainer = null

export const bootstrap = async function () {
console.log("应用正在启动")
}
export const mount = async function () {
console.log("应用正在挂载")
lagouContainer = document.createElement("div")
lagouContainer.innerHTML = "Hello Lagou"
lagouContainer.id = "lagouContainer"
document.body.appendChild(lagouContainer)
}
export const unmount = async function () {
console.log("应用正在卸载")
document.body.removeChild(lagouContainer)
}
  1. 在为前端容器应用中注册微前端应用
registerApplication({
name: "@study/lagou",
app: () => System.import("@study/lagou"),
activeWhen: ["/lagou"]
})
  1. 在模板文件中指定模块访问地址
<script type="systemjs-importmap">
{
"imports": {
"@study/lagou": "//localhost:9001/study-lagou.js"
}
}
</script>
  1. 修改默认应用代码
// 注意: 参数的传递方式发生了变化, 原来是传递了一个对象, 对象中有三项配置, 现在是传递了三个参数
registerApplication(
"@single-spa/welcome",
() =>
System.import(
"https://unpkg.com/single-spa-welcome/dist/single-spa-welcome.js"
),
location => location.pathname === "/"
)

七、创建基于 React 的微应用

  1. 创建应用:create-single-spa

    1. 应用目录输入 todos

    2. 框架选择 react

  2. 修改应用端口 && 启动应用

"scripts": {
"start": "webpack serve --port 9002",
}
}
  1. 注册应用,将 React 项目的入口文件注册到基座应用中.
registerApplication({
name: "@study/todos",
app: () => System.import("@study/todos"),
activeWhen: ["/todos"]
})
  1. 指定微前端应用模块的引用地址
<!--=在注册应用时 systemjs 引用了 @study/todos 模块, 所以需要配置该模块的引用地址-->
<script type="systemjs-importmap">
{
"imports": {
"@study/root-config": "//localhost:9000/study-root-config.js",
"@study/todos": "//localhost:9002/study-todos.js"
}
}
</script>
  1. 指定公共库的访问地址

默认情况下,应用中的 react 和 react-dom 没有被 webpack 打包, single-spa 认为它是公共库,不应该单独打包。

<script type="systemjs-importmap">
{
"imports": {
"single-spa": "https://cdn.jsdelivr.net/npm/single-
spa@5.8.3/lib/system/single-spa.min.js",
"react":
"https://cdn.jsdelivr.net/npm/react@17.0.1/umd/react.production.min.js",
"react-dom": "https://cdn.jsdelivr.net/npm/react-dom@17.0.1/umd/react-
dom.production.min.js",
"react-router-dom": "https://cdn.jsdelivr.net/npm/react-router-
dom@5.2.0/umd/react-router-dom.min.js"
}
}
</script>
  1. 微前端 React 应用入口文件代码解析
// react、react-dom 的引用是 index.ejs 文件中 import-map 中指定的版本
import React from "react"
import ReactDOM from "react-dom"
// single-spa-react 用于创建使用 React 框架实现的微前端应用
import singleSpaReact from "single-spa-react"
// 用于渲染在页面中的根组件
import rootComponent from "./root.component"

// 指定根组件的渲染位置
const domElementGetter = () => document.getElementById("todosContainer")
// 错误边界函数
const errorBoundary = () => <div>发生错误时此处内容将会被渲染</div>

// 创建基于 React 框架的微前端应用, 返回生命周期函数对象
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent,
domElementGetter,
errorBoundary
})
// 暴露必要的生命周期函数

export const { bootstrap, mount, unmount } = lifecycles
  1. 路由配置
import React from "react"
import {BrowserRouter, Switch, Route, Redirect, Link} from "react-router-
dom"
import Home from "./pages/Home"
import About from "./pages/About"

export default function Root(props) {
return (
<BrowserRouter basename="/todos">
<div>{props.name}</div>
<div>
<Link to="/home">Home</Link>
<Link to="/about">About</Link>
</div>
<Switch>
<Route path="/home">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Redirect to="/home" />
</Route>
</Switch>
</BrowserRouter>
)
}
  1. 修改 webpack 配置
const { merge } = require("webpack-merge")
const singleSpaDefaults = require("webpack-config-single-spa-react")

module.exports = (webpackConfigEnv, argv) => {
const defaultConfig = singleSpaDefaults({
orgName: "study",
projectName: "todos",
webpackConfigEnv,
argv
})
return merge(defaultConfig, {
externals: ["react-router-dom"]
})
}

八、创建基于 Vue 的微应用

  1. 创建应用:create-single-spa

    1. 项目文件夹填写 realworld

    2. 框架选择 Vue

    3. 生成 Vue 2 项目

  2. 提取 vue && vue-router

// vue.config.js
module.exports = {
chainWebpack: config => {
config.externals(["vue", "vue-router"])
}
}
<script type="systemjs-importmap">
{
"imports": {
"vue": "https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js",
"vue-router": "https://cdn.jsdelivr.net/npm/vue-router@3.0.7/dist/vue-
router.min.js"
}
}
</script>
  1. 修改启动命令 && 启动应用
"scripts": {
	"start": "vue-cli-service serve --port 9003",
}
  1. Vue 应用配置路由
import Vue from "vue"
import VueRouter from "vue-router"
import singleSpaVue from "single-spa-vue"
import App from "./App.vue"

Vue.use(VueRouter)

Vue.config.productionTip = false

// 路由组件
const Foo = { template: "<div>foo</div>" }
const Bar = { template: "<div>bar</div>" }

// 路由规则
const routes = [
{ path: "/foo", component: Foo },
{ path: "/bar", component: Bar }
]

// 路由实例

const router = new VueRouter({ routes, mode: "history", base: "/realworld"
})

const vueLifecycles = singleSpaVue({
Vue,
// 应用配置
appOptions: {
// 路由
router,
// 渲染组件
render(h) {
return h(App, {
// 向组件中传递的数据
props: {
name: this.name,
mountParcel: this.mountParcel,
singleSpa: this.singleSpa
}
})
}
}
})
// 导出生命周期函数
export const bootstrap = vueLifecycles.bootstrap
export const mount = vueLifecycles.mount
export const unmount = vueLifecycles.unmount
<template>
<div id="app">
<h1>{{ name }}</h1>
<p>
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
</div>
</template>

<script>
export default {
name: "App",
props: ["name"]
}
</script>

九、创建 Parcel 应用

Parcel 用来创建公共 UI,涉及到跨框架共享 UI 时需要使用 Parcel。
Parcel 的定义可以使用任何 single-spa 支持的框架,它也是单独的应用,需要单独启动,但是它不关联路由。
Parcel 应用的模块访问地址也需要被添加到 import-map 中,其他微应用通过 System.import 方法进行 引用。

需求:创建 navbar parcel,在不同的应用中使用它。

  1. 使用 React 创建 Parcel 应用 create-single-spa
import React from "react"
import ReactDOM from "react-dom"
import singleSpaReact from "single-spa-react"
import Root from "./root.component"

const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: Root,
errorBoundary(err, info, props) {
// Customize the root error boundary for your microfrontend here.
return null
}
})

export const { bootstrap, mount, unmount } = lifecycles
export default function Root(props) {
return (
<BrowserRouter>
<div>
<Link to="/">@single-spa/welcome</Link>{" "}
<Link to="/lagou">@study/lagou</Link>{" "}
<Link to="/todos">@study/todos</Link>{" "}
<Link to="/realworld">@study/realworld</Link>
</div>
</BrowserRouter>
)
}
  1. 在 webpack 配置文件中去除 react-router-dom
externals: ["react-router-dom"]
  1. 指定端口,启动应用
"scripts": {
"start": "webpack serve --port 9004",
}
  1. 在模板文件中指定应用模块地址
{
"imports": {
"@study/navbar": "//localhost:9004/study-navbar.js"
}
}
  1. 在 React 应用中使用它
import Parcel from "single-spa-react/parcel"

<Parcel config={System.import("@study/navbar")} />
  1. 在 Vue 应用中使用它
<Parcel :config="parcelConfig" :mountParcel="mountParcel" />

<script>
import Parcel from "single-spa-vue/dist/esm/parcel"
import { mountRootParcel } from "single-spa"

export default {
components: {
Parcel
},
data() {
return {
parcelConfig: window.System.import("@study/navbar"),
mountParcel: mountRootParcel
}
}
}
</script>

十、创建 utility modules

用于放置跨应用共享的 JavaScript 逻辑,它也是独立的应用,需要单独构建单独启动。

  1. 创建应用:create-single-spa

    1. 文件夹填写 tools

    2. 应用选择 in-browser utility module (styleguide, api cache, etc)

  2. 修改端口,启动应用

"scripts": {
"start": "webpack serve --port 9005",
}
  1. 应用中导出方法
export function sayHello(who) {
console.log(`%c${who} Say Hello`, "color: skyblue")
}
  1. 在模板文件中声明应用模块访问地址
<script type="systemjs-importmap">
{
"imports": {
"@study/tools": "//localhost:9005/study-tools.js"
}
}
</script>
  1. 在 React 应用中使用该方法
import React, { useEffect, useState } from "react"

function useToolsModule() {
const [toolsModule, setToolsModule] = useState()
useEffect(() => {
System.import("@study/tools").then(setToolsModule)
}, [])
return toolsModule
}

const Home = () => {
const toolsModule = useToolsModule()
if (toolsModule) toolsModule.sayHello("todos")
return <div>Todos home works</div>
}

export default Home
  1. 在 Vue 应用中使用该方法
<h1 @click="handleClick">{{ name }}</h1>
async handleClick() {
let toolsModule = await window.System.import("@study/tools")
toolsModule.sayHello("realworld")
}

十一、实现跨应用通信

跨应用通信可以使用 RxJS,因为它无关于框架,也就是可以在任何其他框架中使用。

  1. 在 index.ejs 文件中添加 rxjs 的 import-map
 {
"imports": {
"rxjs":
"https://cdn.jsdelivr.net/npm/rxjs@6.6.3/bundles/rxjs.umd.min.js"
}
}
  1. 在 utility modules 中导出一个 ReplaySubject,它可以广播历史消息,就算应用是动态加载进来的,也可以接收到数据。
import { ReplaySubject } from "rxjs"

export const sharedSubject = new ReplaySubject()
  1. 在 React 应用中订阅它
useEffect(() => {
let subjection = null
if (toolsModule) {
subjection = toolsModule.sharedSubject.subscribe(console.log)
}
return () => subjection.unsubscribe()
}, [toolsModule])
  1. 在 Vue 应用中订阅它
async mounted() {
let toolsModule = await window.System.import("@study/tools")
toolsModule.sharedSubject.subscribe(console.log)
}

十二、Layout Engine

允许使用组件的方式声明顶层路由,并且提供了更加便捷的路由API用来注册应用。

  1. 下载布局引擎 npm install single-spa-layout@1.3.1

  2. 构建路由

<template id="single-spa-layout">
<single-spa-router>
<application name="@study/navbar"></application>
<route default>
<application name="@single-spa/welcome"></application>
</route>
<route path="lagou">
<application name="@study/lagou"></application>
</route>
<route path="todos">
<application name="@study/todos"></application>
</route>
<route path="realworld">
<application name="@study/realworld"></application>
</route>
</single-spa-router>
</template>
<script type="systemjs-importmap">
{
"imports": {
"@single-spa/welcome": "https://unpkg.com/single-spa-
welcome/dist/single-spa-welcome.js"
}
}
</script>
  1. 获取路由信息 && 注册应用
import { registerApplication, start } from "single-spa"
import { constructApplications, constructRoutes } from "single-spa-layout"

// 获取路由配置对象
const routes = constructRoutes(document.querySelector("#single-spa-layout"))
// 获取路由信息数组
const applications = constructApplications({
routes,
loadApp({ name }) {
return System.import(name)
}
})

applications.forEach(registerApplication)

start({
urlRerouteOnly: true
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/339633.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7 MMSegmentation 代码教学

本文是openmmlab AI实战营的第七次课程的笔记&#xff0c;以下是我比较关注的部分。本次课程的主要内容是 mmsegmentation的代码教学实战&#xff0c;我会稍微详细记载。环境安装云在线平台 &#xff1a;Featurize推荐代码运行环境&#xff1a;GPU RTX3060 ,CUDA 11.2安装pytor…

[SSD固态硬盘技术 0] SSD的结构和原理导论

版权声明&#xff1a; 本文禁止转载机械硬盘的存储系统由于内部结构,其IO访问性能无法进一步提高,CPU与存储器之间的性能差距逐渐扩大。以Nand Flash为存储介质的固态硬盘技术的发展&#xff0c;性能瓶颈得到缓解。1. 什么是SSD固态硬盘&#xff08;Solid State Drives&#xf…

Python爱心代码

前言 Python漂浮爱心&#xff0c;具体源码见&#xff1a;Python动态爱心代码_爱心代码-Python文档类资源-CSDN下载 爱心类 class Heart(): #每个爱心&#xff08;爱心类&#xff09; def __init__(self): self.r ra.randint(10,15) #爱心的半径 …

[LeetCode 1138]字母板上的路径

题目描述 题目链接&#xff1a;[LeetCode 1138]字母板上的路径 我们从一块字母板上的位置 (0, 0) 出发&#xff0c;该坐标对应的字符为 board[0][0]。 在本题里&#xff0c;字母板为board [“abcde”, “fghij”, “klmno”, “pqrst”, “uvwxy”, “z”]&#xff0c;如下所…

图形编辑器:绘制图形需要用到的填充算法

大家好&#xff0c;我是前端西瓜哥。今天我们来谈谈图形编辑器中&#xff0c;简单说说图形编辑实现图形工具&#xff0c;需要用到的填充算法。 图形的特点是宽高是固定的&#xff0c;在图形编辑器绘制图片有两种方案。 一种是将 宽高比锁死&#xff0c;不允许改变&#xff0c…

SpringCloud和微服务介绍

SpringCloud介绍 SpringCloud是在SpringBoot的基础上构建的,用于简化分布式系统构建的工具集。 该工具集为微服务架构中所涉及的配置管理,服务发现,智能路由,断路器,微代理和控制总线等操作提供了一种简单的开发方式。 SpringCloud中包含了多个子项目&#xff1a; Spring …

Properties类读配置文件、修改配置文件

Properties类简介(1)Properties类是专门用于读写配置文件的集合类(2)配置文件的后缀名为.properties,内容格式为:# 可以用“#”作为注释 键值 键值**注意:**键值对不需要有空格,值不需要用引号一起来。默认类型是String。键、值不可以是null(3)Properties类的方法可查找api文档…

Java编程介绍以及学习路线

1.Java的起源 Java源自Sun公司的一个叫Green的项目&#xff0c;其原先的目的是为家用电子消费产品开发一个分布式代码系统&#xff0c;这样就可以将通信和控制信息发给电冰箱、电视机、烤面包机等家用电器&#xff0c;对它们进行控制和信息交流。最初Green项目的工程师们准备采…

数据挖掘,计算机网络、操作系统刷题笔记48

数据挖掘&#xff0c;计算机网络、操作系统刷题笔记48 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;orac…

2.11sql的增删查改

一.CURD(增删查改1.c新增insert往表里添加数据注意事项1.2.3.4.5.如果是蓝丁文的2.R1.全列查找这一步很危险2.指定列查找3.带表达式的查找4.别名5.查找结果去重:DISTINCT6 排序&#xff1a;ORDER BY7 条件查询&#xff1a;WHERE1.比较运算符WHERE条件可以使用表达式&#xff0c…

如何生成毕业论文的目录和创建模板

有粉丝同学最近在写毕业论文&#xff0c;其中比较让人恼火的是毕业论文的目录&#xff0c;折腾了几遍没弄好&#xff0c;想让我写个简单地教程&#xff0c;那就来吧。主要分为三步&#xff1a;第一步是从模板里面提取标题的样式&#xff0c;第二步是对自己的论文使用设置好的标…

DaVinci:调色版本

调色版本 Grade Version记录着片段的全部调色信息。将一种调色风格或效果&#xff0c;保存为一个调色版本&#xff0c;从而可在多个调色版本之间查看、比较、挑选或者渲染输出。调色版本类型本地版本Local Versions在没有创建新的调色版本之前&#xff0c;片段的调色信息默认记…

MySQl单表查询

表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker ( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL, 工资 float(8,2) NOT NULL, 政治面貌 varchar…

1dB压缩点和三阶交调点、相位差与延时

1dB压缩点与三阶交调点 要知道放大器是一个非线性系统&#xff0c;传输函数基本用泰勒级数表示 如果输入信号幅度很小&#xff0c;那么上式中2次及以上的项就可以忽略而成为小信号的情况。在许多情况下我们可以忽略3次以上的项。 如果输入一个正弦信号 1、可以看到一个单频率…

webpack-dev-server 的 host 配置 0.0.0.0

webpack-devserver 的 host 配置 0.0.0.0配置成0.0.0.0有什么意义为什么会有以上现象什么是webpack-dev-server什么是0.0.0.0什么是127.0.0.1什么是localhost配置成0.0.0.0有什么意义 假如某个vue项目的webpack配置如下&#xff1a; 在这module.exports {dev: {...//其余的配…

ubuntu部署quark-5

下载源代码 解压zip sudo apt-get install unzip unzip xxxxx.zip安装所需要的包 sudo apt install python2 # 查看是否配置了默认的python sudo update-alternatives --list python若没有设置&#xff0c;会显示&#xff1a; # update-alternatives: error: no alterna…

多行文本在块元素中垂直居中

单行文本垂直居中对齐 在块元素中&#xff0c;让单行文本居中&#xff0c;可以使用line-height等于块元素的高&#xff0c;即可让该单行文本垂直居中对齐。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><me…

Java:SpringMVC的使用(1)

目录第一章、SpringMVC基本了解1.1 概述1.2 SpringMVC处理请求原理简图第二章、SpringMVC搭建框架1、搭建SpringMVC框架1.1 创建工程【web工程】1.2 导入jar包1.3 编写配置文件(1) web.xml注册DispatcherServlet(2) springmvc.xml(3) index.html1.4 编写请求处理器【Controller…

Android 进阶——Framework核心 之Binder Java成员类详解(三)

文章大纲引言一、Binder Java家族核心成员关系图二、Binder Java家族核心成员源码概述1、android.os.IBinder1.1、boolean transact(int code, Parcel data, Parcel reply, int flags) send a call to an IBinder object1.2、String getInterfaceDescriptor()1.3、boolean ping…

【宝塔部署SpringBoot前后端不分离项目】含域名访问部署、数据库、反向代理、Nginx等配置

一定要弄懂项目部署的方方面面。当服务器上部署的项目过多时&#xff0c;端口号什么时候该放行、什么时候才会发生冲突&#xff1f;多个项目使用redis怎么防止覆盖&#xff1f;Nginx的配置会不会产生站点冲突&#xff1f;二级域名如何合理配置&#xff1f;空闲的时候要自己用服…