关于前后端分离:前后端未分离项目禁用ES6方案

背景近半年,已产生几起FM我的项目(FreeMarker我的项目)在IE浏览器或者360浏览器兼容模式环境下运行出错的线上问题,导致业务流程无奈执行上来。尽管始终在强调开发同学在做FM我的项目的需要时不要应用ES6,然而口头上的团队约定约束性力度无限,加上开发同学早已习惯性应用ES6,使之问题层出不穷,另外,还有些Web Apis和款式在IE上存在兼容性问题(比方:Element.scrollIntoView()、Element.scrollTo()),这些API和款式的应用也须要强制禁用,因而亟需用工具在编程阶段束缚。 因应用ES6或者应用兼容性较差的Web Apis导致的缺点: 因应用ES6或者应用兼容性较差的Web Apis导致的线上问题(都是三级事件): 另外,因jira单备注不够清晰,款式兼容性导致的问题未作统计。 计划上面计划只针对JavaScript脚本应用ES6+语法个性的解决,对于兼容性较差的Web Apis以及款式的解决另作计划。 Babel转译在webpack中引入babel将ES6语法转译成ES5,然而在构建之前须要将源文件做如下革新: var managePage = {};function debounc() {}革新后: window.managePage = {}window.debounc = function debounc() {} 为什么不设置libraryTarget: 'window'以全局变量输入? 因为libraryTarget: 'window'的打包形式只能将export导出的对象以全局对象的形式输入,但在将源代码进行如下革新后,线上不会有问题,在本地启动我的项目会报“xxx is not defined”,因为export包裹后的变量会变成了局部变量。 export var managePage = {};export function debounc() {}计划的长处: 任何JavaScript高级语法个性都能很好的反对;能够对代码做压缩、混同解决,减小文件大小,进步动态文件加载性能,进步源代码安全性;计划的毛病: 在构建之前须要对源文件进行革新,工作量比拟大,容易出错;须要引入构建工具,增加构建配置,批改Jenkinsfile CI脚本;ESlint正告ESlint是一款插件化的javascript代码检测工具,咱们能够利用其在FM我的项目脚本中是否应用了ES6+语法,如果脚本中有应用,立刻报错解决,并提醒哪些关键字的应用属于ES6语法。另外,为避免开发同学强推应用了ES6+语法的代码,在git hooks的pre-commit钩子中执行eslint命令校验,若通过,则代码胜利commit;若不通过,控制台会打印谬误日志。 留神:请开发同学在commit时不要增加--no-verify参数,否则会跳过校验具体落地流程: (1)在VScode编辑器中装置ESlint拓展插件,并启用 (2)在我的项目根目录下手动或者执行npx eslint --init创立.eslintrc.json配置文件,并增加如下配置项: { "root": true, "env": { "browser": true, "jquery": true }, "parserOptions": { "ecmaVersion": 5, "sourceType": "script" }, "rules": { }}(3)因为管理中心不须要反对IE,因而对于此端的脚本不须要ESlint检视,咱们在根目录下创立.eslintignore配置文件,向其中增加须要跳过检视的文件门路,比方src/main/webapp/static/js/adjustPage.js不须要检视: ...

August 12, 2021 · 1 min · jiezi

全栈式后端开发团队问题分析及建议

序作为一个大部分工作经历都在7-15人编制的技术团队的公司,深刻体会到合理的成员编制对团队开展高效工作的重要性,对团队每一位成员的成长的重要性,对公司的成本控制的重要性。 本文内容是以全栈式后端开发团队转型前后端分离开发团队为主题,从实际问题、工作流程、成员编制、成本控制等为出发点,做一个总结分析,抛砖引玉一起讨论学习,也希望可以帮助更多的朋友解决问题。 一、开发团队角色 小组型技术团队中,不论是全栈式后端开发团队还是前后端分离开发团队,开发角色基本都包含 后端开发、APP开发、web前端。 1. 全栈式后端开发团队各岗位职责web前端,主要负责编写静态的HTML,把CSS做好及部分特效JS后端开发,除了负责CRUD的技术开发,还要将HTML套入jsp、asp等模板引擎,需要编写JS代码做数据渲染以及大部分表单校验,甚至还需要些HTML,调CSS(如后台管理系统,一般前端是不管的),必要还是得写下接口文档给APP开发APP开发,略2. 前后端分离开发团队各岗位职责web前端,主要负责包含前台系统、后台系统所有的静态的HTML,JS数据渲染、表单校验后端开发,只需要负责CRUD的技术开发,编写接口文档给web前端开发、APP开发APP开发,略二、全栈式后端开发团队常见问题1. web前端工作闲,没技术含量一个月22工作日,web前端开发平均每个月最多只有10工作日饱和工作,剩下时间都在吹水、玩手机,以及考虑跳槽(因为嫌的慌,要么没事做,做的事基本没技术含量,想找个更有发展空间的环境)2. 后端开发套页面,CSS无法统一化管理在套页面时,经常出现渲染出数据后,页面效果不协调,需要优化样式,有些人嫌麻烦,觉得自己能改,就写行内样式,前端css没有统一化管理3. 后端开发套页面,JS无法统一化管理在做表单校验时,经常出现同样的代码多次复制粘贴,几十个页面都有90%类似的代码。(有心的,一般是会抽公共js引用,但实际上还是嫌麻烦,复制粘贴来的快)4. 后端开发并不擅于写页面,开发效率低后端开发在写页面时,经常会出现因为一个JS效果,需要花几个小时甚至一天的时间完成,并且部分效果体验比较差,将就将就即可5. web前端在本地调试带数据渲染的页面比较困难有些问题需要根据后端返回的数据渲染后,才会出现的问题,web前端需要调试,一般都是在后端开发座位上改,后端只能在一旁看着,浪费开发力三、两种团队工作流程1. 全栈式后端开发团队工作流程 2. 前后端分离开发团队工作流程 3. 分析从图中可以明显看出,前后端分离工作流程相比全栈式后端开发工作流程中,web前端与后端开发增加了接口对接的沟通成本,但总体来说,节省了后端开发的工作职责,把这段时间调整到接口文档的编写,可以推动技术文档的完整性,并能加强团队的管理。 四、两种团队开发人员编制对比1、 全栈式后端开发团队组织架构 2、 全栈式后端开发团队组织架构 3、对团队每一位成员要求变化后端开发,前后端分离团队模式提高了web前端和后端开发的沟通成本,但实际场景跟APP开发与后端开发对接是类似的,所以区别不大web前端,除了基本的HTML、CSS,还需要会React、Vue.js等JavaScript框架,技术要求更高,但目前该类技术已经是web前端面试时要求的必须技能技术组长,作为管理者,虽然团队角色并没有多少变化,但由于web前端也会遇到问题,作为技术组长,肯定要能提供一些有用的建议,所以也要加强一些前端知识的学习了解五、总结回到现实,大部分团队尽管看到了这些问题,但一直不愿意转型,主要也还是历史原因,那是否历史原因,所以我们就不做改变了呢? 管理团队组织架构、工作模式跟管理代码系统架构也是一样的道理。系统架构全新升级,也从来都不是一刀切,毕竟风险太大了。同样也是一步一步来,先从小的系统开始试水,然后再把主项目边缘的一些模块完成切割,最后实现完全转型。 六、交流学习有兴趣的朋友可以私信作者,大家一起交流学习更多的互联网技术。 My Blogblog.guijianpan.com 技术交流

November 5, 2019 · 1 min · jiezi

微人事-star-数超-10k如何打造一个-star-数超-10k-的开源项目

