首页 文章 精选 留言 我的

精选列表

搜索[Flowable流程审批],共10000篇文章
优秀的个人博客,低调大师

bootx-platform v1.1.0-bate4-fix:认证流程优化

项目介绍 项目地址:https://gitee.com/bootx/bootx-platform 基于 Spring Boot 框架打造,针对单体式应用进行专门设计,提供整套服务模块,努力为打造全方位企业级开发解决方案, 致力将开源版打造成超越商业版后台管理框架的项目。 特色功能 针对敏感信息,可以通过注解配置实现返回时自动脱敏 针对重要信息,可以通过添加注解,实现在数据库中保密存储,配合数据脱敏使用可以更好的保护系统数据的安全 支持多种范围的数据权限控制,如只能查看自己、只能查询指定部门、用户、可以查询全部的数据等等 支持嵌套查询的超级查询构造器,自动生成对应条件 SQL 语句 异常时返回链路追踪 id,方便错误日志追踪 提供项目对应的代码生成器,方便开发 定制 Mybatis Plus 组件,更方便开发 支持多种消息中间件,MQTT、RabbitMQ、Redis 支持全局级 Websocket 集成,通过事件机制可以分发到指定页面 支持通过 ELK 和轻量级 PlumeLog 来管理项目日志,以适应不同的场景 提供移动端开发脚手架,方便开发 H5 与各种小程序 支持通过微信、钉钉、企业微信等第三方开放平台进行扫码登录 本次功能更新 bate4版本发布后发现认证终端这块设计有问题,秉持着有问题早解决的想法,把这一块进行了重构,同时修正了一些其他与登录认证相关的问题,特此发个版本 重构认证应用和认证终端重新设计为认证终端和登录方式 增加用户手机号/邮箱绑定功能 优化微信、钉钉、企业微信绑定时重复校验 优化@IgnoreAuth鉴权注解功能 fix: 开放平台登录报错问题 新功能截图 新认证终端 新登录方式 手机号/邮箱绑定

优秀的个人博客,低调大师

轻量级开源流程编排引擎

LiteFlow 2.6.2版本发布了!这个版本新增一个特性,重构了底层的parser代码。 如果你是第一次知道LiteFlow这款框架,可以移步以下链接进行了解: LiteFlow官网:https://yomahub.com/liteflow Gitee仓库托管主页:https://gitee.com/dromara/liteFlow Github仓库托管主页:https://github.com/dromara/liteflow 也可以看我之前发布的一篇介绍LiteFlow这个框架的文章 https://mp.weixin.qq.com/s/xyydmtk_a5R1zbg3EeORaw 本次更新点如下: 特性 #I4CRSY 增加了组件标签特性,支持在组件里获取自定义的标签组件 https://gitee.com/dromara/liteFlow/issues/I4CRSY

优秀的个人博客,低调大师

【JVM技术探索】全流程化分析Java对象的创建过程

