背景
随着SPA大规模的应用,紧接着就带来一个新问题:一个规模化应用需要拆分。
一方面功能快速增加导致打包时间成比例上升,而紧急发布时要求是越短越好,这是矛盾的。另一方面当一个代码库集成了所有功能时,日常协作绝对是非常困难的。而且最近十多年,前端技术的发展是非常快的,每隔两年就是一个时代,导致同志们必须升级项目甚至于换一个框架。但如果大家想在一个规模化应用中一个版本做好这件事,基本上是不可能的。
最早的解决方案是采用iframe的方法,根据功能主要模块拆分规模化应用,子应用之间使用跳转。但这个方案最大问题是导致页面重新加载和白屏。
那有什么好的解决方案呢?微前端这样具有跨应用的解决方案在此背景下应运而生了!
微前端的概念
微前端是什么:微前端是一种类似于微服务的架构,是一种由独立交付的多个前端应用组成整体的架构风格,将前端应用分解成一些更小、更简单的能够独立开发、测试、部署的应用,而在用户看来仍然是内聚的单个产品。有一个基座应用 (主应用),来管理各个子应用 的加载和卸载。
f135ab0912746bd6.png
所以微前端不是指具体的库,不是指具体的框架,不是指具体的工具,而是一种理想与架构模式。
微前端的核心三大原则就是:独立运行、独立部署、独立开发
微前端的优势
采用微前端架构的好处就是,将这些小型应用融合为一个完整的应用,或者将原本运行已久、没有关联的几个应用融合为一个应用可以将多个项目融合为一,又可以减少项目之间的耦合,提升项目扩展性。
实现微前端的几种方式
微前端框架的分类
Single-spa
single-spa
是一个很好的微前端基础框架,而qiankun
框架就是基于single-spa
来实现的,在single-spa
的基础上做了一层封装,也解决了single-spa
的一些缺陷。
首先我们先来了解该如何使用single-spa
来完成微前端的搭建。
single-spa.jpg
Single-spa实现原理
首先在基座应用中注册所有App的路由,single-spa
保存各子应用的路由映射关系,充当微前端控制器Controler ,。URL响应时,匹配子应用路由并加载渲染子应用。上图便是对single-spa
完整的描述。
有了理论基础,接下来,我们来看看代码层面时如何使用的。
以下以Vue工程为例基座构建single-spa,在Vue工程入口文件main.js完成基座的配置。
基座配置 //main.js import Vue from 'vue' import App from './App.vue' import router from './router' import { registerApplication, start } from 'single-spa' Vue.config.productionTip = false const mountApp = (url) => { return new Promise((resolve, reject) => { const script = document.createElement('script') script.src = url script.onload = resolve script.onerror = reject // 通过插入script标签的方式挂载子应用 const firstScript = document.getElementsByTagName('script')[0] // 挂载子应用 firstScript.parentNode.insertBefore(script, firstScript) }) } const loadApp = (appRouter, appName) => { // 远程加载子应用 return async () => { //手动挂载子应用 await mountApp(appRouter + '/js/chunk-vendors.js') await mountApp(appRouter + '/js/app.js') // 获取子应用生命周期函数 return window[appName] } } // 子应用列表 const appList = [ { // 子应用名称 name: 'app1', // 挂载子应用 app: loadApp('http://localhost:8083', 'app1'), // 匹配该子路由的条件 activeWhen: location => location.pathname.startsWith('/app1'), // 传递给子应用的对象 customProps: {} }, { name: 'app2', app: loadApp('http://localhost:8082', 'app2'), activeWhen: location => location.pathname.startsWith('/app2'), customProps: {} } ] // 注册子应用 appList.map(item => { registerApplication(item) }) // 注册路由并启动基座 new Vue({ router, mounted() { start() }, render: h => h(App) }).$mount('#app') 复制代码
构建基座的核心是:配置子应用信息,通过registerApplication 注册子应用,在基座工程挂载阶段start 启动基座。
子应用配置 import Vue from 'vue' import App from './App.vue' import router from './router' import singleSpaVue from 'single-spa-vue' Vue.config.productionTip = false const appOptions = { el: '#microApp', router, render: h => h(App) } // 支持应用独立运行、部署,不依赖于基座应用 // 如果不是微应用环境,即启动自身挂载的方式 if (!process.env.isMicro) { delete appOptions.el new Vue(appOptions).$mount('#app') } // 基于基座应用,导出生命周期函数 const appLifecycle = singleSpaVue({ Vue, appOptions }) // 抛出子应用生命周期 // 启动生命周期函数 export const bootstrap = (props) => { console.log('app2 bootstrap') return appLifecycle.bootstrap(() => { }) } // 挂载生命周期函数 export const mount = (props) => { console.log('app2 mount') return appLifecycle.mount(() => { }) } // 卸载生命周期函数 export const unmount = (props) => { console.log('app2 unmount') return appLifecycle.unmount(() => { }) } 复制代码
配置子应用为umd打包方式
//vue.config.js const package = require('./package.json') module.exports = { // 告诉子应用在这个地址加载静态资源,否则会去基座应用的域名下加载 publicPath: '//localhost:8082', // 开发服务器 devServer: { port: 8082 }, configureWebpack: { // 导出umd格式的包,在全局对象上挂载属性package.name,基座应用需要通过这个 // 全局对象获取一些信息,比如子应用导出的生命周期函数 output: { // library的值在所有子应用中需要唯一 library: package.name, libraryTarget: 'umd' } } 复制代码
配置子应用环境变量
// .env.micro NODE_ENV=development VUE_APP_BASE_URL=/app2 isMicro=true 复制代码
子应用配置的核心是用singleSpaVue生成子路由配置后,必须要抛出其生命周期函数 。
用以上方式便可轻松实现一个简单的微前端应用了。
那么我们有single-spa
这种微前端解决方案,为什么还需要qiankun
呢?
相比于single-spa
,qiankun
他解决了JS沙盒环境,不需要我们自己去进行处理。在single-spa
的开发过程中,我们需要自己手动的去写调用子应用JS的方法(如上面的 createScript方法),而qiankun
不需要,乾坤只需要你传入响应的apps的配置即可,会帮助我们去加载。
Qiankun
Qiankun的优势
基于 single-spa[1] 封装,提供了更加开箱即用的 API。
技术栈无关 ,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。
HTML Entry 接入方式 ,让你接入微应用像使用 iframe 一样简单。
样式隔离 ,确保微应用之间样式互相不干扰。
JS 沙箱 ,确保微应用之间 全局变量/事件 不冲突。
资源预加载 ,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
基座配置 import { registerMicroApps, start } from 'qiankun'; registerMicroApps([ { name: 'reactApp', entry: '//localhost:3000', container: '#container', activeRule: '/app-react', }, { name: 'vueApp', entry: '//localhost:8080', container: '#container', activeRule: '/app-vue', }, { name: 'angularApp', entry: '//localhost:4200', container: '#container', activeRule: '/app-angular', }, ]); // 启动 qiankun start(); 复制代码
子应用配置
以 create react app
生成的 react 16
项目为例,搭配 react-router-dom
5.x。
1.在 src
目录新增 public-path.js
,解决子应用挂载时,访问静态资源冲突
if (window.__POWERED_BY_QIANKUN__) { __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; } 复制代码
2.设置 history
模式路由的 base
:
复制代码
3.入口文件 index.js
修改,为了避免根 id #root
与其他的 DOM 冲突,需要限制查找范围。
import './public-path'; import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; function render(props) { const { container } = props; ReactDOM.render(, container ? container.querySelector('#root') : document.querySelector('#root')); } if (!window.__POWERED_BY_QIANKUN__) { render({}); } export async function bootstrap() { console.log('[react16] react app bootstraped'); } export async function mount(props) { console.log('[react16] props from main framework', props); render(props); } export async function unmount(props) { const { container } = props; ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root')); } 复制代码
4.修改 webpack
配置
安装插件 @rescripts/cli
,当然也可以选择其他的插件,例如 react-app-rewired
。
npm i -D @rescripts/cli 复制代码
根目录新增 .rescriptsrc.js
:
const { name } = require('./package'); module.exports = { webpack: (config) => { config.output.library = `${name}-[name]`; config.output.libraryTarget = 'umd'; config.output.jsonpFunction = `webpackJsonp_${name}`; config.output.globalObject = 'window'; return config; }, devServer: (_) => { const config = _; config.headers = { 'Access-Control-Allow-Origin': '*', }; config.historyApiFallback = true; config.hot = false; config.watchContentBase = false; config.liveReload = false; return config; }, }; 复制代码
以上对Qiankun的使用可以看出,与single-spa使用过程很相似。不同的是,Qiankun的使用过程更简便了。一些内置的操作交由给Qiankun内部实现。这是一种IOC思想的实现 ,我们只管面向容器化开发,其他操作交给Qiankun框架管理。
Micro-app
micro-app
并没有沿袭single-spa
的思路,而是借鉴了WebComponent的思想,通过CustomElement结合自定义的ShadowDom,将微前端封装成一个类WebComponent组件,从而实现微前端的组件化渲染。并且由于自定义ShadowDom的隔离特性,micro-app
不需要像single-spa
和qiankun
一样要求子应用修改渲染逻辑并暴露出方法,也不需要修改webpack配置,是目前市面上接入微前端成本最低的方案。
WebComponent的概念
**WebComponent**[2] 是HTML5提供的一套自定义元素的接口,**WebComponent**[3] 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的 web 应用中使用它们。以上是MDN社区对WebComponent的解释。
Custom elements(自定义元素): 一组 JavaScript API,允许您定义 custom elements 及其行为,然后可以在您的用户界面中按照需要使用它们。
Shadow DOM(影子 DOM) :一组 JavaScript API,用于将封装的“影子”DOM 树附加到元素(与主文档 DOM 分开呈现)并控制其关联的功能。通过这种方式,您可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。
HTML templates(HTML 模板): 和
元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。
接下来用一个小例子更快来理解WebComponent的概念。
一个存在组件内交互的WebComponent
// 基于HTMLElement自定义组件元素 class CounterElement extends HTMLElement { // 在构造器中生成shadow节点 constructor() { super(); this.counter = 0; // 打开影子节点 // 影子节点是为了隔离外部元素的影响 const shadowRoot = this.attachShadow({ mode: 'open' }); // 定义组件内嵌样式 const styles = ` #counter-increment { width: 60px; height: 30px; margin: 20px; background: none; border: 1px solid black; } `; // 定义组件HTMl结构 shadowRoot.innerHTML = ` Counter Button ; 0 ; + `; // 获取+号按钮及数值内容 this.incrementButton = this.shadowRoot.querySelector('#counter-increment'); this.counterValue = this.shadowRoot.querySelector('#counter-value'); // 实现点击组件内事件驱动 this.incrementButton.addEventListener("click", this.decrement.bind(this)); } increment() { this.counter++ this.updateValue(); } // 替换counter节点内容,达到更新数值的效果 updateValue() { this.counterValue.innerHTML = this.counter; } } // 在真实dom上,生成自定义组件元素 customElements.define('counter-element', CounterElement); 复制代码
有了对WebComponent的理解,接下来,我们更明白了Micro-app的优势。
micro-app的优势 d879637b4bb34253.png
使用简单
我们将所有功能都封装到一个类WebComponent组件中,从而实现在基座应用中嵌入一行代码即可渲染一个微前端应用。
同时micro-app
还提供了js沙箱
、样式隔离
、元素隔离
、预加载
、数据通信
、静态资源补全
等一系列完善的功能。
零依赖
micro-app
没有任何依赖,这赋予它小巧的体积和更高的扩展性。
兼容所有框架
为了保证各个业务之间独立开发、独立部署的能力,micro-app
做了诸多兼容,在任何技术框架中都可以正常运行。
基座的简易配置
基座存在预加载子应用、父子应用通信、公共文件共享等等
// index.js import React from "react" import ReactDOM from "react-dom" import App from './App' import microApp from '@micro-zoe/micro-app' const appName = 'my-app' // 预加载 microApp.preFetch([ { name: appName, url: 'xxx' } ]) // 基座向子应用数据通信 microApp.setData(appName, { type: '新的数据' }) // 获取指定子应用数据 const childData = microApp.getData(appName) microApp.start({ // 公共文件共享 globalAssets: { js: ['js地址1', 'js地址2', ...], // js地址 css: ['css地址1', 'css地址2', ...], // css地址 } }) 复制代码
分配一个路由给子应用
// router.js import { BrowserRouter, Switch, Route } from 'react-router-dom' export default function AppRoute () { return ( ) } 复制代码
子应用的简易配置 // index.js import React from "react" import ReactDOM from "react-dom" import App from './App' import microApp from '@micro-zoe/micro-app' const appName = 'my-app' // 子应用运行时,切换静态资源访问路径 if (window.__MICRO_APP_ENVIRONMENT__) { __webpack_public_path__ = window.__MICRO_APP_PUBLIC_PATH__ } // 基子应用向基座发送数据 // dispatch只接受对象作为参数 window.microApp.dispatch({ type: '子应用发送的数据' }) // 获取基座数据 const data = window.microApp.getData() // 返回基座下发的data数据 //性能优化,umd模式 // 如果子应用渲染和卸载不频繁,那么使用默认模式即可,如果子应用渲染和卸载非常频繁建议使用umd模式 // 将渲染操作放入 mount 函数 -- 必填 export function mount() { ReactDOM.render(, document.getElementById("root")) } // 将卸载操作放入 unmount 函数 -- 必填 export function unmount() { ReactDOM.unmountComponentAtNode(document.getElementById("root")) } // 微前端环境下,注册mount和unmount方法 if (window.__MICRO_APP_ENVIRONMENT__) { window[`micro-app-${window.__MICRO_APP_NAME__}`] = { mount, unmount } } else { // 非微前端环境直接渲染 mount() } 复制代码
设置子应用路由
import { BrowserRouter, Switch, Route } from 'react-router-dom' export default function AppRoute () { return ( // 设置基础路由,子应用可以通过window.__MICRO_APP_BASE_ROUTE__获取基座下发的baseroute, // 如果没有设置baseroute属性,则此值默认为空字符串 ... ) } 复制代码
以上便是Micro-app的用法
Module Federation
Module Federation是Webpack5提出的概念,module federation用来解决多个应用之间代码共享 的问题,让我们更加优雅的实现跨应用 的代码共享。
MF 想做的事和微前端想解决的问题是类似的,把一个应用进行拆分成多个应用,每个应用可独立开发,独立部署,一个应用可以动态加载 并运行另一个应用的代码,并实现应用之间的依赖共享。
为了实现这样的功能, MF在设计上提出了这几个核心概念。
Container
一个被 ModuleFederationPlugin 打包出来的模块被称为 Container 。通俗点讲就是,如果我们的一个应用使用了 ModuleFederationPlugin 构建,那么它就成为一个 Container ,它可以加载其他的 Container ,可以被其他的 Container 所加载。
Host&Remote
从消费者和生产者的角度看 Container ,Container 又可被称作 Host 或 Remote 。
Host
:消费方,它动态加载并运行其他 Container 的代码。
Remote
:提供方,它暴露属性 (如组件、方法等)供 Host 使用
可以知道,这里的 Host 和 Remote 是相对的,因为 一个 Container 既可以作为 Host ,也可以作为 Remote 。
Shared
一个 Container 可以 Shared 它的依赖(如 react、react-dom)给其他 Container 使用,也就是共享依赖。
微信图片_20220626184254.png 微信图片_20220626184305.png
以上是webpack5与之前版本的模块管理对比图
微应用配置
通过webpack5的配置达成微应用的效果
// 配置webpack.config.js const { ModuleFederationPlugin } = require("webpack").container; new ModuleFederationPlugin({ name: "appA", //出口文件 filename: "remoteEntry.js", //暴露可访问的组件 exposes: { "./input": "./src/input", }, //或者其他模块的组件 //如果把这一模块当作基座模块的话, //这里应该配置其他子应用模块的入口文件 remotes: { appB: "appB@http://localhost:3002/remoteEntry.js", }, //共享依赖,其他模块不需要再次下载,便可使用 shared: ['react', 'react-dom'], }) 复制代码
以上便是我对微应用架构的理解,以及微应用架构技术的演变过程。不难看出,这些技术的演变都朝着易用性和可拓展性的方向演进。其中技术也有其时代的局限性,不过思想和技术总是在不断进步的。这几类技术选型都有其优缺点,各有千秋,我们可以根据不同的需要选择不同的技术来构建应用。
下列是本文写作时的参考资料:
single-spa: zh-hans.single-spa.js.org/docs/gettin…[4]
qiankun: qiankun.umijs.org/zh/guide[5]
WebComponent: developer.mozilla.org/zh-CN/docs/…[6]
micro-app: cangdu.org/micro-app/d…[7]
关于本文
作者:花小白
https://juejin.cn/post/7113503219904430111
最后
欢迎关注「前端达人」
你可能感兴趣的:(vue,react,js,javascript,java)
136道Vue面试八股文(答案、分析和深入提问)整理
守护海洋的猫
vue.js 面试 javascript 前端 ecmascript
1.简述mixin、extends的覆盖逻辑回答在Vue中,mixins和extends是用来实现代码复用的两种方式,但它们在覆盖逻辑上有一些细微的区别。1.Mixin当你使用mixins的时候,可以将多个功能组合在一起。Mixins的内容会与组件中的数据、方法、生命周期钩子等进行合并。数据:Mixin中的数据会与组件中的数据合并。如果两个数据属性同名,则组件的数据属性会覆盖mixin中的属性。方
了解Javascript中的异步等待
Brook_
JavaScript javascript 异步
在本文中,我们将探讨async/await对于每个Javascript开发人员来说,异步编程的首选工具。如果您不熟悉javascript,请不要担心,本文将帮助您async/await从头开始理解。介绍async/await是javascript中的一种模式,可使您的代码以同步方式执行,但又不影响javascript的异步行为。定义异步功能要定义一个异步函数,您所要做的只是在函数定义之前添加一个a
玩转网页交互:用JavaScript打造灵动手风琴特效
skyksksksksks
综合个人杂记 javascript 交互 jquery html5 css 前端
一、手风琴特效:网页中的魔法折叠术想象一下你在音乐厅看到的手风琴演奏——轻轻一拉,风箱便如波浪般起伏展开。在网页世界中,手风琴特效正是这种优雅互动的数字化身!当用户点击某个标题时,对应的内容就像被施了魔法般缓缓展开,其他内容则默契地折叠收起。这种设计不仅节省空间,更能让用户像探索藏宝图一样,逐步揭开内容的奥秘。在电商网站的商品详情页,在知识平台的问答专区,甚至在个人作品集网站,手风琴特效都扮演着重
Vue 3 Composition API进阶指南
前端学步
Vue3技术分享专栏 vue.js javascript 前端
在上一篇文章中,我们介绍了Vue3的CompositionAPI基础,包括如何使用setup函数、ref和reactive来创建响应式数据,以及使用watchEffect来监控数据变化。本文将继续深入探讨CompositionAPI的高级用法,帮助你更好地理解和利用Vue3的新特性。组合多个Hooks在实际开发中,我们经常需要组合使用多个自定义的Hooks来实现复杂的功能。Vue3的Composi
nextjs中集成富文本编辑器wangEditor
不cong明的亚子
前端 nodejs react 前端 next.js 富文本编辑器
Vue3CompositionAPI
jpruby
vue
Vue3CompositionAPI第一章最终效果演示1.下载依赖npminstall2.启动前端npmrundev3.启动数据json-server--watchdata/db.json--port=3003第二章创建项目1.vite创建项目npminitvite@latestvite-blog----templatevue2.App.vueApp.vue3.Home.vue1.测试setup的
菜鸟的成长之路
东风吹破了青花瓷
计算机 数据结构与算法 基础篇 入门
菜鸟的成长之路基础能力数据结构与算法数据结构链表数组栈队列字典bitset树堆完全二叉树平衡二叉树二叉查找树B树红黑树lsm树图通用算法排序十种排序算法查找二分查找深度广度优先搜索分治贪心回朔动态规划网络协议OSITCP/IP状态转移拥塞控制可靠工作原理socket编程HTTP/HTTPSIO模型同步IOreactor阻塞IO非阻塞IOIO多路复用信号驱动异步IOC10K问题长链接短链接编译原理l
解释一下this在异步函数中的行为
祈澈菇凉
前端 javascript 开发语言
在JavaScript中,this关键字在异步函数中的行为可能会让人感到困惑。异步函数的执行方式与普通函数不同,这会影响this的指向。下面将详细阐述this在异步函数中的行为,以及如何正确管理this。一、this的基本行为回顾在JavaScript中,this的指向取决于函数的调用方式:全局上下文:在全局作用域中,this指向全局对象(在浏览器中是window)。对象方法:当函数作为对象的方法
Vue3的Composition API
Sunshinedada
vue.js 前端 javascript
Vue3的CompositionAPI(Vue3与Vue2的区别)Vue3引入了CompositionAPI(组合式API),这是一种新的编写组件逻辑的方式,旨在解决OptionsAPI在某些场景下的局限性。CompositionAPI提供了更灵活和强大的代码组织方式,特别适合处理复杂组件的逻辑复用和代码组织。CompositionAPI的核心概念1.setup函数:-setup是Composit
初始java常见模板
xx2534
java 开发语言
Java是一种适用于多种应用程序的编程语言,支持各种不同类型和规模的开发项目,其模板也相对较多,以下是Java的一些常见模板:基础的HelloWorld模板:publicclassHelloWorld{publicstaticvoidmain(String[]args){System.out.println("Hello,World!");}}2.类和对象模板:publicclassPerson{
使用EasyExcel和多线程实现高效数据导出
刘_sy
java工具类 数据库 java excel 批量导出Excel EasyExcel
使用EasyExcel和多线程实现高效数据导出1.概述在企业级应用中,数据导出是一个常见的需求。为了提高导出效率,尤其是在处理大量数据时,我们可以结合使用EasyExcel库和多线程技术。本文将详细介绍如何通过EasyExcel和多线程技术实现高效的数据导出功能。2.环境准备2.1Java版本Java版本:本项目基于Java开发。2.2依赖库com.alibaba:easyexcel:用于Exce
java nio编程实例_Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
weixin_39723010
java nio编程实例
1、BIO编程1.1、传统的BIO编程网络编程的基本模型是C/S模型,即两个进程间的通信。服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信。传统的同步阻塞模型开发中,ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。简单
PyWebIo 快速构建web应用
java全套学习资料
前端 html npm vue.js 前端
Part1什么是PyWebIoPyWebIO提供了一系列命令式的交互函数来在浏览器上获取用户输入和进行输出,将浏览器变成了一个“富文本终端”,可以用于构建简单的Web应用或基于浏览器的GUI应用。使用PyWebIO,开发者能像编写终端脚本一样(基于input和print进行交互)来编写应用,无需具备HTML和JS的相关知识;PyWebIO还可以方便地整合进现有的Web服务。非常适合快速构建对UI要
es6箭头函数和普通函数的区别
vvilkim
es6 前端 ecmascript
在JavaScript中,函数是执行特定任务的代码块。函数可以被定义并且随后被调用。JavaScript中有两种主要的函数定义方式:普通函数声明和箭头函数表达式。下面是这两种函数的定义方式及其区别和使用场景:普通函数声明普通函数可以通过函数声明或函数表达式的方式来定义。函数声明是最简单的方式,通常如下所示:function函数名(参数1,参数2,...){//函数体}示例:functiongree
java 输入输出模板
wangzhuo0978
模板
importjava.io.*;importjava.util.StringTokenizer;publicclassMain{publicstaticvoidmain(String[]args){InputStreaminputStream=System.in;OutputStreamoutputStream=System.out;InputReaderin=newInputReader(inp
Maven 与 Spring Boot 项目的集成
drebander
Maven maven spring boot java
在Java开发中,Maven和SpringBoot是最常见的工具和框架。Maven用于构建和管理项目的依赖,而SpringBoot提供了简化的Spring应用开发方式。将Maven和SpringBoot集成,可以帮助我们更高效地构建和部署SpringBoot应用。本文将介绍如何将Maven与SpringBoot集成,并通过Maven构建和管理SpringBoot项目。1.什么是SpringBoot
基于python sanic框架,使用Nacos进行微服务管理
一醉千秋
python+银河麒麟 微服务 java 架构
微服务软件系统构建方式,已经很普及了,通过开源的sanic进行微服务管理,便捷,技术也比较成熟,而在项目实际应用过程中,微服务类型不仅有java的,还有nodejs、python等,尤其是结合算法模型构建的python接口,需要在Nacos进行注册管理。本文内容耗时2天踏坑,亲测一切ok。参考资源Docker安装nacos(图文并茂,避免踩坑,一步到位)_docker创建nacos容器需要挂载哪些
vue之弹框
ramsey17
vue.js javascript 前端
实现如下需求,点击新增或者行中的编辑按钮,弹出弹框编辑数据。列表中的操作栏:通过slot-scope="scope"来接收作用域插槽的数据(添加属性slot-scope,并且定义对象scope),scope.row拿到对应行的数据;弹框的“新增/修改角色”标题根据states的值来控制,编辑时,“人员名称”处于禁用状态;由于弹框的参数(只有id)满足不了(少于)请求接口的参数(id和name),通
vue select下拉框选项内容过长显示问题
ramsey17
vue.js javascript elementui
如下图的select下拉框的选项的内容过长时,页面显示不协调,通过如下方法把过长的内容用...代替;在任务名称-->在style中添加.el-select::v-deep.popper-class{width:200px;}#sx.el-row.el-select::v-deep.popper-class{width:200px;}
js根据两个经纬度点计算文字显示角度
钱端工程师
javascript
主要用到Turf.js库中的一个方法:rhumbBearing。用于计算两点之间的罗盘方位角(也称为恒向线角或罗盘角)。这种方法假设地球是一个球体,并且沿着最短路径(即大圆路径)测量两点之间的距离和方位角,但在计算方位角时采用了一种简化的方法,即假设沿恒向线(罗盘线)航行。1.安装Turf.js://在项目目录的命令行中输入:npminstall@turf/turf2.使用:import{rhum
vue 解决image-conversion图片处理插件压缩后图片底色变黑问题
qq_48354174
vue.js javascript
官方文档https://www.npmjs.com/package/image-conversion将el-upload封装为一个组件,并将图片上传到对象存储引用方式importSingleUploadfrom"@/components/upload/singleUpload"//isWatermark是否需要水印changeFile方法判断是否是透明图片,如果是透明图片将底部改为透明色impor
JDBC之JAVA连接数据库方法5
倾心凝望
JDBC java 数据库 开发语言
文章目录方式5.使用数据库连接池获取连接方式5.使用数据库连接池获取连接下载依赖添加方式1:pom.xml文件中引入com.alibabadruid1.2.24添加方式2:druid-1.2.24.jar包引入下载网址:https://download.csdn.net/download/qq_44042106/90399318jar包引入同方法4:第三方组件读取properties文件连接编写配
GcExcel
arguments_zd
spreadjs 前端 前端框架
GcExcel简述:GcExcelJava是一款基于Java平台,支持批量创建、编辑、打印、导入/导出Excel文件的服务端表格组件,能够高性能处理和高度兼容Excel。功能特性(图1)文档查询(图2)
介绍一下常用的代码规范工具,如ESLint和Prettier
祈澈菇凉
代码规范
代码规范工具是现代软件开发中不可或缺的一部分,它们帮助开发者维持代码质量、提高可读性并确保一致性。以下是两种常用的代码规范工具:ESLint和Prettier的详细介绍。ESLint1.概述ESLint是一个用于JavaScript代码的静态代码分析工具,主要用于识别和报告代码中的问题。它可以帮助开发者发现潜在的错误、提高代码质量并保持代码风格的一致性。2.主要功能代码检查:ESLint可以检测语
async/await与Generator函数相比有什么区别?
编程微刊
前端 javascript 开发语言
async/await和Generator函数都是JavaScript中处理异步编程的重要工具,但它们在语法、使用方式和背后的机制上存在显著差异。以下是它们之间的主要区别:一、基本概念1.Generator函数Generator函数是通过function*关键字定义的特殊函数,可以暂停和恢复执行。它们返回一个迭代器对象,通过调用.next()方法逐步执行函数中的代码。示例function*gene
jvm的内存分配机制
四条腿
java虚拟机 jvm 内存分配 内存
在学习jvm的内存分配的时候,看到的这篇博客,该博客对jvm的内存分配总结的很好,同时也利用jvm的内存模型解释了java程序中有关参数传递的问题。博客出处:http://www.cnblogs.com/hellocsl/p/3969768.html?utm_source=tuicool&utm_medium=referral看了此博客后,发现应该去深入学习下jvm的内存模型,就是去认真学习下《深
【Java进阶篇】——第11篇:Java 8 新特性及使用
猿享天开
Java开发从入门到精通 java 开发语言
第11篇:Java8新特性及使用Java8是一次里程碑式的更新,引入了多项革新特性,极大地提升了开发效率和代码表现力。本文将从Lambda表达式、StreamAPI、时间日期API、Optional类等核心特性出发,结合实战场景和最佳实践,全面解析Java8的核心功能。1.Lambda表达式与函数式编程1.1Lambda表达式基础Lambda表达式允许以简洁的语法实现函数式接口(仅含一个抽象方法的
华为OD机试 - Excel 单元格数值统计(Python) | 机试题算法思路 【2023】
梦想橡皮擦
excel 华为 python 算法 华为od
最近更新的博客华为OD机试题-最短耗时(JavaScript)华为OD机试题-机器人走迷宫(JavaScript)华为OD机试-新员工座位安排系统(Python)|机试题算法思路华为OD机试-能力组队(Python)|机试题算法思路华为OD机试-内存池(Python)|机试题算法思路使用说明参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。华为OD清单查看地址:bl
新数据结构(10)——Java抽象类和接口
Ut Relinquam
java 数据结构 算法
抽象类抽象类产生原因子类可以重写父类中的方法并覆盖父类中的变量抽象类会将子类里共有的代码逻辑进行提取和抽象化抽象类通常被设计作为父类来实现代码复用抽象类的特点抽象类只需要做方法的定义,不需要实现一个被abstract修饰的类被称为抽象类,一个由abstract修饰的方法则被称为抽象方法。由abstract修饰的抽象方法,通常不在抽象类本身中实现,而是作为必须由子类覆盖和实现的方法的定义存在。只有抽
【论文投稿-第五届人工智能与工业技术应用国际学术会议(AIITA 2025)】编程语言大比拼:C、C++、Python 和 Java
禁默
话题探讨 学术会议 c语言 c++ python
第五届人工智能与工业技术应用国际学术会议(AIITA2025)将于2025年3月28-30日在中国西安举行。会议旨在为从事人工智能、智能制造、自动化等领域的专家学者、工程技术人员、研发人员提供一个共享科研成果和前沿技术,了解学术发展趋势,拓宽研究思路,加强学术研究和探讨,促进学术成果产业化合作的平台。编辑AIITA2025已上线至IEEE官方列表,详情请点击....大会时间:2025年3月28日-
JAVA中的Enum
周凡杨
java enum 枚举
Enum是计算机编程语言中的一种数据类型---枚举类型。 在实际问题中,有些变量的取值被限定在一个有限的范围内。 例如,一个星期内只有七天 我们通常这样实现上面的定义:
public String monday;
public String tuesday;
public String wensday;
public String thursday
赶集网mysql开发36条军规
Bill_chen
mysql 业务架构设计 mysql调优 mysql性能优化
(一)核心军规 (1)不在数据库做运算 cpu计算务必移至业务层; (2)控制单表数据量 int型不超过1000w,含char则不超过500w; 合理分表; 限制单库表数量在300以内; (3)控制列数量 字段少而精,字段数建议在20以内
Shell test命令
daizj
shell 字符串 test 数字 文件比较
Shell test命令
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。 数值测试 参数 说明 -eq 等于则为真 -ne 不等于则为真 -gt 大于则为真 -ge 大于等于则为真 -lt 小于则为真 -le 小于等于则为真
实例演示:
num1=100
num2=100if test $[num1]
XFire框架实现WebService(二)
周凡杨
java webservice
有了XFire框架实现WebService(一),就可以继续开发WebService的简单应用。
Webservice的服务端(WEB工程):
两个java bean类:
Course.java
package cn.com.bean;
public class Course {
private
重绘之画图板
朱辉辉33
画图板
上次博客讲的五子棋重绘比较简单,因为只要在重写系统重绘方法paint()时加入棋盘和棋子的绘制。这次我想说说画图板的重绘。
画图板重绘难在需要重绘的类型很多,比如说里面有矩形,园,直线之类的,所以我们要想办法将里面的图形加入一个队列中,这样在重绘时就
Java的IO流
西蜀石兰
java
刚学Java的IO流时,被各种inputStream流弄的很迷糊,看老罗视频时说想象成插在文件上的一根管道,当初听时觉得自己很明白,可到自己用时,有不知道怎么代码了。。。
每当遇到这种问题时,我习惯性的从头开始理逻辑,会问自己一些很简单的问题,把这些简单的问题想明白了,再看代码时才不会迷糊。
IO流作用是什么?
答:实现对文件的读写,这里的文件是广义的;
Java如何实现程序到文件
No matching PlatformTransactionManager bean found for qualifier 'add' - neither
林鹤霄
java.lang.IllegalStateException: No matching PlatformTransactionManager bean found for qualifier 'add' - neither qualifier match nor bean name match!
网上找了好多的资料没能解决,后来发现:项目中使用的是xml配置的方式配置事务,但是
Row size too large (> 8126). Changing some columns to TEXT or BLOB
aigo
column
原文:http://stackoverflow.com/questions/15585602/change-limit-for-mysql-row-size-too-large
异常信息:
Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAM
JS 格式化时间
alxw4616
JavaScript
/**
* 格式化时间 2013/6/13 by 半仙
[email protected]
* 需要 pad 函数
* 接收可用的时间值.
* 返回替换时间占位符后的字符串
*
* 时间占位符:年 Y 月 M 日 D 小时 h 分 m 秒 s 重复次数表示占位数
* 如 YYYY 4占4位 YY 占2位<p></p>
* MM DD hh mm
队列中数据的移除问题
百合不是茶
队列移除
队列的移除一般都是使用的remov();都可以移除的,但是在昨天做线程移除的时候出现了点问题,没有将遍历出来的全部移除, 代码如下;
//
package com.Thread0715.com;
import java.util.ArrayList;
public class Threa
Runnable接口使用实例
bijian1013
java thread Runnable java多线程
Runnable接口
a. 该接口只有一个方法:public void run();
b. 实现该接口的类必须覆盖该run方法
c. 实现了Runnable接口的类并不具有任何天
oracle里的extend详解
bijian1013
oracle 数据库 extend
扩展已知的数组空间,例:
DECLARE
TYPE CourseList IS TABLE OF VARCHAR2(10);
courses CourseList;
BEGIN
-- 初始化数组元素,大小为3
courses := CourseList('Biol 4412 ', 'Psyc 3112 ', 'Anth 3001 ');
--
【httpclient】httpclient发送表单POST请求
bit1129
httpclient
浏览器Form Post请求
浏览器可以通过提交表单的方式向服务器发起POST请求,这种形式的POST请求不同于一般的POST请求
1. 一般的POST请求,将请求数据放置于请求体中,服务器端以二进制流的方式读取数据,HttpServletRequest.getInputStream()。这种方式的请求可以处理任意数据形式的POST请求,比如请求数据是字符串或者是二进制数据
2. Form
【Hive十三】Hive读写Avro格式的数据
bit1129
hive
1. 原始数据
hive> select * from word;
OK
1 MSN
10 QQ
100 Gtalk
1000 Skype
2. 创建avro格式的数据表
hive> CREATE TABLE avro_table(age INT, name STRING)STORE
nginx+lua+redis自动识别封解禁频繁访问IP
ronin47
在站点遇到攻击且无明显攻击特征,造成站点访问慢,nginx不断返回502等错误时,可利用nginx+lua+redis实现在指定的时间段 内,若单IP的请求量达到指定的数量后对该IP进行封禁,nginx返回403禁止访问。利用redis的expire命令设置封禁IP的过期时间达到在 指定的封禁时间后实行自动解封的目的。
一、安装环境:
CentOS x64 release 6.4(Fin
java-二叉树的遍历-先序、中序、后序(递归和非递归)、层次遍历
bylijinnan
java
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
public class BinTreeTraverse {
//private int[] array={ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
private int[] array={ 10,6,
Spring源码学习-XML 配置方式的IoC容器启动过程分析
bylijinnan
java spring IOC
以FileSystemXmlApplicationContext为例,把Spring IoC容器的初始化流程走一遍:
ApplicationContext context = new FileSystemXmlApplicationContext
("C:/Users/ZARA/workspace/HelloSpring/src/Beans.xml&q
[科研与项目]民营企业请慎重参与军事科技工程
comsci
企业
军事科研工程和项目 并非要用最先进,最时髦的技术,而是要做到“万无一失”
而民营科技企业在搞科技创新工程的时候,往往考虑的是技术的先进性,而对先进技术带来的风险考虑得不够,在今天提倡军民融合发展的大环境下,这种“万无一失”和“时髦性”的矛盾会日益凸显。。。。。。所以请大家在参与任何重大的军事和政府项目之前,对
spring 定时器-两种方式
cuityang
spring quartz 定时器
方式一:
间隔一定时间 运行
<bean id="updateSessionIdTask" class="com.yang.iprms.common.UpdateSessionTask" autowire="byName" />
<bean id="updateSessionIdSchedule
简述一下关于BroadView站点的相关设计
damoqiongqiu
view
终于弄上线了,累趴,戳这里http://www.broadview.com.cn
简述一下相关的技术点
前端:jQuery+BootStrap3.2+HandleBars,全站Ajax(貌似对SEO的影响很大啊!怎么破?),用Grunt对全部JS做了压缩处理,对部分JS和CSS做了合并(模块间存在很多依赖,全部合并比较繁琐,待完善)。
后端:U
运维 PHP问题汇总
dcj3sjt126com
windows2003
1、Dede(织梦)发表文章时,内容自动添加关键字显示空白页
解决方法:
后台>系统>系统基本参数>核心设置>关键字替换(是/否),这里选择“是”。
后台>系统>系统基本参数>其他选项>自动提取关键字,这里选择“是”。
2、解决PHP168超级管理员上传图片提示你的空间不足
网站是用PHP168做的,反映使用管理员在后台无法
mac 下 安装php扩展 - mcrypt
dcj3sjt126com
PHP
MCrypt是一个功能强大的加密算法扩展库,它包括有22种算法,phpMyAdmin依赖这个PHP扩展,具体如下:
下载并解压libmcrypt-2.5.8.tar.gz。
在终端执行如下命令: tar zxvf libmcrypt-2.5.8.tar.gz cd libmcrypt-2.5.8/ ./configure --disable-posix-threads --
MongoDB更新文档 [四]
eksliang
mongodb Mongodb更新文档
MongoDB更新文档
转载请出自出处:http://eksliang.iteye.com/blog/2174104
MongoDB对文档的CURD,前面的博客简单介绍了,但是对文档更新篇幅比较大,所以这里单独拿出来。
语法结构如下:
db.collection.update( criteria, objNew, upsert, multi)
参数含义 参数
Linux下的解压,移除,复制,查看tomcat命令
y806839048
tomcat
重复myeclipse生成webservice有问题删除以前的,干净
1、先切换到:cd usr/local/tomcat5/logs
2、tail -f catalina.out
3、这样运行时就可以实时查看运行日志了
Ctrl+c 是退出tail命令。
有问题不明的先注掉
cp /opt/tomcat-6.0.44/webapps/g
Spring之使用事务缘由(3-XML实现)
ihuning
spring
用事务通知声明式地管理事务
事务管理是一种横切关注点。为了在 Spring 2.x 中启用声明式事务管理,可以通过 tx Schema 中定义的 <tx:advice> 元素声明事务通知,为此必须事先将这个 Schema 定义添加到 <beans> 根元素中去。声明了事务通知后,就需要将它与切入点关联起来。由于事务通知是在 <aop:
GCD使用经验与技巧浅谈
啸笑天
GC
前言
GCD(Grand Central Dispatch)可以说是Mac、iOS开发中的一大“利器”,本文就总结一些有关使用GCD的经验与技巧。
dispatch_once_t必须是全局或static变量
这一条算是“老生常谈”了,但我认为还是有必要强调一次,毕竟非全局或非static的dispatch_once_t变量在使用时会导致非常不好排查的bug,正确的如下: 1
linux(Ubuntu)下常用命令备忘录1
macroli
linux 工作 ubuntu
在使用下面的命令是可以通过--help来获取更多的信息1,查询当前目录文件列表:ls
ls命令默认状态下将按首字母升序列出你当前文件夹下面的所有内容,但这样直接运行所得到的信息也是比较少的,通常它可以结合以下这些参数运行以查询更多的信息:
ls / 显示/.下的所有文件和目录
ls -l 给出文件或者文件夹的详细信息
ls -a 显示所有文件,包括隐藏文
nodejs同步操作mysql
qiaolevip
学习永无止境 每天进步一点点 mysql nodejs
// db-util.js
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host: 'localhost',
user: 'root',
password: '',
database: 'test',
port: 3306
});
一起学Hive系列文章
superlxw1234
hive Hive入门
[一起学Hive]系列文章 目录贴,入门Hive,持续更新中。
[一起学Hive]之一—Hive概述,Hive是什么
[一起学Hive]之二—Hive函数大全-完整版
[一起学Hive]之三—Hive中的数据库(Database)和表(Table)
[一起学Hive]之四-Hive的安装配置
[一起学Hive]之五-Hive的视图和分区
[一起学Hive
Spring开发利器:Spring Tool Suite 3.7.0 发布
wiselyman
spring
Spring Tool Suite(简称STS)是基于Eclipse,专门针对Spring开发者提供大量的便捷功能的优秀开发工具。
在3.7.0版本主要做了如下的更新:
将eclipse版本更新至Eclipse Mars 4.5 GA
Spring Boot(JavaEE开发的颠覆者集大成者,推荐大家学习)的配置语言YAML编辑器的支持(包含自动提示,