看了下,微人事(https://github.com/lenve/vhr)... star 数超 10k 啦,松哥第一个 star 数过万的开源项目就这样诞生了。 两年前差不多就是现在这个时候,松哥所在的公司业绩下滑严重,关门倒闭已成定局,很多同事在谋划的新的出路,松哥则被公司留下来善后,在一段并不太忙碌的日子里,做了两个 Spring Boot + Vue 的前后端分离开源项目,以期能给自己来年找工作增加一点筹码,没想到这两个项目后来受到很多关注,也帮助了很多人。有不少小伙伴在公司使用微人事项目做脚手架开发项目,也有国内 top20 的高校研究生借鉴微人事做毕设,我自己也因此收到一些大厂的橄榄枝,可以说还是收获满满。 关于这个项目诞生的故事,松哥之前写过一篇文章,感兴趣的小伙伴可以看看: 公司倒闭 1 年了,而我当年的项目上了 GitHub 热榜今天,我想和小伙伴们聊聊如何从零开始打造一个 star 数过万的开源项目。松哥把这些经验总结为三点: 文档详细项目有料适当宣传这些经验不是什么惊世骇俗的大道理,都很普通,关键在于执行。 1. 文档详细其实在做微人事和 V 部落之前,松哥在 GitHub 上已经做过多个开源项目了,比较有意思的一个是一个 Android 上的自定义控件,我做了一个歌词展示的控件,这个控件引入到自己的项目中以后,可以根据当前歌曲的播放进度动态滚动歌词,效果如如下: 还有一个比较好玩的就是 Android 上自动抢红包的 App。不过这些开源工具和项目最终都石沉大海了。 究其原因,我觉得是自己对待这些项目不够认真,项目开源之后基本上都没有再继续维护了,一个项目提交次数一般都是个位数,项目做完之后,写一篇博客介绍下就算完事了。一个自己都不怎么重视的项目,其实很难引起别人的重视。 所以在 V 部落和微人事中,我就吸取教训,尽量把项目的文档写的详细一些,让不懂前后端分离开发的小伙伴看到我写的开发文档后,就能够快速理清项目的思路。就这样,我每写一个功能点,就写一篇技术文档,微人事项目前前后后一共写了 30 多篇文档: 同时我考虑到很多小伙伴第一次接触到这个项目,一个庞然大物不好处理,因此我在每一次项目提交之前,都会对项目打一个 tag,这样大家通过 git clone 命令获取到项目之后,就可以通过 tag 非常方便的定位到项目的任意时刻,例如只想看登录设计的,可以根据文档介绍回到 v20180107 这个版本: 小伙伴也可以点击 GitHub 上的 release 下载不同时期的项目。我一开始担心有的小伙伴不熟悉 Git 上的 tag 操作,还针对此写了个教程,就是上面文档的第 17 篇。 ...

October 15, 2019 · 1 min · jiezi

喜大普奔两个开源的-Spring-Boot-Vue-前后端分离项目可以在线体验了

折腾了一周的域名备案昨天终于搞定了。 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了。 1. 也曾经上过线其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了,以帮助小伙伴们更好的查看效果。但是那个是一台国外服务器,之所以购买国外服务器,主要是嫌国内备案麻烦,当然也有其他大家都懂的原因。 国外服务器有方便的地方,同时也有很多不便,例如网络不稳,随时有失联的风险。所以我在 2018 年年初,虽然把这两个项目都部署在服务器上,但是很多小伙伴的访问体验都不好,主要还是网络的问题。后来一段时间,经过几轮围剿与反围剿,这台服务器就彻底和松哥失联了。 失联之后,因为工作比较忙,我也就懒得去折腾了,所以导致微人事和 V 部落大家在很长一段时间内无法在线查看效果。 2. 重新上线最近因为有一些其他的计划,于是购买了阿里云服务,完事之后就是备案,所有东西都搞定之后,想着先把微人事和 V 部落部署起来,方便大家查看效果。 说干就干,我首先规划了两个二级域名: vblog.itboyhub.comvhr.itboyhub.com这两个二级域名分别用来部署 V 部落和微人事。 大家可以通过这两个地址查看效果: 微人事 V 部落 为了确保每位小伙伴都能看到完整的演示效果,防止有的小伙伴不慎把所有数据清空了,导致其他小伙伴啥都看不到,我只开通了演示账户的查询和部分字段的更新权限,因此大家在查看演示效果时,可能会有一些涉及到增删改的操作会执行失败,请勿见怪,将项目部署到本地运行之后,就可以查看完整效果了。 3. 技能树既然都写到这儿了,就和大家聊一聊这两个部署是怎么实现的。 3.1 部署方案选择大家知道前后端分离部署的时候,我们有两种不同的方案: 一种就是将前端项目打包编译之后,放到后端项目中(例如 Spring Boot 项目的 src/main/resources/static 目录下)另外一种则是将前端打包之后的静态资源用 Nginx 来部署,后端单独部署只需要单纯的提供接口即可。一般在公司项目中,我们更多的是采用后者。不过松哥这里部署为了省事,我采用了第一种方案。(以后抽空我会和大家聊聊第二种部署方案) 3.2 域名映射域名映射这块简单,登录阿里云后台,添加两个 A 记录即可。 3.3 启动 Spring Boot将微人事和 V 部落分别打包上传到服务器,这个过程应该就不用我多说了吧,然后分别启动这两个项目,两个项目的默认端口分别是 8081 和 8082,命令如下: nohup java -jar vblog.jar > vblog.log &nohup java -jar vhr.jar > vhr.log &将两个项目的运行日志分别写入到 vblog.log 和 vhr.log 文件中。 ...

September 20, 2019 · 2 min · jiezi

对前后端通信的基本了解如何通信跨域

1、什么是浏览器的同源政策限制?端口,域名,协议 ,只要一个不一样就跨域2、前后端如何通信?常见通信的几种方式 Ajax : 短连接Websocket : 长连接,双向的。CORS fetch()Form表单(最原始的)Ajax是如何通信的 基本通信原理:浏览器可以发出HTTP请求与接收HTTP响应,实现在页面不刷新的情况下和服务端进行数据交互。实现过程:1) 创建XMLHttpRequest对象(异步调用对象)var xhr = new XMLHttpRequest();2) 创建新的Http请求(方法、URL、是否异步)xhr.open(‘get’,’example.php’,false);3) 设置响应HTTP请求状态变化的函数。onreadystatechange事件中readyState属性等于4。响应的HTTP状态为status==200(OK)或者304(Not Modified)。4) 发送http请求xhr.send(data);5) 获取异步调用返回的数据优点:提高用户体验,较少网络数据的传输量Fome表单是如何通信 基本通信原理:通过form表单以post/get方式提交数据。实现过程:当你点击submit按钮时,浏览器会默认把你在input里面输入的数据,以post或get的方式提交到form表单中的action这个地址。相当于你提交表单时,就会向服务器发送一个请求,然后服务器会接受并处理提交过来的form表单,最后返回一个新的网页。缺点:1、单项提交,页面会发生跳转或刷新,导致用户体验不好3、浪费宽带。改用ajax。了解Websocket 建立在TCP协议之上,与HTTP协议有着良好的兼容性3、跨域通信有几种?引JSONPHash(url#后面的,改变页面不刷新)postMessage(H5中新增的)WebSocketCORS介绍以下最常用的JSONP 1.JSONP原理利用<script元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。2.JSONP和AJAX对比JSONP和AJAX相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。但AJAX属于同源策略,JSONP属于非同源策略(跨域请求)3.JSONP优缺点JSONP优点是兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性4、GET与post区别?POST与GET的区别1、GET请求会被浏览器主动缓存,而POST不会2、GET请求参数会被完整保留在浏览器历史记录里,而POST中参数不会被保留3、GET请求在URL中传送的参数是有长度限制的,而POST没有限制4、GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息本质上都建立在TCP链接上

July 3, 2019 · 1 min · jiezi

前后端分离时代Java-程序员的变与不变

事情的起因是这样的,有个星球的小伙伴向邀请松哥在知乎上回答一个问题,原题是: <!--more--> 前后端分离的时代,Java后台程序员的技术建议?松哥认真看了下这个问题,感觉对于初次接触前后端分离的小伙伴来说,可能都会存在这样的疑问,于是决定通过这篇文章和大家聊一聊这个话题。 我这里还是尽量从一个 Java 程序员的角度来说说这个问题,这样大家可能更好理解。 从一个题外话开始很多小伙伴可能知道,松哥本科是经管学院的,亚当•斯密的《国富论》多多少少还是了解一点。书中提到人类社会的本质就是分工协作,亚当•斯密认为人类之间的专业分工可以极大的提高生产力、创造财富,专业分工也是工业革命的基础。人类社会的发展过程就是一个专业分工不断细化、不断深化的过程,从最早的农牧分家到手工业农业分家再到商人的出现,其实都是专业分工不断细化深化的体现。 我们的开发世界也是一个小宇宙,专业分工不断细化也是一个趋势,从这个角度来说,前后端分离,都是值得积极拥抱的。 前后端分离的开发方式在最近几年突然火起来,松哥认为有两方面的原因: 前端的发展。前端经过近几年的发展,已经不再是我们传统所说的HTML+画图了,各种概念层出不穷,webpack、RxJs、Node、Redux、ssr、NuxtJs等,前端已经可以胜任很多事情,也能够完成更加丰富的用户交互。移动互联网的发展。前两年移动互联网的火爆,很多公司的产品都要在多个平台上线,Android、iOS、小程序、公众号、PC 等等各个平台都要展示,不可能针对不同的设备开发一套后端,应该是多个前端共用同一个后端,这是就不能采用传统的前后端不分的方式来开发后端程序了。正是这样的业务需求,促进了前后端分离的发展。变与不变程序员之间的分工协作方式有所变化,开发方式当然也会随着一起变化。但是这种变化其实是非常细微的,很容易上手的。 变工作内容变老实说,前后端分离之后,对 Java 程序员的要求变低了,以前大家大家出去面试 Java 工程师,如果是前后端不分的话,前端基本上也是必问的,常见的问题就是各种元素选择器,这也很好理解,因为在前后端不分的开发方式中,后端工程师多多少少是要写一点前端代码的,你很难完完全全的只写 Java 代码。但是在这种情况下,你要写的前端代码其实都是很简单的,不会是特别难的。 前后端分离之后,Java 程序员只需要专注于后台业务逻辑,对外接收前台传来的参数,根据参数给出不同的响应即可,基本上不需要写前端代码。因为这个时候的前端不同于前后端不分时候的前端,前后端分离之后,前端还是有一定的难度,较为常见的是 SPA 应用,涉及到 NodeJS、Webpack 等,此时如果还要让后端工程师写前端代码,对后端工程师的技术要求就会比较高。 不过话说回来,前后端分离后,如果你还能即写前端又写后端,那可以让老板加薪了。 接口变前后端不分的时候,很少会涉及到接口设计,以 SpringMVC 为例,你可能返回的始终是 ModelAndView 一类的东西,前后端分离之后,我们基本上不需要返回页面了,后端主要是返回 JSON 数据,所以关键是设计好各种接口。 一个比较好的实践方案是设计满足 RESTful 规范的接口,语义明确,简洁明了,看到 URL 就知道你想干嘛! 开发流程变化前后端分离之后,前端不可能等后端开发好接口之后再去开发,如果这样,原本两个月做完的项目可能就得 4 个月才能完成。 一般在开发之前,整个项目组需要先设计好一个接口文档,一般可以采用 Swagger 来做接口文档(SpringBoot整合Swagger2,再也不用维护接口文档了!),文档中约定了接口的详细信息,前后端分别按照既定的接口规范去开发,在尚未开发完成时,可以借助 Mock 来进行测试。 前端也是使用模拟数据进行测试,开发完成之后,前后端接口联调,完成测试。 不变其实除了前后端交互方式发生变化之外,其他的地方都是不变的。 前后端分离,一般来说是不会影响后端技术架构的,你使用了 SSM 或者 Spring Boot 或者 Dubbo 或者微服务,无论什么,这些技术架构既可以支撑你前后端不分的项目,也可以支撑你前后端分离的项目。 因此我说后端技术架构不受前后端分离影响。 另一方面,技术的根本不变,例如你做 Java 开发,该会的 SSM/SpringBoot/Redis/Nginx/Dubbo/SpringCloud/MySQL/MyCat/ELK/...等等,都还得会。 所以,还是去老老实实撸代码吧! 结语如果仅仅从一个 Java 程序员的角度来说,前后端分离开发这种方式,其实是解放了 Java 程序员,可以让我们专注于后端的工作,不用再去写前端代码,术业有专攻,可以写出更优质的后端代码。不过话说回来,如果想保持一个良好的竞争力,还是有必要去了解一下目前流行的前端开发方式。 ...

July 1, 2019 · 1 min · jiezi

前后端分离ssm配置swagger接口文档

之前配置过springboot,相比ssm要简单很多,现在记录一下ssm的配置 在pom.xml中加入依赖<!--swagger本身不支持spring mvc的,springfox把swagger包装了一下,让他可以支持springmvc--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version> </dependency>添加配置类SwaggerConfig.java@WebAppConfiguration@EnableSwagger2@EnableWebMvc@ComponentScan(basePackages = "com.maxcore.controller")public class SwaggerConfig { @Bean public Docket customDocket() { // return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { Contact contact = new Contact("娜", "https://www.baidu.me", "baidu_666@icloud.com"); return new ApiInfo("仿简书前台API接口",//大标题 title "Swagger测试demo",//小标题 "0.0.1",//版本 "www.baidu.com",//termsOfServiceUrl contact,//作者 "Blog",//链接显示文字 "https://www.baidu.me"//网站链接 ); }}在dispatcher-servlet.xml(springmvc的配置文件)中加入如下配置 <bean class="com.maxcore.config.SwaggerConfig" /> <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" /> <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/" />要在controller层添加注解 最后启动项目,访问swagger接口文档的路径一定要对,不然一直报404,你以为你没配置对,其实是你路径不对,笔者在这里表示有很痛的领悟笔者的本地的访问路径是 http://localhost/jianShuSSM_w... 一般都是http://ip地址:端口(默认80,不显示)/项目名/swagger-ui.html ...

June 22, 2019 · 1 min · jiezi

前后端分离ssm配置跨域

前后端分离开发需要跨域,之前只会pringboot跨域,只需要一个配置类即可,下面记录一下ssm的配置 三个文件需要添加配置 SimpleCORSFilter.java实现Filterpublic class SimpleCORSFilter implements Filter { private boolean isCross = false; @Override public void destroy() { isCross = false; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (isCross) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpServletResponse httpServletResponse = (HttpServletResponse) response; System.out.println("拦截请求: " + httpServletRequest.getServletPath()); httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); httpServletResponse.setHeader("Access-Control-Max-Age", "0"); httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token"); httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true"); httpServletResponse.setHeader("XDomainRequestAllowed", "1"); } chain.doFilter(request, response); } @Override public void init(FilterConfig filterConfig) throws ServletException { String isCrossStr = filterConfig.getInitParameter("IsCross"); isCross = isCrossStr.equals("true") ? true : false; System.out.println(isCrossStr); }dispatcher-servlet.xml(springMVC的配置文件)<!-- 接口跨域配置--> <mvc:cors> <mvc:mapping path="/**" allowed-origins="*" allowed-methods="POST, GET, OPTIONS, DELETE, PUT" allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With" allow-credentials="true" /> </mvc:cors> ## web.xml ...

June 22, 2019 · 1 min · jiezi

laravel前后端分离获取微信授权结合laravelwechat

1、开始之前,请一定仔细阅读微信开发者文档文档中,总共写了几个步骤: 1、通过appId和需要跳转的路由去请求授权2、授权之后跳转路由中返回的code 注:前端只需要知道这两个步骤3、根据code获取access_token4、根据access_token获取用户信息(snsapi_userinfo授权)2、前端发起授权请求。这一步需要前端拼凑路由,并且将页面跳转到拼凑路由,路由规则如:https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的公众appId号&redirect_uri=你的回调路由&response_type=code&scope=你选择的方式&state=STATE#wechat_redirect注 授权方式可选择为snsapi_userinfo或者snsapi_base,差别请看文档跳转之后授权页面如下(开发者工具效果) 3、点击同意之后,会根据你之前拼凑的回调路由返回code,如下:http://test.***.com/index?code=021Azdiu12zdXd05kkju1ZYkiu1AzdiR&state=1 4、将路由中的code直接传递给后端,让后端做获取用户信息的系列的逻辑处理。注:如下是laravel中间件中处理方式,session只用于这次请求,也可以将用户的微信信息放在request中到controller进行逻辑处理,看个人喜好 public function handle($request, Closure $next, $scopes = null) { $wechatCacheKey = 'wechat.oauth_user.default'; if (config("qa.mock_user") == 1){ $user = new SocialiteUser(config('wechat.mock_user')); } else { $code = $request->get("code", ""); if ($code === ""){ $appId = $this->config["app_id"]; return Response::toJson(["aid" => $appId], "请重新获取授权CODE!",10006); } // 开始拉取用户信息 $app = Factory::officialAccount($this->config); $user = $app->oauth->user(); } session([$wechatCacheKey => $user]); } return $next($request); }注:这个例子只是写了授权的逻辑,token相关验证我已经做了剔除 坑点:1、vue的路由会将code拼接在url和#之间,如www.****.com/?code=XXXXX/#/index,这个code需要单独处理

June 14, 2019 · 1 min · jiezi

JeecgBoot-201-版本发布企业级快速开发平台

Jeecg-Boot 2.0.1 版本发布,前后端分离快速开发平台Jeecg-Boot项目简介Jeecg-boot 是一款基于代码生成器的快速开发平台!采用前后端分离技术:SpringBoot,Mybatis,Shiro,JWT,Vue & AntDesign。提供强大的代码生成器, 前端页面和后台代码一键生成,不需要写任何代码,保持jeecg一贯的强大,绝对是全栈开发者福音!!JeecgBoot的宗旨是降低前后端分离的开发成本,提高UI能力的同时提高开发效率,追求更高的能力,No代码概念,一系列智能化在线开发。源码下载源码下载:https://github.com/zhangdaisc...在线文档:http://jeecg-boot.mydoc.io在线演示:http://boot.jeecg.org入门视频:http://t.cn/E9mFjet常见问题:http://t.cn/EITSuH8升级日志本版本主要录制全新教学视频和修复2.0.0版本的一系列bug,提供稳定版本供大家使用录制新版入门教程视频用户列表无编辑按钮,编辑提示无权限非admin用户,角色授权、部门、用户等操作提示无权限提示 Parameter useId not found (SysAnnouncementMapper的userid找不到)Type definition error: [simple type, class org.jeecg.modules.system.model.SysUserDepartsVO]无构造器问题oracle下部门数据列表是空问题系统公告提示资源找不到问题类别统计报表菜单删除,此功能是测试未完全实现部门管理怎么添加子部门: 选中部门,鼠标右键,添加子部门或删除子部门老菜单访问404,因为V2.0版本,菜单增加了一个类型“是否路由”,请设置“是”项目打可执行jar包,缺少maven plugin插件的问题添加新菜单访问404问题解决,改造程序,默认设置菜单路由类型默认值“是”系统展示

June 7, 2019 · 1 min · jiezi

JeecgBoot-20-入门视频教程

视频大纲 视频地址: https://pan.baidu.com/s/1Il0T... 提取码:hok5 源码下载: https://github.com/zhangdaisc... (喜欢请Star)

June 6, 2019 · 1 min · jiezi

jwt前后端整合方案

一、jwt是什么JWT全称, JSON Web Token,是一个以JSON为基准的标准规范。 举例:服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样 { "姓名": "brook", "角色": "前端攻城狮", "帅气指数": "5颗星"}以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。 我们先看看jwt的真实面目 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6ImFkbWluIiwidXNlcm5hbWUiOiJhZG1pbiIsInBvc2l0aW9uIjoiIiwicGhvbmUiOm51bGwsImVtYWlsIjpudWxsLCJyb2xlIjpbImFkbWluIl0sImF2YXRhciI6Imh0dHA6Ly9pbWcuZG9uZ3FpdWRpLmNvbS91cGxvYWRzL2F2YXRhci8yMDE1LzA3LzI1L1FNMzg3bmg3QXNfdGh1bWJfMTQzNzc5MDY3MjMxOC5qcGciLCJpbnRyb2R1Y3Rpb24iOiIiLCJjcmVhdGVfdGltZSI6IjIwMTctMTEtMDJUMTg6MTU6NDguMDAwWiIsInVwZGF0ZV90aW1lIjoiMjAxNy0xMS0yNlQwNjozMzoxNy4wMDBaIiwiaWF0IjoxNTM5MjQ0NjQ1fQ.cRg7ZAQ-1ZBiJUPDx6naQupUMK2BLHmIusMQZrnqVpG它是一个很长的字符串,中间用点(.)分隔成三个部分。三个部分依次为 Header(头部) Payload(负载) Signature(签名)即header.payload.sign。 Header 部分是一个 JSON 对象,描述 JWT 的元数据。 Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。 Signature 部分是对前两部分的签名,防止数据篡改。 关于这三部分的详解,可以具体参考阮一峰老师的文章:http://www.ruanyifeng.com/blo... 在使用jwt的时候建议放在 HTTP 请求的头信息Authorization字段里面,如下 Authorization: Bearer <token>二、jwt的好处前后端分离:使用JWT作为接口鉴权不需要前端代码发布到后端指定目录下,可以完全跨域,前端项目可以单独部署减轻服务端内存负担:比起使用session来保存cookie,JWT自身包含了所有信息,通过解密即可验证(当然啦,这个通过吧session存在redis来避免)安全性:防止CSRF攻击移动端:对于无法使用cookie的一些移动端,JWT能够正常使用部署:服务器不需要保存session数据,无状态,容易扩展PS:为什么不写为什么使用jwt呢,因为它其实还是存在不少缺点的,需要根据使用业务场景确定,不是所有的场景都适合使用jwt,甚至网上有些帖子都是在评论jwt比较鸡肋的。具体可以看分析https://juejin.im/entry/59748... 三、jwt怎么使用直接上图,流程如下 我们以Eggjs项目为例,使用koa-jwt这个库https://github.com/koajs/jwt 后端(以Eggjs项目为例)1、在config.default.js 中以中间件的方式使用koa-jwt config.middleware = ['compress', 'errorHandler','jwt']; // 加上配置 config.jwt = { match: '/api', secret: 'abiao', unless: ['/api/user/login'], };match指egg路由匹配到相应前缀,则会使用当前的中间件。可以使用正则表达式去匹配,推荐api前缀定为api。secret指jwt的加密密钥。unless指指定的路由不经过此中间件,一般为login接口PS:egg中使用插件有全局模式和中间件模式。全局模式应该使用egg的插件,中间件模式可以使用第三方koa的插件 ...

April 28, 2019 · 2 min · jiezi

Spring-Boot-Vue-前后端分离两种文件上传方式总结

在Vue.js 中,如果网络请求使用 axios ,并且使用了 ElementUI 库,那么一般来说,文件上传有两种不同的实现方案: 通过 Ajax 实现文件上传通过 ElementUI 里边的 Upload 组件实现文件上传两种方案,各有优缺点,我们分别来看。 准备工作首先我们需要一点点准备工作,就是在后端提供一个文件上传接口,这是一个普通的 Spring Boot 项目,如下: SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");@PostMapping("/import")public RespBean importData(MultipartFile file, HttpServletRequest req) throws IOException { String format = sdf.format(new Date()); String realPath = req.getServletContext().getRealPath("/upload") + format; File folder = new File(realPath); if (!folder.exists()) { folder.mkdirs(); } String oldName = file.getOriginalFilename(); String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf(".")); file.transferTo(new File(folder,newName)); String url = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/upload" + format + newName; System.out.println(url); return RespBean.ok("上传成功!");}这里的文件上传比较简单,上传的文件按照日期进行归类,使用 UUID 给文件重命名。 ...