前言概要 对应过程则是:对象创建、对象内存布局、对象访问定位的三个过程。 对象的创建过程 对象的创建方式 java中对象的创建方式有很多种,常见的是通过new关键字和反射这两种方式来创建。除此之外,还有clone、反序列化等方式创建。 通过new关键字创建 // Person zhangsan = new Person(id, height, weight) Person zhangsan = new Person(); 通过反射创建 反射创建对象,可以通过class.newInstance()调用无参的构造器创建对象,也可以使用构造器来创建constructor.newInstance()。 //Class clz = Class.forName("Person类的全限定类名") Class clz = Person.class; Person zhangsan = clz.newInstance() // 使用构造器创建 Constructor<Person> cons = clz.getConstructor() // 也可以指定参数类型获取有参构造器 Person zhangsan1 = cons.newInstance() 通过clone创建对象 当类实现了Cloneable接口时,可以使用clone()方法复制一个对象。需要留意是clone方法是浅拷贝。 Person libo = new Person(name: "李博", age:12, ...) Person Livonor = new Person(name: "Livorno", age:32, ...) libo.setFather(Livonor) Person zhangsi = libo.clone() // 此时,张四和张三的名字、父亲在内存中都引用了相同的对象 反序列化创建 通过读取IO数据流创建,非本节重点 对象的创建过程 检查类加载(包含是否初始化、是否被加载、是否被解析) 对于new和反射两种创建方式而言,需要检查创建对象所使用的参数是否已完成类加载(比如它的类型和参数类型)。如果没有,要先完成类加载过程。 分配内存空间 虚拟机为对象分配内存,即起始地址和偏移量。 对象所需要的空间在创建前就可以确定,但是起始地址需要在分配时去内存中找到一块足够大的空间。地址的分配有两种方式:指针碰撞和空闲列表。 指针碰撞 指针碰撞的方式是假设内存空间是规整的,被使用的和空闲的内存被分割成了两整块,通过一个指针记录分界点。在给对象分配内存的时候,将指针空闲区域移动一段与对象大小相等的距离即可。 空闲列表 如果内存不规整,那么就需要维护一张表,来记录内存中那些地址是空闲的。分配对象时,通过空闲列表去找到一块足够大的空闲内存分配给对象并更新空闲列表。 多个线程创建的对象内存的冲突 举个例子,线程1和2同时要创建两个对象,指针是同一个。它们各自将指针加载到了cpu缓存,然后去执行分配地址空间的指令。结果就导致,后分配的哪一个,可能将先分配的那个对象的地址给覆盖了。 解决的办法有两种,一种是对分配内存的动作进行同步处理,即采用CAS加失败重试的方式,保证更新操作的原子性。 // 伪代码表示CAS+失败重试 while(true){ oldPtr = ptr //读取共享指针 newPtr = oldPtr + sizeOfInstance if(compareAndSet(oldPtr, ptr, newPtr)){break} } 另一种是使用TLAB的方式将线程的分配空间在堆内存中隔离开,在堆中为每个线程预先分配一小块不同的空间,每个线程创建对象都在自己对应的空间中完成。 即每个线程在 Java堆中预先分配一小块内存(本地线程分配缓冲(Thread Local Allocation Buffer ,TLAB)),哪个线程要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配新的TLAB时才需要同步锁。虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定。 分配完内存之后,对象就已经存在于虚拟机的堆中了,此时虚拟机要将分配的内存空间初始化为零值(对象头例外)。 设置对象头 对象头包含了两种信息:MarkWord和类型指针。 MarkWord:存放对象本身的运行时状态数据(如HashCode, GC分代年龄、锁状态、是否偏向信息等) KlassPointer:类型指针指向它的类型的元数据。对象头在对象的内存布局中细讲。 即对象指向它的类元数据的指针 虚拟机通过这个指针来确定这个对象是哪个类的实例 数据长度:如果对象 是 数组,那么在对象头中还必须有一块用于记录数组长度的数据 因为虚拟机可以通过普通Java对象的元数据信息确定对象的大小,但是从数组的元数据中却无法确定数组的大小。 执行对象实例构造函数 首先递归的执行父类的构造函数,然后收集本类中为实例变量赋值的语句并执行,最后执行构造方法中的语句。 public class AddA { public static void main(String[] args) { Father guy = new Son(30); guy.saySomething(); System.out.println(guy.age); } } class Father{ int age = 60; public Father() { saySomething(); } public Father(int age) { this.age = age; } public void saySomething(){ System.out.println("I am the father, " + age + "years old"); } } class Son extends Father{ int age = 20; public Son(int age) { // super(); 不写则隐式调用方法,写则必须在子类构造方法的第一句 saySomething(); this.age = age; saySomething(); } public void saySomething(){ System.out.println("I am the son, " + age + " years old"); } } 因为它涉及到了多态与方法的动态分派。在这里先简单描述一下它的执行过程,用来掌握构造方法的执行还是ok的。 首先,创建一个Son对象,然后调用其有参构造方法Son(int age)。 在有参构造方法中隐式调用了父类的无参构造方法,然后父类的构造方法继续调Object的构造方法。接下来收集为父类成员变量赋值的语句并执行。 由于多态中子类的成员变量会覆盖父类的成员变量,因此子类对象的age仍然是0。 同时无参构造方法中的saySomething()此时是被子类对象调用的,因此打印了第一句I am the son, 0 years old。 然后,super()方法出栈,回到子类构造方法中。此时应该收集为子类成员变量赋值的语句并执行。对象的age=20,saySomething()打印出第二句I am the son, 20 years old。 然后执行构造方法中的赋值语句int age = age;saySomething(); 第三句话被打印I am the son, 30 years old。 子类对象创建完成,回到main方法。此时使用多态,将对象转成Father对象。 由于多态的规则:被重写的方法使用动态分派,查找(vtable)方法表,该方法实际是属于子类对象的。 因此guy.saySomething()实际调用的是子类对象的方法,打印出第四句话,I am the son, 30 years old。 最后,输出guy.age. 成员变量不具备多态性,因此打印出父类对象的age 60. I am the son, 0 years oldI am the son, 20 years oldI am the son, 30 years oldI am the son, 30 years old 对象的内存布局 对象在堆中的存储布局划分为三个部分:对象头、实例数据和对其填充(padding)。 对象的内存布局 对象头 对象头中包含markword(标记字段)和类型指针【数组长度】。 markword markword存储与对象自身定义数据无关的信息,用来表示对象的运行时状态。包括了HashCode,GC年龄,锁状态等信息。在一个32位的虚拟机中,markword用一个32位的bitmap表示,bitmap最后两位存放锁状态信息,如下图。 markword 普通状态下,状态为01,存储hashcode,分代年龄,偏向锁状态为0。 偏向锁状态下,状态为01,存储持有偏向锁的线程和重入次数,分代年龄,偏向锁状态为1。此时hashcode没了,但是,hashcode可以通过Object的hashcode()方法计算出来,只要没有重写该方法,那么得到的哈希码始终是一致的。 轻量级锁,状态为00。通过cas方式将对象的markword信息原子性地交换到了持有该对象锁的线程中,存储在lockRecord内,并同时将lockRecord的指针存放在对象头Markword的前30位。 重量级锁状态下,前30位存放指向锁控制器Monitor的指针,锁状态为10. 对象被标记为待回收状态时,最后两位状态为11. KlassPointer(类型指针) 指向类型元数据,从而可以通过对象来访问到它的类型信息。 数组长度(array length) 主要记录数组的长度信息一般为4字节(根据int的范围来考虑) 实例数据 实例数据中存放了对象的字段信息。无论是从父类继承的,还是在子类中定义的,都保存在实例数据中。 按照一定顺序存放,在满足这个顺序的条件下,父类定义的字段又会出现在子类定义的变量之前。 即代码中定义的字段内容 注:这部分数据的存储顺序会受到虚拟机分配参数(FieldAllocationStyle)和字段在Java源码中定义顺序的影响。 // HotSpot虚拟机默认的分配策略如下: longs/doubles、ints、shorts/chars、bytes/booleans、oop(Ordinary Object Pointers) // 从分配策略中可以看出,相同宽度的字段总是被分配到一起 // 在满足这个前提的条件下,父类中定义的变量会出现在子类之前 CompactFields = true; // 如果 CompactFields 参数值为true,那么子类之中较窄的变量也可能会插入到父类变量的空隙之中。 对齐填充 如果对象的实例数据占用空间不是8的整数倍,则填充0值让对象的占用空间位8的整数倍。 对象的访问定位 常见的有两种方式,句柄访问和直接指针访问。 句柄访问 使用句柄访问的话,对象的引用(如zhangsan),指向的是句柄池中的某个句柄,该句柄存放了指向实际实例对象的指针和指向方法区数据类型的指针。 其好处是,当对象被移动的时候(比如垃圾回收时,整理内存空间需要大量移动对象),不需要频繁的修改引用,只需要修改句柄中实例数据指针。 通过指针访问,则是对象的引用直接指向了该对象。其好处是,通过引用访问对象时,不需要多一次的指针定位,使得访问速度更快。

