layui框架使用方法详解

前言 首先我们先了解一下什么是layui。 layui(谐音:类UI) 是一款采用自身模块规范编写的前端 UI 框架,遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到 API 的每一处细节都经过精心雕琢,非常适合界面的快速开发。 layui框架结构 ├─css //css目录 │ │─modules //模块css目录(一般如果模块相对较大,我们会单独提取,比如下面三个:) │ │ ├─laydate │ │ ├─layer │ │ └─layim │ └─layui.css //核心样式文件 ├─font //字体图标目录 ├─images //图片资源目录(目前只有layim和编辑器用到的GIF表情) │─lay //模块核心目录 │ └─modules //各模块组件 │─layui.js //基础核心库 └─layui.all.js //包含layui.js和所有模块的合并文件 快速上手 首先,我们先获得(下载) layui 的最新版,链接地址:https://res.layui.com/static/download/layui/layui-v2.4.5.zip 然后解压部署到我们的静态资源目录下, 然后引入到我们的工程里面,在这里,只需要引入两个文件。 <link rel="stylesheet" type="text/css" href="${path}/public/layui/css/layui.css"> <script type="text/javascript" src="${path}/public/layui/layui.js"></script> 不需要管其他文件,只需要这两个就可以使用layui前端框架了。 基础入门 照葫芦画瓢 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title>开始使用layui</title> <link rel="

Clang Plugin 之 Debug

前面一篇文章 LLVM & Clang 入门 讲了如何编写一个 Clang 插件,然后将插件编译成一个.dylib的动态链接库。集成到 Xcode 中就可以看到效果(正确的结果)。 在得到正确结果的过程中,必不可少的一步就是Debug,没有任何程序是一蹴而就的,除非你printf一个"Hello, World!",说不定你的world还写成了word。 在使用Plugin的模式下我们是不能打断点进行 Debug 的,但是我们可以在代码中加日志,然后在终端中执行命令看日志进行 Debug。这种低效率(Low)的方式是你想要的吗?显然不是。 我们只需要把.dylib动态库变成可执行文件就能打断点 debug。LibTooling 或许是一个不错的选择。使用 LibTooling 的话,我们只需要改动很少部分的代码就可以。 LibTooling 简介: LibTooling 是一个独立的库,它允许使用者很方便地搭建属于你自己的编译器前端工具,它基于 C++ 接口,提供给使用者强大全面的 AST 解析和控制能力,同时由于它与 Clang 的内核过于接近导致它的版本兼容能力比 libclang 差得多,Clang 的变动很容易影响到 LibTooling。libTooling 还提供了完整的参数解析方案,可以很方便的构建一个独立的命令行工具。 创建 LibTooling 项目及代码调整 为了方便,我们直接创建一个可执行的LibTooling项目,我们可以创建一个名为QTPluginTooling的项目。 创建过程跟 创建插件 步骤差不多,前面 3 步都是一样的,只需要把QTPlugin替换为QTPluginTooling就可以。 只是在第 4 步略有不同,QTPluginTooling目录下的CMakeLists.txt的文件内容为 set(LLVM_LINK_COMPONENTS Support ) add_clang_executable(QTPluginTooling QTPluginTooling.cpp ) target_link_libraries(QTPluginTooling PRIVATE clangAST clangBasic clangDriver clangFormat clangLex clangParse clangSema clangFrontend clangTooling clangToolingCore clangRewrite clangRewriteFrontend ) if (UNIX) set(CLANGXX__LING_OR_COPY create_symlink) else() set(CLANGXX_LINK_OR_COPY copy) endif() 复制代码

解决npm不支持Nodejs版本的问题

本来今天是打算使用git bash安装babel的,但是在使用npm的时候发现崩了,出现了类似以下的情况(我的Nodejs版本是11.6.0)。 网上谷歌了下说是因为NodeJs的版本太高了,npm不支持安装的Nodejs版本。看了下npm -v,我的还是5的版本,所以得去升级下npm了。 如果说按照网上的解决办法只是重装下Nodejs,npm自然也会跟着升级的话那也好。只是我最后安装完Nodejs后发现,npm的版本还是5的版本。最后实在不行我做了以下三件事: 使用which npm命令找到npm的路径,执行rm命令删除。 which npm //第一条命令 rm "/c/Program Files/nodejs/npm" //第二条命令 找到node_modules下的npm目录,删除。 C:\Users\lvb\AppData\Roaming\npm\node_modules\npm 重新安装Nodejs,再次查看Nodejs和npm的版本是否匹配。 至此成功的更新了npm的版本号,升级后也匹配Nodejs的版本了。如果想知道自己的Nodejs和npm的版本匹配,可以查看下面的操作步骤。