April 28, 2019 · 2 min · jiezi

推荐一个在线接口Mock工具fastmock

fastmock可以让你在没有后端程序的情况下能真实地在线模拟ajax请求,你可以用fatmock实现项目初期纯前端的效果演示,也可以用fastmock实现开发中的数据模拟从而实现前后端分离。如下面的接口模拟一个用户列表https://www.fastmock.site/moc…模拟各种特殊类型的数据https://www.fastmock.site/moc…您可以直接在浏览器打开上面的链接或者用ajax请求查看返回的数据在使用fastmock之前,你的团队实现数据模拟可能是下面的方案中的一种或者多种本地手写数据模拟,在前端代码中产生一大堆的mock代码。利用mockjs或者canjs的can-fixture实现ajax拦截,本地配置必要的json规则。后端在Controller层造假数据返回给前端。上面的方式中,不管哪一种方式,都会要求开发人员写一些跟项目本无任何关联的代码,第一个和第二个方式还会需要前端项目在本地引入不必要的js文件。比如下面的mock数据// 产品配置 { url: ‘/pms/product/list’, on: true, type: ‘get’, resp: Mock.mock({ ‘body’: { ‘currentPage’: 1, ‘isMore’: 0, ‘pageSize’: 15, ‘resultList|10’: [ { ‘productNo’: ‘11111’, ‘productName|1’: [‘产品名称1’, ‘产品名称2’, ‘产品名称3’, ‘产品名称4’, ‘产品名称5’], ‘productType|1’: [‘1’, ‘2’, ‘3’, ‘4’, ‘5’], ‘status|1’: [‘1’, ‘2’], ‘gmtCreate’: ‘@DATETIME(“yyyy-MM-dd HH:mm:ss”)’, ‘gmtModified’: ‘@now(“yyyy-MM-dd HH:mm:ss”)’, ‘createUserCode’: ‘@name’ } ], ‘startIndex’: 0, ’totalNum’: 100, ’totalPage’: 1 }, ‘reCode’: ‘0000’, ‘reMsg’: ‘成功’, ‘success’: true }) }, // 产品配置-贷款材料配置 { url: ‘/pms/cfgLoanDoc/list’, on: true, resp: Mock.mock({ ‘body’: { ‘currentPage’: 1, ‘isMore’: 0, ‘pageSize’: 15, ‘resultList|10’: [ { ’loanDocCode|+1’: 1, ’loanDocName’: /[测试字体]{4,30}/ } ], ‘startIndex’: 0, ’totalNum’: 100, ’totalPage’: 1 }, ‘reCode’: ‘0000’, ‘reMsg’: ‘成功’, ‘success’: true }) }上面的代码为mockjs的事例代码,更多mockjs相关资料参考链接mockjs文档为此,我们将mock层独立出来,通过中间服务的形式在前端和后端服务之前建立一道围栏,使用fastmock,前端只需要修改自己的XHR请求地址,后端只需要在开发前和前端约定好接口文档即可。等到后端服务开发完成,前端再将XHR请求地址替换回来进行联调测试即可。tip:当然,你也可以通过npm script不同命令加载不同配置文件的形式切换你的XHR地址,这里不作详细介绍。还是不了解fastmock?让我们跟着教程一探究竟吧了解并开始使用fastmock ...

