⑴ 记录用qiankun微前端改造 路由hash模式
最近来了个新项目,老系统升级。老系统本身是个很多应用混毕饥在一起的一个公众号应用。因为历史原因很杂。现在要开始一点点升级。很多子模块不能一次完成升级,所以是新老应用并行的情况,我就想到了粗睁用微前端改造。手凳返
我选择的是 qiankun 这个轮子。主应用、微应用 都选择的是 vue2.x (因为老项目都是vue开发,qiankun可以兼容所有框架) 。路由模式都是选择的hash。 但是history模式更优雅一点。但是需要服务器端配置。
b. 注册微应用入口
b. 修改main.js
c. 修改webpack配置
⑵ 从源码理解总结web容器、spring容器、spring mvc容器三者关系
本篇,我打算从springMVC项目的web.xml的配置文件入手,通过部分源码逐步去理解解释三个容器的关系以及调用顺序,因为是基于我个人的理解,可能有所不足。
一般web.xml文件里会有如下两段配置信息:
我们先了解下web.xml,以下引用自 《web.xml文件是什么?有什么用?--详解》 :
然后结合我们上面的web.xml中关于spring和spring mvc的配置信息来进入话题:
首先,启动web容器的时,会先生成对应项目的ServelContent对象,这个是每个项目的上下文,这个ServelContent可以管理所有的servlet,并将我们web.xml中设置的<context-param>内容作为键值对交给这个对象。
然后加载<listener>标签内容,这个时候就会产生org.springframework.web.context.ContextLoaderListener。
spring的这个 ContextLoaderListener 在接下来的过程中很重要,我们来看一下源码
首先,可以看出它继承了ContextLoader类,并实现了ServletContextListener接口。
这里再直接引用他人的结论 《Spring中ContextLoaderListener作用》
好了,人家说法中回到我们的起点了,我们基本都被人告知“ContextLoaderListener的作用是创建并初始化spring容器”
那我们就可以深入进去看看,到底哪里做了这一步:
首先,我们知道了ServletContextListene是ServletContext的监听者,监听器的响应动作就是在服务器启动时contextInitialized会被调用,关闭的时候contextDestroyed被调用,这个好理解,那我们就来看一下ContextLoaderListener重写的contextInitialized方法到底做了什么。
我们再进入观察initWebApplicationContext方法细看
我因为自己消化过一遍,直接给出关键位置的方法说明——
1、首先是278行:创建了WebApplicationContext,我们可以理解为spring容器的壳子有了
2、其次是288和289行:对ApplicationContext加载了配置文件,并设置servletContext为WebApplicationContext的parent,到这一步,可以理解为我们的spring容器也就差不多成型了
3、接下来是294行:把ApplicationContext对象以键值对的形式存到servletContext中,这一步很关键,就是因为servletContext中存在这个键值对,所以其他内部成员可以通过servletContext访问到ApplicationContext,当然也能使用其管理的bean,而spring mvc则没有这样存在servletContext,所以我觉得正是这一步决定了子容器springmvc可以取用父容器内的bean,反着则不然。
接下来直到轮到我们的springmvc容器<servlet>标签内容
会生成控制org.springframework.web.servlet.DispatcherServlet,这是一个前端控制器,主要的内容我之前也有一篇文章做过自我记录
《Spring MVC的工作机制简单理解》
我们可以看到设置的
<load-on-startup>1</load-on-startup>
这个标签大概意思就是:
1、load-on-startup 元素标记容器是否应该在web应用程序启动的时候就加载这个servlet,(实例化并调用其init()方法)。
2、它的值必须是一个整数,表示servlet被加载的先后顺序。
3、如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载。
4、如果值为正整数或者0时,表示容器在应用启动时就加载并初始化这个servlet,值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
在DispatcherServlet的时候就根据springMVC容器容器的配置文件生成。
比如我这边就是
那顺序确定了,我们再看一下spring和spring mvc的父子关系哪里确定:
我们可以从下面3个截图看到dispatcherServlet的继承关系,同时,init方法用的是dispatcherServlet父类的父类的方法。
重点在于initServletBean()方法,经过追踪,我们找到该方法的最终实现又是在dispatcherServlet的父类FrameworkServlet中
其中涉及父子关系的实际是在219行的initWebApplicationContext()方法
initWebApplicationContext()方法主要用于创建或刷新WebApplicationContext实例,并对Servlet功能所使用的变量进行初始化。
从238行源码就可以看到,它获得ContextLoaderListener中初始化的rootContext,
在246行设置了父子关系的引用,也就是从这一点我们看到了spring和springMVC的父子关系!
并且,可以看到这只是一条单向的引用,spring中没有引用直接指向springMVC,也就是子类能找到父类,然而父类都不知道这个子类,父子容器之间内部对象调用关系更明了。
再通过构造函数和Servlet的contextAttribute属性查找ServletContext来进行webApplicationContext实例的初始化,最终。
这个方法内263行源码onRefresh(wac)方法是FrameworkServlet提供的模板方法,在子类,也就是我们的DispatcherServlet的onRefresh()方法中进行了重写。而在onRefresh()方法中调用了initStrategies()方法来完成初始化工作,初始化Spring MVC的9个组件。
1、Tomcat在启动时给每个Web应用创建一个全局的上下文环境,这个上下文就是ServletContext,其为后面的Spring容器提供环境。
2、Tomcat在启动过程中触发容器初始化事件,Spring的ContextLoaderListener会监听到这个事件,它的contextInitialized方法会被调用,在这个方法中,Spring会初始化全局的Spring根容器,这个就是Spring的IoC容器,IoC容器初始化完毕后,Spring将其存储到ServletContext中,便于以后来获取。
3、Tomcat在启动过程中还会扫描Servlet,一个Web应用中的Servlet可以有多个,以SpringMVC中的DispatcherServlet为例,这个Servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个Servlet请求。
4、Servlet会在容器启动时加载或延迟加载(根据启动级别设置数字)。延迟加载时,当第一个请求达到时,serlet容器发现对应Servlet还没有被实例化,就调用Servlet的init方法。
在spring MVC里
DispatcherServlet在初始化的时候会建立自己的容器,叫做SpringMVC 容器,用来持有Spring MVC相关的Bean。同时,Spring MVC还会通过ServletContext拿到Spring根容器,并将Spring根容器设为SpringMVC容器的父容器,请注意,Spring MVC容器可以访问父容器中的Bean,但是父容器不能访问子容器的Bean, 也就是说Spring根容器不能访问SpringMVC容器里的Bean。
说的通俗点就是,在Controller里可以访问Service对象,但是在Service里不可以访问Controller对象。
⑶ web容器有几种作用域如何防止sql注入
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表蚂贺高单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击.
防护
归纳一下,主要有以下几点:
1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和
双"-"进行转换等。
2.永远闷尺不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包拍肆装
6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。
⑷ 路由模式(hash、history)
history:不带#/ 利用html5 的 history.pushState API 来完成URL跳转,而无需重新加载页培迟面 好看 正常的URL http://user/id
hash:带#/ 通过锚点值来实现的路由跳转
区别:
2.hash 采用的是乱宏通过锚点值来实现的配陪李路由跳转,history 模式 采用html5 的 history.pushState API 来完成URL跳转
3.history模式 需要后端配合,因为刷新页面 会404
4.hash模式 支持IE 7、8,history模式 支持IE 10
⑸ 了解什么是hash路由和history路由
hash 路由:监听 url 中 hash 的变化,然后渲染不同的内容,这种路由不向服务器发送请求,不需要服务端的支持;
history 路由:监听 url 中的路径变化,需要客户端和服务端共同的支持;
我们一步步实现这两种路由,来深入理解下底层的实现原理。我们主要实现以下几个简单的功能:
1.监听路由的变化,当路由发生变化时,可以作出动作;
2.可以前进或者后退;
3.可以配置路由;
当页面中的 hash 发生变化时,会触发hashchange事件,因此我们可以监听这个事件,来判断路由是否发生了变化。
事件hashchange只会在 hash 发生变化时才能触发,而第一次进入到页面时并不会触发这个事件,因此我们还需要监听load事件。
在 history 路由中,我们一定会使用window.history中的方法,常见的操作有:
back():后退到上一个答档氏路由;
forward():前进到下一个路由,如果有的话;
go(number):进入到任意一个路由,正数为前进,负数为后退;
pushState(obj, title, url):前进到指定的 URL,不刷新页面;
replaceState(obj, title, url):用 url 替换当前的路由,不刷新页面;
调用这几种方式时,蠢岁都会只是修改了当前页面的 URL,页面的内容没有任何的变化。但前 3 个方法只是路由历史记录的前进或者后退,无法跳转到指定的 URL;而pushState和replaceState可以跳转到指定的 URL。如果有面试官问起这个问题“如何仅修改页面的 URL,而不发送请求”,那么答案就是这 5 种方法。
如果服务端没有新更新的 url 时,一刷新浏览器就会报错,因为刷新浏览器后,是真实清散地向服务器发送了一个 http 的网页请求。因此若要使用 history 路由,需要服务端的支持。
当我们用 history 的路由时,必然要能监听到路由的变化才行。全局有个 popstate 事件,别看这个事件名称中有个 state 关键词,但 pushState 和 replaceState 被调用时,是不会触发触发 popstate 事件的,只有上面列举的前 3 个方法会触发
针对这种情况,我们可以使用 window.dispatchEvent 添加事件:
然后就可以添加对这两个方法的监听了:
⑹ vue路由(一、二级路由)
是前台为了者吵实现单页面应用然后设置路径,根据不同的路径显示不同页面。但是这些路径在服务器上不是真是存在的
hash路由 默认的是hash路由
history路由
通过onhashchange()来检测路由的变化,根据不同的hash来显示不同元素。获取当前的hash值location.hash
通过onpopstate来检测history堆栈路径的变化,堆栈的路径是通过history.pushState(null, '',"?page=2")添加进去的
由hash路由设置成history路由,给路由添加配置项 mode="history"
1、设置相应组件
2、在router->index.js文件中添加配置
首先引入组件,然后配置规则 {path:设置路径,name:名,component:组件}
3、在需要现在组件的地方给页面添加<router-view></router-view>
4、设置导航路径
使用vue提供 <router-link to="路径"></router-link> 默认的解析成a标签
5、设置默认路由
6、设置导航样式
1、需要定义组件
2、确晌庆定好在那个组件配置二级路由,就去那个组件的配置规则中添加children关键字,按照一级路由的配置方法配置规则
3、在需要配置二级路由的组件中添加router-view
4、设置导航 <router-link to="/ / ">
5、设置导航链接的样式
我们可以定义一个一级路由,里面可以包裹底部footer组件,让他宴嫌握为二级路由,这时点击底部的二级路由时,就会切换不同的页面,而不需要底部组件显示的时候,那我们在配置一个一级路由就好了!!!
⑺ 什么叫web容器以及作用
tomcat 是SERVLET的容器。
web 容器就是实现了JAVA的那些接口:javax.servlet。
而且JSP也是SERVLET的
web 容器启动后一直运行,监听所有提交到他所监控的那个端口的请求,并对此做出反映。
个人理解, 之前有看过人家别人写的web容器的例子, 不过忘记了,如果你写深入理解, 自己搜索把。
⑻ web容器中有哪些重要的作用域,并说出自己的理解
web容器的四大作用域:pageContext, request, session、application四个作用域中
1、如果把变量放到pageContext里,就说明它的作用域是page,它的有效范围只在当前jsp页面里。
从把变量放到pageContext开始,到jsp页面结束,你都可以使用这个变量。
2、如果把变量放到request里,就说明它的作用域是request,它的有效范围是当前请求周期。所谓请求周期,就是指从http请求发起,到服务器处理结束,返回响应的整个过程。在这个过
程中可能使用forward的方式跳转帆铅逗了多个jsp页面,在这些页面里你都可以使用这个变量。
3、如果把变量放到session里,就说明它的作用域是session,它的有效范围是当前会话。所谓当前会话,就是指从用户打开浏览器激山开始,到用户关闭浏览器这中间的过程。这个过程可能包含多个请求响应。也就是说,只要用户不关浏览器,服务器就有办法知道这些请求是一个人发起的,整个过程被称为一个会话(session),而放到会话中的变量,
4、如果把变量放到application里,就说明它的作用域是application,它的有效范围是整个应用。整个应用是指从应用启动,到应用结束。我们没有说“从服务器启动,到服务器关闭”是因为一个服务器可能部署多个应用,当然你关闭了服务器,就会把上面所有的应用都关闭了。application作用域里的变量,它们的存活时间是最长的,如果不进行手工删除,它们就一直可以使用。与上述三个不同的是,application里的变量可以被所有用户共用。如果用户甲的操作修改了application中的变量,用户乙访问时得态卖到的是修改后的值。这在其他scope中都是不会发生的,page,
request, session都是完全隔离的,无论如何修改都不会影响其他
⑼ vue路由hash和history
SPA ,即 单页面应用 (Single Page Application)。就是只有一张 web页面的应用。单页应用程序 (SPA) 是加载单个html页面并在 用户与应用程序交互时 动态更新该页面的web应用程序。浏览器一开始会加载必需的html、css和 js ,所有的操作都在这张页面上完成,都由js来控制
对于现代开发的项目来说,稍微复杂一点的SPA,都需要用到 路由 。而 vue-roter 正是 vue 的路由标配,且 vue-router 有 两种模式 : hash 和 history 。
hash 模式是一种把前端路由的路径用井号 # 拼接在真实 url 后面的模式。当井号 # 后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 onhashchange 事件。
下面用一个网址来演示以上属性:
history API 是 H5 提供的新特性,允许开发者 直接更改前端路由 ,即更新浏览器 URL 地址而 不重新发起请求 。
hash 与 history 在浏览器下刷新时的区别:
正常页面浏览
改造H5 history模式
HTML5新增的API:
主要有以下特点:
对于 history 来说,确实解决了不少 hash 存在的问题,但是也带来了新的问题:
在实际的项目中,如何对这两者进行选择:
⑽ router(History,hash)前端路由机制
前端路由机制
前端路由,顾名思义就是一个前端不同页面的状态管理器,可以不向后台发送请求而直接通过前端技术实现多个页面的效果。
前端路由机制原理及两种实现方式
一、History
History 接口允许操作浏览器的曾经在标签页或者框架里访问的会话历史记录。
用户访问网页的历史记录通常会被保存在一个类似于栈对象中,即history对象:
history 对象包含用户(在浏览器窗口)访问过的url
history对象是window对象的一部分,可以通过window.history属性进行访问。
基本的API用法如back、forward、go不做多解释,可以参考MDN
重点解释html5新增的API:
1、history.pushState() //在history对象中添加一条新的浏览记录
2、History.replaceState() // 是替换history中的当前记录
3、history.state //是一个属性,可以得到当前页的state信息。
4、window.onpopstate //是一个事件,在点击浏览器后退按钮或js调用forward()、back()、go()时触发。
(和它相似的一个方法叫做onhashchange,onhashchange是老API, 浏览器支持度高, 本来是用来监
听hash变化的, 但可以被利用来做客户端前进和后退事件的监听,onpopstate是专门用来监听浏览器
前进后退的, 不仅可以支持hash, 非hash的同源url也支持。)
history.pushState与History.replaceState的区别
history.pushState和History.replaceState都接收三个参数:即(data[,title][,url])
状态对象(state Object):一个object,与pushState方法创建的新历史记录条目关联。
标题:一般传null
地址(url):新的历史记录条目的地址。
pushState和replaceState都会操作浏览器的历史记录,并且不会引起页面的刷新。
不同之处在与:一个新增,一个替换。
History 模式是 HTML5 新推出的功能,比之 Hash URL 更加美观
一、hash
我们经常看到在url中出现#符号,这个在路由中出现的#,叫做hash,很多大型框架的路由系统都是由hash实现的。
上面提到一个方法onhashchange事件,用来监听hash变化,也可以被利用来做客户端前进和后退事件的监听。