windows在注册表中删除了HKEY_CLASSES_ROOT\.exe导致无法打开.exe文件

一不小心将注册表中的HKEY_CLASSES_ROOT\.exe删除,导致.exe文件全部打不开。本想重新添加一个值到注册表,却发现就连注册表都打不开。win+R,输入regedit都打不开。还好网上教程多。 新建一个txt文件。写入下面的内容。 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.exe] @="exefile" "Content Type"="application/x-msdownload" [HKEY_CLASSES_ROOT\.exe\PersistentHandler] @="{098f2470-bae0-11cd-b579-08002b30bfeb}" 重命名.reg。文件名随意,保存。双击执行。就好了。

Unity DrawCall详解

在实际项目开发中,提起unity优化,肯定是有DrawCall的相关内容的,下面就讲解一下什么是DrawCall以及如何对DrawCall进行优化操作。 一、什么是DrawCall? 在unity中,每次CPU准备数据并通知GPU的过程就称之为一个DrawCall。 具体过程就是:设置颜色-->绘图方式-->顶点坐标-->绘制-->结束,所以在绘制过程中,如果能在一次DrawCall完成所有绘制就会大大提高运行效率,进而达到优化的目的。 二、DrawCall为什么会影响游戏运行效率? 说道为什么会影响效率,就首先要了解一下他的工作原理:为了CPU和GPU可以进行并行工作,就需要一个命令缓冲区,就是由CPU向其中添加命令,然后又GPU从中读取命令,这样就实现了通过CPU准备数据,通知GPU进行渲染。 在每次调用DrawCall之前,CPU需要向GPU发送很多内容,主要是包括数据,渲染状态(就是设置对象需要的材质纹理等),命令等。CPU进行的操作具体就是: 准备渲染对象,然后将渲染对象从硬盘加载到内存,然后从内存加载到显存,进而方便GPU高速处理设置每个对象的渲染状态,也就是设置对象的材质、纹理、着色器等输出渲染图元,然后向GPU发送DrawCall命令,并将渲染图元传递给GPU 所以如果DrawCall数量过多就会导致CPU进行大量计算,进而导致CPU的过载,影响游戏运行效率。 三、如何优化DrawCall? 1.关于图集、材质、层级的处理,减少DrawCall 想看这些如何进行优化,就需要对他们的工作原理进行理解一下。下面我们以NGUI为例,讲解一下他们之间的关系: NGUI主要是有三大模块组成:UIPanel,UIWidget,UIDrawcall组成,其中UIPanel是用来管理UIWidget控件和UIDrawCall,而UIWidget是所有组件的基类。 在NGUI框架中,会有一个静态的list用来存放所有的Panel,然后每个单独的Panel下会保存自己的UIWidget和UIDrawCall,就是在每次绘制的时候panle会遍历自己下面的所有层级下的子物体,直到查找结束,或者遇到新的panel会跳出当前分支,继续寻找其他分支,直到全部查找结束。所以说在实际运行中,每次都会为一个UIWidget绘制一个DrawCall,如果这时候连续的多个UIWidget使用的材质和纹理一致,就会公用一个DrawCall,下面给大家看下具体的情形: 这是使用不同材质和纹理的情况 这是使用相同的材质和纹理的情况​​​​​​ 所以并不是好多人的认知是只要同一个图集就会占用同一个DrawCall,通过上图分析发现不光是要使用同一个图集,还要使用同样的材质在同一个panel下才可以,否则就会重新进行调用一次DrawCall。另外需要注意的是,如果使用同一个图集、材质,但是中间夹杂了其他的渲染状态,也会导致重新调用一次DrawCall。 另外还需要注意一点就是在panel下如果动态的物体,就是为了实现某种效果,需要UI 进行位置移动,这种情况下,最好做成动态分离,因为只要panle下UI有移动,panle就会对清空之前的保存的UIWidget和UIDrawCall,重新进行渲染,这样就会造成性能浪费,有的同学会说这样不是增加了DrawCall吗,但是相对于每次都重新绘制,应该还是会更加节省性能的吧,你说呢? 所以说在对UI进行界面排布就需要对图集和层级做好规划,进而减少DrawCall次数。 2.关于批处理 批处理从字面意思就是一块处理多个物体的意思,但是是什么样的都可以进行批处理吗?答案就是使用同一个材质的物体才可以。unity中有个两种批处理方式,动态批处理和静态批处理。对于动态批处理来说,好处就是一切都是自动处理的,并且物体是可以移动的,但是限制颇多,具体有哪些限制下面会进行分析。对于静态批处理来说,好处就是自由度很高,限制条件少,但是它会占用更多的内存,并且经过批处理的物体不可以在进行移动。 首先说一下动态批处理,条件是物体使用同一个材质,并且满足对应的特定条件,unity就会自动为我们做动态批处理。 这里可以看到动态批处理中,四个物体但是只占用了三个DrawCall,就是unity进行了动态批处理,两个cube只占用了一个DrawCall。 下面说下动态批处理限制: 顶点属性最大限制900,使用lightmap的物体不行进行批处理使用MultiplePass的shader也不会进行批处理接受实时阴影的物体也不会进行批处理 下面说下静态批处理, 静态批处理前提当然也是使用了同一个材质,然后就是讲对应的对象设置为static: 这时你会发现DrallCall变为1了,这就是静态批处理的作用,但是这时候你会发现VBO Total比刚才大了,这就是静态批处理坏处,通过内存来换取性能,下面我们看下官方的解释: 如果在静态批处理前有一些物体共享了相同的网格(例如这里的两个箱子),那么每一个物体都会有一个该网格的复制品,即一个网格会变成多个网格被发送给GPU。在上面的例子看来,就是VBO的大小明显增大了。如果这类使用同一网格的对象很多,那么这就是一个问题了,这种时候我们可能需要避免使用静态批处理,这意味着牺牲一定的渲染性能。例如,如果在一个使用了1000个重复树模型的森林中使用静态批处理,那么结果就会产生1000倍的内存,这会造成严重的内存影响。 3.减少实时光的使用以及阴影效果 同样的设置,但是如果你将灯光的阴影效果打开,你会发现DrawCall大幅增加: 所以在项目中,如果想让场景更加完美,可以使用lightmap满足你想要的阴影效果。 综上所述就是要对图集进行和层级处理要做好整体规划,尽量将材质纹理合并,对于灯光的根据当前情况做好相应处理。