January 28, 2019 · 1 min · jiezi

DRF跨域后端解决之django-cors-headers

在使用django-rest-framework开发项目的时候我们总是避免不了跨域的问题,因为现在大多数的项目都是前后端分离,前后端项目部署在不同的web服务器上,因为我们是后端程序员,因此我要通过后端的程序实现跨域。当然如果前端框架是Vue的话,则可以代理服务实现跨域,我也就知道一点点,如果有兴趣,大家可以自行搜索哦。DRF后端实现跨域第三方扩展———djangocorsheaders,在介绍之前,我先介绍两个概念:同源策略、跨域同源策略同源策略/SOP(Same origin policy)是一种约定,是浏览器的一种安全机制。这里同源需要"协议+域名+端口"三者都相同,否则不能进行Ajax访问。跨域不同源之间的网站通信就是跨域。安装pip install django-cors-headers注册INSTALLED_APPS = ( ‘corsheaders’,)添加中间件MIDDLEWARE = [ ‘corsheaders.middleware.CorsMiddleware’, #最好添加至第一行]配置白名单#单个配置CORS_ORIGIN_WHITELIST =( ’ 域名’,)#正则配置:CORS_ORIGIN_REGEX_WHITELIST =(r’^(https?://)?(\w+.)?jim.com $’,)或者直接允许所有主机跨域CORS_ORIGIN_ALLOW_ALL = True 默认为False一般情况下,我们配置这些就足够,当然最为一个出名的扩展,肯定做的很完美,更多的配置,请访问:https://github.com/ottoyiu/dj…

January 25, 2019 · 1 min · jiezi

互联网产品项目管理经验分享

背景笔者目前经营着一个开发人员为主的团队。成员有产品经理、前端开发、后台开发、测试、UI设计师。在实际的项目开发中,一旦项目周期较长,上线时间非常难以把握。此外因为时间安排不合理,项目输出的软件产品质量也很难有所保证。经过几次有些失败的项目开发经历,总结了一些原因,发现主要是因为开发过程中成员沟通问题所导致。特别是在前后端分离的开发过程中,更容易出现因开发人员沟通协调不到位出现各种问题。痛定思痛。原先坚定认为小团队不需要进行项目管理的笔者,也不得不去思考一些有效的方案来破局。在最新的项目中,这一套方法论还是带来了不错的成效,今天在这里分享给大家。正文需求分析笔者最早在学习软件工程的时候,就听过一句话:一切(发布的)软件问题,归根结底都是需求问题。这个环节主要是产品经理负责。原先我们的流程是产品经理做需求分析,制作原型,然后组织全体研发成员(UI+前端+后端+测试)进行评审。这样的流程是存在不少问题的。一个会议人数如果超过 5 个人,就很难相互进行有效的交流,转而成为了一个公开发布的会议。而当下情况,一个有开发经验的产品经理可遇不可求。产品经理设计出的原型,往往因为其缺乏开发思维,会出现一些逻辑错误。另外,最典型会出现的问题是,很多产品经理的原型只考虑了最表层的页面流程,而被这背后的数据流转缺乏认识。针对以上问题,我们在这个所谓的“产品评审”环节前增加了一个“架构师评审”的环节。由一个资深的开发人员对产品原型先进行评审,这位开发人员需要时擅长后台开发的技术人员,辅助完善产品设计上的后台逻辑部分。在这个“架构师评审”环节完成之后,再组织全体研发人员进行公审,可以避免掉很多问题。总结:产品在向全体成员输出原型之前,需资深开发对原型进行一次评审,从源头避免一些需求问题。任务拆解对于一个周期较长的项目来说,如果在开发把所有的功能全部实现之后在再开始进行测试和需求验证,风险会很大。所以,在开始进行开发之前,我们需要先将一个完整的产品拆分成相对对立的模块,每个模块需要能够独立的进行测试(典型的就是能够时间完整的增删改查功能),最后再将各个模块组合起来进行完整测试。这项工作说起来简单,但是实际操作上并不容易。对于一个较为复杂的产品来说,各个模块的耦合度还是挺高的。所以在进行工作的安排时,完成顺序需要进行良好的规划。比如一个系统在进入测试(这里指的是有 QA 人员进行的测试)的时候,其最先需要完成的步骤。所以在规划上,我们需要把被依赖最多的模块安排在优先级最高的地方。说到任务拆解,不得不聊聊分布提交测试。在以前我们往往会在一个项目即将开发完成的时候,才提交到测试那里进行测试。这种方式存在两个问题:在开发阶段,测试往往并没有能够参与进入工作的机会,导致了时间浪费同一时间测试那里堆积了过多的工作量,对于项目的整体进度带来了不稳定性所以,做好任务拆解,一个不错的功能就是能够让测试较早的介入工作。项目经理通过规划好项目更新的计划,先完成一个相对完成较为独立的模块,集中开发完成此模块,然后进行测试提交。即可很好地完成将测试进度与开发进度交叉起来。按照这种方式进行拆解,当然仍旧难以测试到各个模块相互交叉关联的地方。所以最后在整个项目开发完成,进行完整的集成测试仍旧是必须的。任务跟进里程碑里程碑是在项目管理中比较经常强调的概念,这个概念放在项目开发中非常形象。相信很多人跟我一样,上学的时候老师布置的寒假作业、暑假作业经常只有到假期快结束的时候才会想起来写。在项目开发中也一样,大部分人对于时间节点是没有明确的概念的。所以将大目标分解成相应的小目标,能够有效的降低项目最终延期的风险。站例会最初听说站例会的时候,我是很不以为然的,总是觉得团队内部有什么问题,直接进行沟通就行了,应该不存在需要每天专门开会来解决的问题。而且现在有类似 Tower、Teambition 这样的协作产品,在团队的进度实时同步上能够提供很大的帮助。但是在实际的项目实践中,往往因为各种原因,很多同事不会或者不愿意进行相关的沟通。在Tower、Teambition 这种工具的使用过程中,也发现很多同事并不愿意及时去更新上面的任务状态,最终这类软件的任务安排流于形式,无法有效地跟踪任务进度状况。前期我们遇到这个问题的时候,只能通过询问每个开发的方式来获取最新的项目进度情况,当时长期以往发现这个方式非常讨嫌。大部分开发都是比较讨厌别人向他们问进度情况的。这个时候,站例会的优势就体现出来了。站例会的基本规则就是要求每个开发自述自己当前的项目情况,主要有以下几点:我当前在做什么我今天会完成什么我有什么需要支持的工作在会上如果成员提出需要何人支持,可以得到项目组相关成员的立即响应,对于成员的信息流转又很大的帮助。甘特图管理整体项目进度(以模块进度来进行管理)甘特图真的是一个好东西,可以很清晰的掌握项目的整体进度。但是我们在尝试使用的时候总是没有很好的办法让他落地。其中一个很重要的原因是一开始我们就把甘特图定的太细了。例如,我们开发模式是前后端分离开发,为此将每个前后端的任务全部拆分开进行展示。这样做的后果就是甘特图上的任务过多,无法很清晰的定位,进而无法很好地把握整体项目进度。经过我们的多次项目实践,发现一个较好的使用甘特图的方式就是:每个任务按独立的模块划分。无论是前端还是后台,我们将他们的模块放在一起进行管理。这样做的好处还有一点,就是能够刺激前后端共同合作把模块做好,而不是在遇到问题的时候,各种推脱甩锅。网上又很多甘特图软件,但是就灵活性和易用性来讲,我还是喜欢使用Excel里的甘特图模板,耐心体验一下就会发现非常好用。有机会笔者会出一篇小教程来讲讲如何使用Excel里的甘特图模板。后记项目管理的过程,必然将分担一大部分人的精力。笔者个人仍旧认为,如果资源足够,一个团队最好的优化效率的方法是:严格抓招聘环节,及时淘汰掉不合适的人。最后说说写这篇文章的感想吧。今天在听《罗辑思维》之前比较老的节目,里面讲到了“实验室经验”和“工厂经验”。前者指的是科学家们在研究所里面对新的技术、产品去研究,总结并发布自己的经验;后者指的是工厂在生产中总结出的各种难以复制的实践经验。作为一个工作了 7 年的程序员,深知很多知识是难以在书本以及博客上学习到的。很多时候我们在某一个博客上学习到了某个技术知识,但是当它应用到生产的时候,就会出现各种问题。正如这篇文章讲的项目管理知识,个人在刚开始带团队的时候,也看了不少相关的文章和资料,但是大多都过于理论化,难以应用到我们实际的工作当中。今天我写这篇文章,正是想要分享我在实践工作当中的“工厂经验”,这些经验可能不是最好的,但一定是经过实践考验的。希望能够帮到看到这篇文章的你。

January 17, 2019 · 1 min · jiezi

前后分离接口规范实践

找到一篇关于前后端分离非常好的文章,分享给大家:前后分离接口规范实践

December 10, 2018 · 1 min · jiezi

实现前后端分离的心得

实现前后端分离的心得对目前的web来说,前后端分离已经变得越来越流行了,越来越多的企业/网站都开始往这个方向靠拢。那么,为什么要选择前后端分离呢?前后端分离对实际开发有什么好处呢?为什么选择前后端分离在以前传统的网站开发中,前端一般扮演的只是切图的工作,只是简单地将UI设计师提供的原型图实现成静态的HTML页面,而具体的页面交互逻辑,比如与后台的数据交互工作等,可能都是由后台的开发人员来实现的,或者是前端是紧紧的耦合后台。比如,以前淘宝的Web基本上都是基于MVC框架webx,架构决定了前端只能依赖后端。所以他们的开发模式依然是,前端写好静态demo,后端翻译成VM模版,这种模式的问题就不说了,被吐槽了很久。而且更有可能后台人员直接兼顾前端的工作,一边实现API接口,一边开发页面,两者互相切换着做,而且根据不同的url动态拼接页面,这也导致后台的开发压力大大增加。前后端工作分配不均。不仅仅开发效率慢,而且代码难以维护。而前后端分离的话,则可以很好的解决前后端分工不均的问题,将更多的交互逻辑分配给前端来处理,而后端则可以专注于其本职工作,比如提供API接口,进行权限控制以及进行运算工作。而前端开发人员则可以利用nodejs来搭建自己的本地服务器,直接在本地开发,然后通过一些插件来将api请求转发到后台,这样就可以完全模拟线上的场景,并且与后台解耦。前端可以独立完成与用户交互的整一个过程,两者都可以同时开工,不互相依赖,开发效率更快,而且分工比较均衡。如何做到前后端分离(以下的内容都是基于我们的电影购票网站来讨论的)前端的技术框架是: vue全家桶+nodejs+express(实现的是单页面(SPA)应用)首先,先分清楚前后端的工作前端的工作:实现整一个前端页面以及交互逻辑,以及利用ajax与nodejs服务器(中间层)交互后端的工作:提供API接口,利用redis来管理session,与数据库交互我们项目的整一个架构如下:接下来进入正题,如何实现前后端分离一般来说,要实现前后端分离,前端就需要开启一个本地的服务器来运行自己的前端代码,以此来模拟真实的线上环境,并且,也是为了更好的开发。因为你在实际开发中,你不可能要求每一个前端都去搭建一个java(php)环境,并且在java环境下开发,这对于前端来说,学习成本太高了。但如果本地没有开启服务器的话,不仅无法模拟线上的环境,而且还面临到了跨域的问题,因为你如果写静态的html页面,直接在文件目录下打开的话,你是无法发出ajax请求的(浏览器跨域的限制),因此,你需要在本地运行一个服务器,可是又不想搭建陌生而庞大的java环境,怎么办法呢?nodejs正好解决了这个问题。在我们项目中,我们利用nodejs的express框架来开启一个本地的服务器,然后利用nodejs的一个http-proxy-middleware插件将客户端发往nodejs的请求转发给真正的服务器,让nodejs作为一个中间层。这样,前端就可以无忧无虑的开发了由于前后端分离后,前端和后台同时开发时,就可能遇到前端已经开发好一个页面了,可是却等待后台API接口的情况。比如说A是负责前端,B是负责后台,A可能用了一周做好了基本的结构,并且需要API接口联调后,才能继续开发,而此时B却还没有实现好所需要的接口,这种情况,怎么办呢?在我们这个项目里,我们是通过了mock来提供一些假数据,我们先规定好了API接口,设计出了一套API文档,然后我们就可以通过API文档,利用mock(http://mockjs.com)来返回一些…,这样就可以模拟发送API到接受响应的整一个过程,因此前端也不需要依赖于后端开发了,可以独立开发,等到后台的API全部设计完之后,就可以比较快速的联调。为什么要引入nodejs作为中间层前面的我发的项目结构图中,已经表明,在这个项目里,我们将nodejs作为中间层,那么,为什么我们要特地引入nodejs呢?直接用java做不就行了吗?我觉得引入nodejs主要是为了分层开发,职责划分,nodejs作为前端服务器,由前端开发人员负责,前端开发人员不需要知道java后台是如何实现的,也不需要知道API接口是如何实现的,我们只需要关心我们前端的开发工作,并且管理好nodejs前端服务器,而后台开发人员也不需要考虑如何前端是如何部署的,他只需要做好自己擅长的部分,提供好API接口就可以;nodejs本身有着独特的异步、非阻塞I/O的特点,这也就意味着他特别适合I/O密集型操作,在处理并发量比较大的请求上能力比较强,因此,利用它来充当前端服务器,向客户端提供静态文件以及响应客户端的请求,我觉得这是一个很不错的选择。前端服务器如何部署nodejs前端服务器的职责作为静态文件服务器,当用户访问网站的时候,将index.html以及其引入的js、css、fonts以及图片返回给用户负责将客户端发来的ajax请求转发给后台服务器其实前端服务器的部署工作是算比较简单的,具体有以下两个点:将开发完的前端代码,利用webpack打包成静态压缩文件在服务器上,利用pm2负载均衡器来执行以下的代码来开启服务器:(PS:其实也有一个做法,就是用nginx来做反向代理,负责转发请求,根据客户端访问的url把这个请求转发到不同的服务,比如访问/api/*的请求,就转发到后台服务,访问其它的请求,就转发到nodejs服务)以上,就是我对于前后端分离的一些看法,以及一些实践,如果大家有什么好的想法,欢迎交流。本次项目代码的地址为:https://github.com/chenjigeng… 由于本项目的后台服务已经下线,此项目运行不起来。只供参考本文地址在->本人博客地址, 欢迎给个 start 或 follow

November 17, 2018 · 1 min · jiezi

企业管理系统前后端分离架构设计 系列一 权限模型篇

前段时间分别用vue和react写了两个后台管理系统的模板vue-quasar-admin和3YAdmin。两个项目中都实现了基于RBAC的权限控制。因为本职工作是后端开发,比较清楚权限控制一个管理系统应该必须具备的核心功能,而且是可以做到通用的。打算写写关于管理系统前后端分离方面的文章,也是做一个知识的总结,其中会涉及到vue,react,node,.net core等方面的知识。术语描述用户(Subject):发起操作的主体对象(Object):指操作所针对的客体对象,比如文章或评论权限(Permission):用来指代对某种对象的某一种操作,例如“添加文章的操作”权限码:权限的代号,例如用“ARTICLE_ADD”来指代“添加文章的操作”权限权限有时候也可以称为动作或者功能。比如“添加文章”,既可以认为它是一个动作,也可以认为它是一个功能。对象也可以称为资源。常用的权限模型ACL(Access Control List)(访问控制列表)DAC(Discretionary Access Control)(自主访问控制)MAC(Mandatory Access Control)(强制访问控制)RBAC(Role-Based Access Control)(基于角色的访问控制)ABAC(Attribute-Based Access Control)(基于属性的访问控制)ACL(Access Control List)(访问控制列表)ACL是最早也是最基本的一种访问控制机制,它是用来描述用户和权限之间关系的数据列表。它的原理非常简单:每一项资源,都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行CRUD等操作。当试图访问这项资源时,会首先检查这个列表中是否有关于当前用户的访问权限,从而确定当前用户可否执行相应的操作。例如一个文件对象的 ACL 为 Alice: read,write; Bob: read,这代表 Alice 对该文件既能读又能写,而 Bob 只能读取。由于ACL的简单性,使得它几乎不需要任何基础设施就可以完成访问控制。但同时它的缺点也是很明显的,由于需要维护大量的访问权限列表,ACL在性能上有明显的缺陷。另外,对于拥有大量用户与众多资源的应用,管理访问控制列表本身就变成非常繁重的工作。最开始的ACL定义中,用户直接和权限挂钩,数据存储的是用户与权限的关联关系。如果两个用户的权限是一样的,那么就需要分别存储这两个用户与权限的关联关系,也是上面所提到的ACL的缺陷。为了解决这些问题,便有了对ACL设计的改进,相同权限的用户放到同一个分组里,分组与权限挂钩,不再是用户直接与权限挂钩。以及后来出现的RBAC(基于角色的访问控制),角色与分组也是差不多的概念,角色直接与权限挂钩,用户再与角色进行关联。所以,现在一般说ACL,不再是用户直接和权限挂钩的一种权限控制模型,把它看做一个单纯的访问控制列表即可。列表里维护的可能是用户与权限的关系,也可以是用户组与权限的关系,也可以是角色与权限的关系,甚至是部门,职位等等于权限的关系。ACL是权限体系中的业务规则。RBAC等权限模型要用到ACL才能工作,ACL服务于RBAC等权限模型,其它权限控制体系里的权限规则也叫ACL。DAC(Discretionary Access Control)(自主访问控制)系统会识别用户,然后根据被操作对象(Subject)的权限控制列表(ACL: Access Control List)或者权限控制矩阵(ACL: Access Control Matrix)的信息来决定用户的是否能对其进行哪些操作,例如读取或修改。而拥有对象权限的用户,又可以将该对象的权限分配给其他用户,所以称之为“自主(Discretionary)”控制。因为用户能自主地将自己拥有的权限授予其他用户,所以DAC模型可以任意传递权限,用户能间接获得本不具有的访问权限,因此DAC模型的安全性较低,不能给系统充分的数据保护。DAC可以直接使用ACL的物理模型,区别在于,DAC模型中用户可以将自己具备的权限分配给其它用户(程序里的操作就是根据用户ID筛选出权限列表,根据列表为要分配权限的用户构造出新的权限列表并保存)DAC是传统的UNIX访问控制模型,也是Windows文件系统的访问控制模型。Windows的文件访问权限的设置中,除了用户,还有组。这个组与后面要说到的RABC模型的角色有什么区别呢?https://stackoverflow.com/questions/7770728/group-vs-role-any-real-difference我认为没必要去划分的太清楚,不管是组还是角色,都是为了更好的管理和分配权限在最原始的ACL模型上做的改进。如果有需要,甚至可以把权限分配到部门,职位上。MAC(Mandatory Access Control)(强制访问控制)MAC是为了弥补DAC权限控制过于分散的问题而诞生的。在MAC的设计中,每一个对象都有一些权限标识,每个用户同样也会有一些权限标识,而用户能否对该对象进行操作取决于双方的权限标识的关系,这个限制判断通常是由系统硬性限制的。访问时,系统先对用户的访问许可级别和资源对象的密级进行比较,再决定用户是否可以访问资源对象。用户不能改变自身和资源对象的安全级别,只有系统管理员或管理程序才能 控制资源对象和用户的级别。比如在影视作品中我们经常能看到特工在查询机密文件时,屏幕提示需要“无法访问,需要一级安全许可”,这个例子中,文件上就有“一级安全许可”的权限标识,而用户并不具有。MAC非常适合机密机构或者其他等级观念强烈的行业,但对于类似商业服务系统,则因为不够灵活而不能适用。MAC可以继续使用DAC的模型,但是要对用户进行等级划分,比如一级,二级,三级。。。,对对象资源也要做划分,比如机密,秘密和最高机密。用户访问的资源的时候,根据用户等级与资源访问级别来做判断,比如一级用户只能访问机密文件,如果访问的是最高机密文件,系统就会拒绝。这一系列规则是优先于DAC的,如果MAC与DAC混用,要先校验MAC再校验DAC。RBAC(Role-Based Access Control)(基于角色的访问控制)ACL的访问控制机制中,直接维护的是用户与功能的关系,这一系列的关系就是一个权限列表。当很多的用户具有相同功能权限的时候,就要进行繁琐的关联操作。RBAC就是在用户与权限之间引入了角色的概念。用户与角色之间做关联,权限列表维护的是角色与功能的关系。RBAC是目前使用最普遍的权限控制模型。当某些用户具备相同的权限的时候,只需要为这些用户建一个角色,把相应的功能关联到这个角色上,生成角色的权限列表。当有新的用户需要相同权限的时候,把用户关联到这个角色上即可。而当用检查或校验用户的操作权限的时候,查询用户所属角色的权限列表即可。当然,RBAC也不是完美的,比如想要为某个用户单独设置某个功能权限,可能需要为这个功能权限单独创建一个角色,然后把特定的用户关联到这个角色上。当想要移除某个用户的特定功能权限的时候,可能需要重新设置角色的功能权限,把特定功能权限从当前角色中移除,建立新的角色并关联特定的功能权限,然后再把新角色与相关的用户做关联(也可以直接在特定功能的程序里校验操作用户)这里说一个比较常见的RBAC的错误的用法:那就是直接使用角色做权限判断。比如只有角色A才能做文章的删除操作。function delPost(postId){ if(!isRole(‘A’)){ return false; }}如果需求该为角色B也可以删除文章。那就必须修改代码function delPost(postId){ if(!isRole(‘A’)&&!isRole(‘B’)){ return false; }}正确的做法应该是添加"删除文章"这个功能,把这个功能关联到相应的角色上。判断的时候是根据功能去判断而不是角色。function delPost(postId){ if(!hasPermission(‘POST_DEL’)){ return false; }}针对“只有角色A才能做文章的删除操作”这一需求,把这个删除功能关联到角色A上,然后把需要这个操作权限的用户加入到角色A中即可。当别的角色也需要这个操作权限,把功能关联到对应角色上即可,不需要再修改代码。在RBAC的核心基础上,还可以做相应的扩展,比如角色继承,角色分组之类的,这些扩展都是为了在一定程度简化权限管理工作。ABAC(Attribute-Based Access Control)(基于属性的权限控制)RBAC虽然是目前最普遍的权限控制模型。但是某些情况下,RBAC是无法满足并且也实现不了的。比如业务员1和业务员2都属于业务员角色,都有查看客户订单的权限。当有一个需求,要求业务员1只能查看北京地区的客户的订单,业务员2只能查看上海的客户的订单。这单单使用RBAC是无法实现。借助RBAC,可行的做法是,分地区创建角色,然后程序中根据角色做数据的过滤,这种做法缺点之前也提到过,需求变更的时候可能需要每次都修改代码。上面业务员查看订单的例子,地区是订单的一个属性,需求就是针对这个地区属性来做订单的查询范围的权限控制。这种权限控制方式就是ABAC(Attribute-Based Access Control)(基于属性的权限控制),也被一些人称为是权限系统设计的未来。不同于常见的将用户通过某种方式关联到权限的方式,ABAC则是通过动态计算一个或一组属性是否满足某种条件来进行授权判断的(可以编写简单的逻辑)。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。例如规则:“允许所有班主任在上课时间自由进出校门”这条规则,其中,“班主任”是用户的角色属性,“上课时间”是环境属性,“进出”是操作属性,而“校门”就是对象属性了。ABAC非常的灵活,但是实现也是非常的难。这其中涉及到逻辑的动态执行,数据动态过滤等,更加具体就是动态拼接SQL语句(使用ORM的话就是动态组装对应ORM的查询语句)。感兴趣的可以在Github上搜索ABAC,看看不同语言是否已经有现成的解决方案。下面说说我学习到的一种实现方式:还是业务员查看订单的例子,在RBAC的基础上,扩展一个实体规则,订单就是实体,也就是针对订单设置一系列的规则。规则存储格式可以是json也可以是xml,甚至是Sql语句,能解析即可。比如北京地区这个规则:{ “regionId”:1}上海地区:{ “regionId”:3}regionId 就是系统里对应区域的Id,也是订单或订单相关表的某个字段。保存这个规则的时候,规则内容(就是上面的json),规则实体(也就是订单,表明这个规则是针对订单的)是必须的。也可以加上这个规则是适用增删改查中的一种或多种。创建好实体的规则,将规则与角色做关联,也就是将北京地区的规则关联到北京地区角色上,上海地区的规则关联到上海地区角色上。后端做权限校验的时候,还是先按RBAC模型的控制方式进行校验(是否具备订单查看权限),然后根据当前操作对象(也就是实体),取出用户所属角色关联的对应实体的规则。然后解析规则,动态拼接Sql或者ORM语句。没做地区限制(或没配置规则)的时候,Sql可能是select userId,orderNo,createdDate from T_Order配置了规则,解析拼接后可能就是select userId,orderNo,createdDate from T_Order where regionId=1这里是针对地区这个属性实现了动态的权限控制。实际开发过程中,要控制的东西是非常多了,查看字段的控制,数据范围的控制。要满足这些复杂的控制,需要制定一套完整的规则,以及针对规则编写相应的解析程序。比如根据配置的规则,最后解析出来可能是各种Sql语句:<,>,=,like,in,not in等等。可以看出,要真正的落地实现ABAC是多么的复杂。每次都要解析规则,对程序的性能也造成的影响,就算使用缓存,命中的概率也是非常的小,因为很多因素都是动态的。所以,如果需要根据属性做权限判断的场景不是很多的话,还是建议使用RBAC,然后程序中做判断比较省事省力。总结ACL早期定义中是一种权限控制机制,这种机制直接维护的是用户与功能的关系,功能就是针对对象定义的一些操作,比如增删改查的等。用户与功能的关系列表也称为权限列表或访问控制列表,现在说ACL,一般就是指这个权限列表或访问控制列表,但是里面维护的关系不一定是用户与功能的关系,在RBAC中维护的就是角色与功能的关系。RBAC在ACL的基础上加入了角色的概念,权限列表或访问控制列表里维护的不再是用户与功能的关系,而是角色与功能的关系。ACL可以和RBAC混着用,既可以在角色上设置权限,也可以直接给用户设置权限,更加灵活。借助角色的思想,可以在用户组,组织,职位等等上设置权限,以便更好的做好权限管理,也就是将权限设置从单一个体转移到某一类组合上。ABAC非常的灵活,也非常的难实现。参考文章权限系统设计模型分析Authorization Models: ACL, DAC, MAC, RBAC, ABAC ...

October 23, 2018 · 1 min · jiezi