优秀的个人博客,低调大师

阿里云ECS服务器入门使用流程 新手必看教程

一、阿里云根据个人需要选合适的云服务器,选好cpu、内存、带宽,地域,这四个是主要的。其他可以默认选择。选择服务器之前先领取代金券减少上云成本 二、登陆控制台 输入账号密码,进去看到服务界面,新手可能不容易看懂。点击左侧菜单,点击云服务器,显示界面如图: 点击实例,在左上角选择区域(一定要选对地域才能看到服务器),这时看到服务器信息了,如图: 大家不要看这里这么多信息,对我们有用的其实只有几个而已,别的都不用看。更多参阅云服务器配置帮助文档。 三、连接主机 1、通过控制台连接 阿里云服务器要用到两个密码,一个是远程登录密码,一个是实例密码,就是我们平常登录服务器的root密码(以linux服务器为例)。通过控制台连接服务器需要使用到这两个密码,如果不知道重置即可。注意:修改实例密码需要重启服务器才能生效。 点击远程连接,输入远程连接密码 输入root用户和密码(就是刚才改过的实例密码),开始对服务器进行操作。 登录成功后,可以输入各种命令。点击左侧按钮列表的断开连接,就能够断开与服务器的链接了。 2、通过工具连接 在云控制台的实例页面看到公网IP,通过工具软件连接服务器,和上面的作用一样,可以输入各种命令了。 三、开通安全组同样在实例最右侧点击【更多】>>【网络和安全组】>>【安全组配置】 点击配置规则 入方向看到的就是目前服务器的安全组规则了,你可以在这里添加、修改、删除规则。 比如要开放 80端口,按照下面的例子填写。这块挺重要的,规则添加不对了可能就无法正常访问了。更多参阅安全组帮助文档。 四、网站搭建 做网站的话可以搭配系统镜像使用,阿里云自带一键开通,方法如下图: 点击【确定,更换系统盘】,注意提前保存数据。点击【镜像市场】,从镜像市场选择 搜索【宝塔面板】,选择0/月的,注意看已使用人数,选择人数多的那个。 自定义密码,然后输入符合要求的密码。这里记住登陆名和密码,以后链接服务器都要用。也可以用密钥方式,这里不细说了。 接下来记住宝塔面板的登陆地址,账号密码。去登陆到宝塔面板中,开始建站之旅。记住如果宝塔面板无法登陆,那是因为安全组中没有添加面板的端口,按照上面的办法去添加就行了。更多参阅镜像市场帮助文档。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册