解决MySQL开机提示 “High Severity Error”问题

电脑出现异常关机,电脑再次开机MySQL出现 “High Severity Error”的问题,这种情况可能是因为配置文件损坏导致的。 解决方案是从文件管理器中输入“%AppData%\Oracle\MySQL Notifier\”,然后删除目录下的“settings.config”文件,然后重启电脑就可以了。

Ubuntu下MySQL Server安装

公司业务需要安装MySQL,安装过程比较简单,但是在配置连接的中途遇到了不少坑,特此记录下来。 一、安装: sudo apt-get update sudo apt-get install mysql-server sudo apt-get install mysql-client sudo apt-get install libmysqlclient-dev 二、配置: 1、启动 /etc/inint.d/mysql start 2、停止 /etc/inint.d/mysql stop 3、重启 /etc/inint.d/mysql restart 三、连接: 在mysql server启动后通过mysql -u(用户名) -p(密码)连接的时候出现了以下错误: ERROR 2003 (HY000): Can't connect to MySQL server on '*.*.*.*' (111) 出现这个问题是因为配置文件中有bind_address=127.0.0.1 ,只能本地登录,需要修改my.cnf解决: 1、vim /etc/mysql/my.cnf 2、注释掉bind-address = 127.0.0.1 3、/etc/init.d/mysql restart 屏蔽掉之后客户端再次连接又出现: ERROR 1130 (HY000): Host '*.*.*.*' is not allowed to connect to this MySQL server 这个问题是因为外部ip地址访问数据库并没有权限,需要让数据库给其分配权限,在本地登录mysql,执行 1、设定指定ip能够访问mysql:

我在51CTO微职位学软考——心得

有时候感觉自己还有大把的青春和时间去挥霍,却不知挥霍到哪里。因为每天的时间只能干两件事,就是上班忙工作,下班玩孩子。所以日子过的总有些平淡无奇,其它时间倒头便睡。然而即便睡也睡不踏实,半夜醒来常常被工作的压力折磨醒,早晨睁眼依然满眼疲惫,继续上班、看孩子、睡觉。 三十而立,但我这人比较后知后觉,直到三十五才有而立的体会。管着一个不大不小的公司,膝下一儿一女。已经可以依靠自己的本领独立承担自己应承受的责任了,但自己的人生目标与发展方向又在哪里,始终没有一个清晰的定位。清晰的定位不光是要对自己负责,更重要的是对自己的孩子负责。我已经后知后觉了,但我希望他们将来能有一条捷径,在属于他们的那个时代脱颖而出,而我就是这条捷径的领路人。 记得刚毕业不久在微软实习的那段时间,我想的最多的问题就是为什么10年前没有好好学习英语,要是可以沟通无障碍,那我现在就可以留到微软,享受弹性式工作制和超高薪待遇了。工作了几年我又再想为什么10年前没有好好学习java,从2000年开始学习电脑,到现在也没有积累多少开发经验。要不然现在也不用天南海北的跑,逢年过节买站票赶着回家了。现在虽然过的比较稳定,然而这种稳定带来的却是对未来的一种危机感。我不希望10年再后回想自己现在错过了什么,我要在当下做的尽量多一些,保证未来不会后悔。因为只有此时此刻的决定才能影响我未来的生活。于是我开始思考现在应该干些什么。我现在需要钱养活孩子,钱现在够用,未来肯定不够。所以我不能像现在这样赚钱。10年后也许我会在别的公司,干别的事情。所以我现在的技能在新公司可能完全用不上,所以我要尽量多掌握一些技能,保证在任何公司工作都要成为不可替代那个人,才能保证我的收入。于是我开始思考多考一些证书,一定要含金量高的,并且不光是要拿证书,一定要能学到真东西用在提升工作效率上,从而提升收入。所以开始研究几年前就开始关注的软考,这时候我自然又有了后悔情绪,如果前几年就考几个这样的证书,现在也许挂靠费都挣了不少了。此时我也终于下定了决心,今年软考必过一门。先拿个中级,再拿个高级,高级以后可以申请当评标专家,可以申请当大学里的客座教授,这也许也是一条不错的发展路线。 我是51cto的老用户了,经常在这里查一些免费的课程,至少我人为在业界比较权威,所以我选择报名也在这个比较熟悉的平台。自己学习可能抓不住重点,所以在这个知识付费的年代,我愿意交些学费走走捷径。学费自己还能承受的起,只是回家对老婆可能要解释一二。毕竟目前为了这俩孩子,一直过着精打细算的生活。现在几千块钱的投入,未来就会多出一条生存道路,我想这样的道理她还是比较赞成的。结果就在之后的几天被证实。她不但没什么意见,相反我还经常被讽刺。因为在公司我要管人力、财务、业务、项目等,忙的不可开交。幼儿园还有活动不停叫家长参与,老婆去不了我就不能错过。回了家给孩子讲绘本、做游戏、洗涮睡觉。老婆忙完学校的孩子,回来又给这俩进行辅学。一天下来已经晚上11、12点了,很疲惫,于是什么也不想干,就想睡觉。她看我报了名好几天没动静,于是就讽刺我说,看来这钱又白花了。我也曾做过规划,把我从早上七点到晚上十二点的工作活动全部罗列了一遍,结果发现一天顶多挤出俩小时,而这俩小时还是吃饭、上厕所、在路上。我记得是五月份报的名,直到八月份才开始看视频教程。有时候在厕所举着手机看,有几次在公交上看,有时候陪孩子玩的时候电脑在一旁播着。但结果是完全记不住。就这样断断续续看到11月份,视频教程没有看完。还有十天,也是最关键的十天,如果还没什么改变,那我这次软考的计划就泡汤了。也就是这段时间,学习群里连续发了几个浓缩版的精华材料。于是我把希望寄托在这些材料上面,但依然还是内容有些多。而我又静不下心来背,只是草草看过有个印象。事后才发现原来就是这些印象导致了我软考顺利通过。 考试那天我提前两个小时出发,打算到了考场在临阵磨会抢。结果堵车。确实堵,全内蒙的考生都在往呼和浩特市的那一个地方赶,而且就一条快速路,上去了就拐不下来。看着时间一分一秒过去,只能听天由命。把车停好还有五分钟开考,我从校门口一路狂奔到考场,考场很远。还好开考不到五分钟。在我之后的人就没让进了,暗自庆幸,但心不平,气不和。我答的很慢,不准备答完卷后返回头在重新检查,因为即使检查也不能确定到底那个是正确答案。经历过这些年最紧张的两个小时考试,从考场出来我终于心平气和了。慢慢的开车回家,这回堵的再厉害也不着急了,而天边的夕阳很大很红,似乎在预示着一个不错的结果。考试结果出来后,上、下午两科均50分以上,确实是不错的结果。 回想起来,还是最后51CTO发的那几个综合性材料起了决定性作用,真正感受到了51学院确实经验丰富,比较权威,所以我毫不犹豫的又报第二年的软考,由于报名太快,都没赶上双十二活动。但我知道软考拿证后,产生的价值一定高过今次报名的学费。现在我真正在乎的是用知识去赚钱,用赚的钱在去学知识这条路,是我趁还年轻,真正要走的一条路,未来我要走出更多的路。就像一颗树会长出很多树枝。终究会成为一个参天大树,而每根树枝的尽头,总会长出新绿的树叶。多年后落叶归根是我的归宿,但在相同的位置会再次开枝散叶,这就是我的孩子,是我生命和意志的延续,这棵参天大树则永远生机勃勃。 转载于:https://blog.51cto.com/2000145/2335930

Linux下的-bash: command not found错误(解决方法)

当我们在 Linux下执行一个命令时,报 -bash: XXXX: command not found,这和Windows是相同的道理,都是环境变量惹的祸, 就是说你的 命令的 执行文件不在 /usr/bin 或者 /etc/init.d 中,他就找不到 执行该命令的 文件来执行. 思路是将 该应用的 bin 目录 放入到 profile 文件中就OK了 1、find / -name profile #找到该文件(这个文件相当于 你在Windows 中加入环境变量那块),一般该文件在 /etc/profile 这里 2、vim profile #编辑该文件 3、export PATH=”$PATH:/usr/local/nginx/sbin” #在该文件中加入 command not found 的应用的 bin 目录, 4、source /etc/profile // 更新配置(不用重启系统) 之后你在执行 就 OK啦! 转载于:https://blog.51cto.com/python20101030/2335470

Linux中怎么搭建Discuz论坛

文章目录 Linux中怎么搭建Discuz论坛1、搭建yum安装环境:2、安装http服务:3、安装php*软件:4、安装数据库:5、登陆数据库:6、创建数据库:7、搭建论坛: Linux中怎么搭建Discuz论坛 说明:本实验再虚拟机中进行,所使用的软件是VMware Workstation Pro14.0 使用的是rhel-server-7.5-x86_64-dvd的镜像文件,搭建论坛的安装包为Discuz_X2.5_SC_UTF8.zip。 1、搭建yum安装环境: (1)编辑yum的配置文件: vim /etc/yum.repos.d/base.repo (2)在配置文件中写下下面这段代码,写完后记得保存并退出。 (3)然后我们将Redhat7.5的镜像文件挂载到指定挂载点目录/mnt使用命令: mount /dev/sr0 /mnt/ (4)紧接着我们使用命令:yum repolist 查看一下yum的安装是否正确,当状态出现5099时,说明安装没有问题。如下图: 2、安装http服务: (1)使用命令: yum install httpd -y,来安装一个http(包名:httpd)的服务,当出现complete!即完成。 (2)重新启用httpd这个服务,使用命令 systemctl restart httpd (3)我们查看一下防火墙运行状况,使用命令: systemctl status firewalld (4)由于防火墙是开着的,会阻止我们虚拟机与pc之间互相的访问,因此我们需要关闭防火墙。 使用命令: systemctl stop firewalld.service (5)然后我们使用pc机上的浏览器,输入虚拟机当前的IP地址:192.168.0.22,然后访问。就会进入如下界面: 看到这个界面,说明已经访问到的是http所用apache软件的主界面。 (6)如果没有看到这个界面,还需要关闭SELINUX,使用命令: setenforce 0,关于SELINUX以后我会在我Linux进阶中详细解释的。建议有没有看到这个界面,都敲一下比较好。 3、安装php*软件: 它是网页相关的软件,我们要动态访问网页。安装有关php的所有软件,使用命令:yum install php* -y 4、安装数据库: (1)一般默认都已经安装过了,不过没关系,我们可以再安装一下,使用命令: yum install mariadb-db -y ,它会提示我们已经安装过了。如下图: (2)启动服务,使用命令: systemctl start mariadb.service (3)数据库安好后,我们需要初始化数据库。论坛中的数据都被存放再数据库中,数据库可以简单的理解为一张EXCEL表格,对应的用户和密码等信息。 ①安装数据库:使用命令: mysql_secure_installation ②然后直接回车进入下一步,它会提示是否给进入数据库的root用户设置密码 ③我们输入y或Y,回车后输入密码,两次密码一致进入下一步。 ④询问:是否删除匿名(anonymous)用户?y 这个根据实际情况而定。由于我们这里是实验,直接y到下一步。 ⑤询问:不允许(disallow)root用户远程登陆?y ⑥询问:移除数据测试数据库并访问它?y ⑦询问:现在重新加载权限表?y

利用python 在网页上显示markdown

介绍 _很多同学可能有这种情况,在自己的网站上显示自己写的markdown文档,当然 你可以利用你的MD工具把你的markdown导出html的文件,然后在网页上显示。不过你每改动一下,就要重新导出一次,非常繁琐,这篇文章就是简单介绍一下如何利用flask+python 在自己的服务器上用html显示markdown文档 _ 准备工作 如果想在服务器上部署,那么请先看我的这篇文章 服务器配置flask+nginx+python服务基本使用 可以看一下我的这篇博文 python Flask的基本使用依赖库 : markdown 开始 1 安装markdown依赖库 pip3 install markdown 2 main.py from flask import Flask from flask import render_template from flask import Markup import markdown app=Flask(__name__) @app.route('/main') def index(): content = md2html('static/doc/main.md') #markdown文件的路径 return render_template('index.html',**locals()) #md转html的方法 def md2html(filename): exts = ['markdown.extensions.extra', 'markdown.extensions.codehilite','markdown.extensions.tables','markdown.extensions.toc'] mdcontent = "" with open(filename,'r',encoding='utf-8') as f: mdcontent = f.read() pass html = markdown.markdown(mdcontent,extensions=exts) content = Markup(html) return content if __name__ == '__main__': app.

指针19 用指向结构体的指针做函数参数

例题 有一个结构变量s,含有学号、姓名、性别和成绩4 个成员,要求在main函数中输入结构体变量成员的数值,在另一个函数中输出结构体变量成员的数值。 代码 #include<stdio.h> struct student {long num; char name[15]; char sex; float score; }; int main() {void print(struct student *p); struct student s; printf("Number:"); scanf("%ld",&s.num); getchar(); printf("Name:"); gets(s.name); printf("Sex:"); scanf("%c",&s.sex); printf("Score:"); scanf("%f",&s.score); printf("Number Name Sex Score\n"); print(&s); return 0; } void print(struct student *p) {printf("%-8ld%-7s%-4c%-5.1f\n",p->num,p->name,p->sex,p->score); } 运行结果 p.s.注意 gets函数前的getchar()函数是用来存储回车的 下一篇 指针20 动态存储分配简介上

解决:shiro中重写doGetAuthenticationInfo,结果首次登录先执行doGetAuthenticationInfo后执行login的问题

前提: Springboot整合Shiro后,启动项目,首次进入登录页面输入用户账号密码点击登录,却先执行AuthRealm类(继承AuthorizingRealm类)中的重写的方法doGetAuthenticationInfo(),token为登录的用户信息,该方法执行后页面报404。手动退回登录页面第二次登录输入用户账号密码点击登录, 此次流程没问题,首先执行login()方法,再次执行doGetAuthenticationInfo() 方法,token为登录用户的信息 原因一(这种原因是错误, 需要改代码) 在配置ShiroConfig的时候,没有开放登录接口。 如图1,图2 原因二(这种原因不是错误, 不需要改代码) 自己shiro配置了FormAuthenticationFilter 如图 默认拦截器FormAuthenticationFilter 只拦截post请求, 我们在登录的时候,如果用户名为username,密码为password,那么我们可以不用自己写登录的代码,FormAuthenticationFilter这个过滤器会自动帮我们进行登陆验证 这种情况下, 当登陆报错了才会进来login方法中来。若身份验证成功的话,会直接跳转到之前的访问地址或是successfulUrl去。因为在FormAuthenticationFilter内部都已经做完认证了。我们只需要在login方法中写上(判断异常类型)验证失败的逻辑就好, @RequestMapping(value = "login",method = RequestMethod.POST) public string loginSubmit(Param param) { String errorClassName = (String) ServletHelper.getRequestAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME); if(UnknownAccountException.class.getName().equals(errorClassName)) { ServletHelper.setRequestAttribute("error", "用户名/密码错误"); } else if(IncorrectCredentialsException.class.getName().equals(errorClassName)) { ServletHelper.setRequestAttribute("error", "用户名/密码错误"); } else if(errorClassName != null) { ServletHelper.setRequestAttribute("error", "未知错误:" + errorClassName); } // 登录失败后,跳回到login画面,让用户再次登录 return "admin/login"; } //DisabledAccountException (禁用的帐号) //LockedAccountException (锁定的帐号) //UnknownAccountException(错误的帐号) //ExcessiveAttemptsException(登录失败次数过多) //IncorrectCredentialsException (错误的凭证) //ExpiredCredentialsException (过期的凭证) …… 舒服…

Java去除字符串中的括号以及里面的内容

/** * * 功能描述: 去掉括号里面的内容 * * @param: [context] * @return: java.lang.String * @date: 2018/7/12 0012 11:18 */ private String ClearBracket(String context) { // String bracket = context.substring(context.indexOf("("), context.indexOf(")") + 1); // context = context.replace(bracket, ""); // // context.substring(context.lastIndexOf()) // // return context; // 修改原来的逻辑,防止右括号出现在左括号前面的位置 int head = context.indexOf('('); // 标记第一个使用左括号的位置 if (head == -1) { return context; // 如果context中不存在括号,什么也不做,直接跑到函数底端返回初值str } else { int next = head + 1; // 从head+1起检查每个字符 int count = 1; // 记录括号情况 do { if (context.

霍夫曼编码(C++ 优先队列)

霍夫曼编码 一般采用前缀编码 -- -- 对字符集进行编码时,要求字符集中任一字符的编码都不是其它字符的编码的前缀,这种编码称为前缀(编)码。 算法思想: 构造哈夫曼树非常简单,将所有的节点放到一个队列中,用一个节点替换两个频率最低的节点,新节点的频率就是这两个节点的频率之和。这样, 新节点就是两个被替换节点的父节点了。如此循环,直到队列中只剩一个节点(树根)。 其实这就是一个贪心策略,属于贪心算法的典型应用。 例子: 我们直接来看示例,如果我们需要来压缩下面的字符串: “beep boop beer!” 首先,我们先计算出每个字符出现的次数,我们得到下面这样一张表 : 字符次数‘b’3‘e’4‘p’2‘ ‘2‘o’2‘r’1‘!’1 然后,我把把这些东西放到Priority Queue中(用出现的次数据当 priority),我们可以看到,Priority Queue 是以Prioirry排序一个数组,如果Priority一样,会使用出现的次序排序:下面是我们得到的Priority Queue: 接下来就是我们的算法——把这个Priority Queue 转成二叉树。我们始终从queue的头取两个元素来构造一个二叉树(第一个元素是左结点,第二个是右结点),并把这两个元素的priority相加,并放回Priority中(再次注意,这里的Priority就是字符出现的次数),然后,我们得到下面的数据图表: 同样,我们再把前两个取出来,形成一个Priority为2+2=4的结点,然后再放回Priority Queue中 : 继续我们的算法(我们可以看到,这是一种自底向上的建树的过程): 最终我们会得到下面这样一棵二叉树: 此时,我们把这个树的左支编码为0,右支编码为1,这样我们就可以遍历这棵树得到字符的编码,比如:‘b’的编码是 00,’p’的编码是101, ‘r’的编码是1000。我们可以看到出现频率越多的会越在上层,编码也越短,出现频率越少的就越在下层,编码也越长。 最终我们可以得到下面这张编码表: 字符编码‘b’00‘e’11‘p’101‘ ‘011‘o’010‘r’1000‘!’1001 这里需要注意一点,当我们encode的时候,我们是按“bit”来encode,decode也是通过bit来完成,比如,如果我们有这样的bitset “1011110111″ 那么其解码后就是 “pepe”。所以,我们需要通过这个二叉树建立我们Huffman编码和解码的字典表。 这里需要注意的一点是,我们的Huffman对各个字符的编码是不会冲突的,也就是说,不会存在某一个编码是另一个编码的前缀,不然的话就会大问题了。因为encode后的编码是没有分隔符的。 于是,对于我们的原始字符串 beep boop beer! 其对就能的二进制为 : 0110 0010 0110 0101 0110 0101 0111 0000 0010 0000 0110 0010 0110 1111 0110 1111 0111 0000 0010 0000 0110 0010 0110 0101 0110 0101 0111 0010 0010 0001

OpenCv-C++-ORB特征检测与匹配

图像的特征点可以简单的理解为图像中比较显著显著的点,如轮廓点,较暗区域中的亮点,较亮区域中的暗点等。 ORB的全称是ORiented Brief,采用FAST(features from accelerated segment test)算法来检测特征点。 与Brisk,AKAZE类似,ORB也分两部分,即特征点提取和特征点描述。特征提取是由FAST(Features from Accelerated Segment Test)算法发展来的,它基于特征点周围的图像灰度值,检测候选特征点周围一圈的像素值,如果候选点周围领域内有足够多的像素点与该候选点的灰度值差别够大,则认为该候选点为一个特征点。而特征点描述是根据BRIEF(Binary Robust Independent Elementary Features)特征描述算法改进的。 将FAST特征点的检测方法与BRIEF特征描述子结合起来,并在它们原来的基础上做了改进与优化。据说ORB算法的速度是sift的100倍,是surf的10倍。 ORB算法是为解决BRIEF的缺陷而改进的,主要解决两个缺点:噪声敏感、旋转不变性。 关于具体的理论部分可以参考下面两篇文章: 参考文章:https://blog.csdn.net/gaotihong/article/details/78712017 参考文章:https://blog.csdn.net/guoyunfei20/article/details/78792770 代码部分: #include<opencv2/opencv.hpp> #include<iostream> #include<math.h> using namespace cv; using namespace std; Mat img1, img2; void ORB_demo(int, void*); int main(int argc, char** argv) { img1 = imread("D:/test/box.png"); img2 = imread("D:/test/box_in_scene.png"); if (!img1.data|| !img2.data) { cout << "图片未找到!" << endl; return -1; } namedWindow("ORB_demo",CV_WINDOW_AUTOSIZE); ORB_demo(0,0); imshow("input image of box",img1); imshow("input image of box_in_scene"

FPGA实战--等精度频率测量

首先放置效果图: 本次试验中采用的是等精度测频率,等精度测频的原理是产生一个1s的高电平,在高电平中对被测方波进行计数,所测得数字即该波形频率。具体等精度测量原理请参考:http://www.elecfans.com/d/591858.html 注意点:在1s高电平上升沿时,被测信号也需要是上升沿,才能进行准确计数,代码相对简单 本次实验功能,对信号测频,将测得频率以二进制32位通过uart发送给pc,对于pc发送得数据,将复制返回。下面将主要代码贴上: 顶层文件:Fre_measure.v module Fre_measure( input clk, input rst_n, input clk_measure, input uart_rx, output uart_tx ); wire[31:0] fre_cnt; Time_1s time_1s( .clk (clk ), .rst_n (rst_n ), .flag_1s (flag_1s ) ); dff1 dff_1( .clk_measure (clk_measure ), .flag_1s (flag_1s ), .clk_match (clk_match ) ); Fre_cnt fre_cnt1( .clk_measure (clk_measure ), .rst_n (rst_n ), .clk_match (clk_match ), .fre_cnt (fre_cnt ) ); uart_test uart_test1( .clk (clk ), .rst_n (rst_n ), .uart_rx (uart_rx ), .

node-rsa 解密

node-rsa 公钥解密 const NodeRSA = require('node-rsa'); const key = new NodeRSA('-----BEGIN PUBLIC KEY-----\n'+ ........... '-----END PUBLIC KEY-----'); const token = "token"; const decrypted = key.decryptPublic(token, 'utf8'); console.log('decrypted: ', decrypted); 如果遇到解密异常,例如公钥head是'-----BEGIN RSA PRIVATE KEY-----\n'+........'-----END RSA PRIVATE KEY-----': /Users/admin/Desktop/code/node_modules/_asn1@0.2.3@asn1/lib/ber/reader.js:168 throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + ^ InvalidAsn1Error: Expected 0x2: got 0x30 at newInvalidAsn1Error (/Users/yangxiaofei/Desktop/mycode/koa-demos/node_modules/_asn1@0.2.3@asn1/lib/ber/errors.js:7:13) at Reader.readString (/Users/yangxiaofei/Desktop/mycode/koa-demos/node_modules/_asn1@0.2.3@asn1/lib/ber/reader.js:168:11) at Object.privateImport (/Users/yangxiaofei/Desktop/mycode/koa-demos/node_modules/_node-rsa@1.0.1@node-rsa/src/formats/pkcs1.js:64:16) at Object.autoImport (/Users/yangxiaofei/Desktop/mycode/koa-demos/node_modules/_node-rsa@1.0.1@node-rsa/src/formats/pkcs1.js:132:28) at Object.detectAndImport (/Users/yangxiaofei/Desktop/mycode/koa-demos/node_modules/_node-rsa@1.0.1@node-rsa/src/formats/formats.js:54:103) at NodeRSA.module.exports.NodeRSA.importKey (/Users/yangxiaofei/Desktop/mycode/koa-demos/node_modules/_node-rsa@1.0.1@node-rsa/src/NodeRSA.js:183:22) at new NodeRSA (/Users/yangxiaofei/Desktop/mycode/koa-demos/node_modules/_node-rsa@1.