搜索词>>K520 耗时0.0030
  • 康佳 K520 KONKA K520固态硬盘SSD 测评

    概述本文主要对康佳(KONKA )最新推出的K520 500G版固态硬盘进行使用使用简单测评概述本文主要对康佳(KONKA )最新推出的K520 500G版固态硬盘进行使用使用简单测评。本文包括以下内容:康佳k520 固态硬盘测评环境说明康佳k520 固态硬盘开箱康佳k520 固态硬盘实际使用测评  K520测评环境 笔记本一台,配置:T9固态一枚;I7 4702MQ16G 内存sata3接入康佳k520康佳K520开箱  ​康佳K520 盒子正面  ​康佳K520盒子背面   ​康佳K520全家福  康佳K520实际使用测评 首先说说这款固态硬盘再AS 软件上的测试,测试得分一般看到的都是800分左右,从分数来看不错。本文的主要目的是实际使用测评。首先,空盘写入文件,速度波动如下: ​康佳 K520 空盘写入测试操作说明:硬盘格式化为NTFS格式,空盘无任何内容;从另一个固态硬盘复制几十个 1个多G文件,文件类型均为zip压缩包。内容是软件安装程序。从空盘的写入来看,再300+到400之间还是毕竟稳定的,赞一个​就空盘写入来看,康佳的这款K520已经能达到和闪迪入门款/东芝入门款的写入性能了,不错不错。​由于个人使用,500G很容易就用到一半,各类型的固态当容量到一定程度都有不同程度的降速,三星 东芝 这些旗舰产品也不例外,只是他们的好产品有些,降速不明显,中端和入门降速还是明细的。接下来就进行了康佳K520 在写入220G左右后开始复制写入测试,结果如下:​半盘容量后写入测试写入内容为1G左右压缩包。从上图可以明显感觉到降速。可能你觉得一个文件复制有偶然性,那么下面的100+ 1G压缩包给你解除偶然性:​100+ 1Gzip文件写入测试  ​写入性能 注意:同样的文件,我在T9 固态能达到300左右稳定200+以上。仅供大家参考​K520实际使用测评总结硬盘使用为主,软件测试分数只是一个参考,请勿盲目;空盘写入速度比较惊人,快要像一线品牌靠齐了,比较康佳才开始搞这个,这点还是不错的;对于半盘后的降速,我觉得康佳还需努力;本次618价格还算便宜,是个亮点299/500G。应该是最便宜的单G/¥了
  • i5 7600k攒机/装机配置参考方案

    i5 7600k七代Intel酷睿处理器,七代I5系列中最强处理器装机配置参考方案i5 6700k七代Intel酷睿处理器,七代I5系列中最强处理器装机配置参考方案<br /> <br /> 问题解答:<br /> 1.七代奔腾i5 7600k怎么样<br /> 答:在上一代的基础上提升了性能,功耗稍微降低了一些<br /> 2.i5 7600k配什么主板?<br /> 答:作为七代的新处理器,肯定是用七代的主板H270系列,B250系列,Z270系列,由于带K一般起步B250系列,推荐Z270系列<br /> 3.i5 7600k配什么显卡?<br /> 答:GTX1060系列显卡,RX480系列显卡<br />   <table class="table table-bordered table-hover" border="1" cellpadding="1" cellspacing="1"> <tbody> <tr> <td>名称</td> <td>型号</td> <td>备注</td> <td> </td> </tr> <tr> <td>CPU处理器</td> <td>I5 7600K</td> <td>LGA1151/3.8 GHz/6MB/91W/HD Graphics 630</td> <td> </td> </tr> <tr> <td>CPU FAN</td> <td>九州风神(DEEPCOOL) 玄冰400 CPU散热器</td> <td> </td> <td> </td> </tr> <tr> <td>GPU显卡</td> <td>微星 MSI GTX 1060 GAMING X 6G</td> <td>GDDR5 192BIT PCI-E 3.0 显卡</td> <td> </td> </tr> <tr> <td>主板  </td> <td>微星(MSI)Z270M MORTAR主板</td> <td> </td> <td> </td> </tr> <tr> <td>内存</td> <td>金士顿(Kingston)骇客神条 Fury系列 DDR4 2400 8G/16G</td> <td>8G或者16G根据个人需求</td> <td> </td> </tr> <tr> <td>电源</td> <td>振华(SUPER FLOWER)额定450W 冰山金蝶450战斗版 电源</td> <td> </td> <td> </td> </tr> <tr> <td>硬盘</td> <td>西部数据(WD)蓝盘 1TB</td> <td> </td> <td> </td> </tr> <tr> <td>机箱</td> <td>Tt(Thermaltake) 启航者S3</td> <td> </td> <td> </td> </tr> <tr> <td colspan="3" rowspan="1">由于硬件价格波动较大,暂未提供参考价格</td> <td> </td> </tr> </tbody> </table> 以上配置仅供参考<br /> 一般游戏全特效,大型游戏中高画质无压力。<br /> 附录机箱参考图:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="机箱" src="/assist/images/blog/b802219c-c2d1-4093-b518-ee6e0d4ce12f.jpg" />
  • JVM调优总结篇(一)

    JVM调优总结篇(一),这里主要搬运了csdn大神得总结。收藏以后可能会用到<h2><strong>1.堆大小设置</strong></h2> JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。<br /> <strong>典型设置:</strong> <ul> <li>java <strong>-Xmx3550m -Xms3550m -Xmn2g</strong> <strong>-Xss128k<br /> -</strong><strong>Xmx3550m</strong>:设置JVM最大可用内存为3550M。<br /> <strong>-Xms3550m</strong>:设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。<br /> <strong>-Xmn2g</strong>:设置年轻代大小为2G。<strong>整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小</strong>。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。<br /> <strong>-Xss128k</strong>:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。</li> <li>java -Xmx3550m -Xms3550m -Xss128k <strong>-XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0<br /> -XX:NewRatio=4</strong>:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5<br /> <strong>-XX:SurvivorRatio=4</strong>:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6<br /> <strong>-XX:MaxPermSize=16m</strong>:设置持久代大小为16m。<br /> <strong>-XX:MaxTenuringThreshold=0</strong>:设置垃圾最大年龄。<strong>如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代</strong>。对于年老代比较多的应用,可以提高效率。<strong>如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间</strong>,增加在年轻代即被回收的概论。</li> </ul> <h2><strong>2.回收器选择</strong></h2> JVM给了三种选择:<strong>串行收集器、并行收集器、并发收集器</strong>,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器。默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数。JDK5.0以后,JVM会根据当前<a href="http://java.sun.com/j2se/1.5.0/docs/guide/vm/server-class.html" rel="external nofollow" target="_blank">系统配置</a>进行判断。 <ol> <li><strong>吞吐量优先</strong>的并行收集器<br /> 如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等。<br /> <strong>典型配置</strong>: <ul> <li>java -Xmx3800m -Xms3800m -Xmn2g -Xss128k <strong>-XX:+UseParallelGC -XX:ParallelGCThreads=20<br /> -XX:+UseParallelGC</strong>:选择垃圾收集器为并行收集器。<strong>此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。<br /> -XX:ParallelGCThreads=20</strong>:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。</li> <li>java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 <strong>-XX:+UseParallelOldGC<br /> -XX:+UseParallelOldGC</strong>:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集。</li> <li>java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  <strong>-XX:MaxGCPauseMillis=100<br /> -XX:MaxGCPauseMillis=100</strong><strong>:</strong>设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。</li> <li>java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100 <strong>-XX:+UseAdaptiveSizePolicy<br /> -XX:+UseAdaptiveSizePolicy</strong>:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。</li> </ul> </li> <li><strong>响应时间优先</strong>的并发收集器<br /> 如上文所述,并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。<br /> <strong>典型配置</strong>: <ul> <li>java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 <strong>-XX:+UseConcMarkSweepGC -XX:+UseParNewGC</strong><br /> <strong>-XX:+UseConcMarkSweepGC</strong>:设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。<br /> <strong>-XX:+UseParNewGC</strong>:设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。</li> <li>java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC <strong>-XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection</strong><br /> <strong>-XX:CMSFullGCsBeforeCompaction</strong>:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。<br /> <strong>-XX:+UseCMSCompactAtFullCollection</strong>:打开对年老代的压缩。可能会影响性能,但是可以消除碎片</li> </ul> </li> </ol> <h2><strong>3.辅助信息</strong></h2> JVM提供了大量命令行参数,打印信息,供调试使用。主要有以下一些: <ul> <li><strong>-XX:+PrintGC</strong><br /> 输出形式<strong>:[GC 118250K->113543K(130112K), 0.0094143 secs]</strong> <p><strong>                [Full GC 121376K->10414K(130112K), 0.0650971 secs]</strong></p> </li> <li><strong>-XX:+PrintGCDetails</strong><br /> 输出形式<strong>:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]</strong> <p><strong>                [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]</strong></p> </li> <li><strong>-XX:+PrintGCTimeStamps</strong> -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用<br /> 输出形式:<strong>11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]</strong></li> <li><strong>-XX:+PrintGCApplicationConcurrentTime:</strong>打印每次垃圾回收前,程序未中断的执行时间。可与上面混合使用<br /> 输出形式:<strong>Application time: 0.5291524 seconds</strong></li> <li><strong>-XX:+PrintGCApplicationStoppedTime</strong>:打印垃圾回收期间程序暂停的时间。可与上面混合使用<br /> 输出形式:<strong>Total time for which application threads were stopped: 0.0468229 seconds</strong></li> <li><strong>-XX:PrintHeapAtGC</strong>:打印GC前后的详细堆栈信息<br /> 输出形式:<br /> 34.702: [GC {Heap before gc invocations=7:<br />  def new generation   total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)<br /> <strong>eden space 49152K,  99% used</strong> [0x1ebd0000, 0x21bce430, 0x21bd0000)<br /> <strong>from space 6144K,  55% used</strong> [0x221d0000, 0x22527e10, 0x227d0000)<br />   to   space 6144K,   0% used [0x21bd0000, 0x21bd0000, 0x221d0000)<br />  tenured generation   total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)<br /> <strong>the space 69632K,   3% used</strong> [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)<br />  compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)<br />    the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)<br />     ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)<br />     rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)<br /> 34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)<strong>Heap after gc invocations=8:</strong><br />  def new generation   total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)<br /> <strong>eden space 49152K,   0% used</strong> [0x1ebd0000, 0x1ebd0000, 0x21bd0000)<br />   from space 6144K,  55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)<br />   to   space 6144K,   0% used [0x221d0000, 0x221d0000, 0x227d0000)<br />  tenured generation   total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)<br /> <strong>the space 69632K,   4% used </strong>[0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)<br />  compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)<br />    the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)<br />     ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)<br />     rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)<br /> }<br /> , 0.0757599 secs]</li> <li><strong>-Xloggc:filename</strong>:与上面几个配合使用,把相关日志信息记录到文件以便分析。</li> </ul> <h2><strong>4.常见配置汇总</strong></h2> <ol> <li>堆设置 <ul> <li><strong>-Xms</strong>:初始堆大小</li> <li><strong>-Xmx</strong>:最大堆大小</li> <li><strong>-XX:NewSize=n</strong>:设置年轻代大小</li> <li><strong>-XX:NewRatio=n:</strong>设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4</li> <li><strong>-XX:SurvivorRatio=n</strong>:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5</li> <li><strong>-XX:MaxPermSize=n</strong>:设置持久代大小</li> </ul> </li> <li>收集器设置 <ul> <li><strong>-XX:+UseSerialGC</strong>:设置串行收集器</li> <li><strong>-XX:+UseParallelGC</strong>:设置并行收集器</li> <li><strong>-XX:+UseParalledlOldGC</strong>:设置并行年老代收集器</li> <li><strong>-XX:+UseConcMarkSweepGC</strong>:设置并发收集器</li> </ul> </li> <li>垃圾回收统计信息 <ul> <li><strong>-XX:+PrintGC</strong></li> <li><strong>-XX:+PrintGCDetails</strong></li> <li><strong>-XX:+PrintGCTimeStamps</strong></li> <li><strong>-Xloggc:filename</strong></li> </ul> </li> <li>并行收集器设置 <ul> <li><strong>-XX:ParallelGCThreads=n</strong>:设置并行收集器收集时使用的CPU数。并行收集线程数。</li> <li><strong>-XX:MaxGCPauseMillis=n</strong>:设置并行收集最大暂停时间</li> <li><strong>-XX:GCTimeRatio=n</strong>:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)</li> </ul> </li> <li>并发收集器设置 <ul> <li><strong>-XX:+CMSIncrementalMode</strong>:设置为增量模式。适用于单CPU情况。</li> <li><strong>-XX:ParallelGCThreads=n</strong>:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。</li> </ul> </li> </ol> <p> </p> <h2><strong>5、调优总结</strong></h2> <ol> <li><strong>年轻代大小选择</strong> <ul> <li><strong>响应时间优先的应用</strong>:<strong>尽可能设大,直到接近系统的最低响应时间限制</strong>(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。</li> <li><strong>吞吐量优先的应用</strong>:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。</li> </ul> </li> <li><strong>年老代大小选择</strong> <ul> <li><strong>响应时间优先的应用</strong>:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑<strong>并发会话率</strong>和<strong>会话持续时间</strong>等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得: <ul> <li>并发垃圾收集信息</li> <li>持久代并发收集次数</li> <li>传统GC信息</li> <li>花在年轻代和年老代回收上的时间比例</li> </ul> 减少年轻代和年老代花费的时间,一般会提高应用的效率</li> <li><strong>吞吐量优先的应用</strong>:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。</li> </ul> </li> <li><strong>较小堆引起的碎片问题</strong><br /> 因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置: <ul> <li><strong>-XX:+UseCMSCompactAtFullCollection</strong>:使用并发收集器时,开启对年老代的压缩。</li> <li><strong>-XX:CMSFullGCsBeforeCompaction=0</strong>:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩</li> </ul> </li> </ol>
  • RTX 2070/RTX 2080 测评

    RTX 2070/RTX 2080 测评,RTX 2070/RTX 2080跑分怎么样?RTX 2070/RTX 2080游戏怎么样?一.RTX 2070/RTX 2080跑分用手机界“雷布斯”的话来说,不服咋先跑个分RTX 2070/RTRTX 2070/RTX 2080 测评,RTX 2070/RTX 2080跑分怎么样?RTX 2070/RTX 2080游戏怎么样?一.RTX 2070/RTX 2080跑分用手机界“雷布斯”的话来说,不服咋先跑个分RTX 2070/RTX 2080 3DMARK基准测试​RTX 2070/RTX 2080 3DMARK基准测试从跑分的角度来看RTX 2080 RTX 2070比上一代的GTX 2070/GTX 1070性能提升了30%左右。可以看到RTX 2070与上一代的GTX 1080分数比较接近了,通过一些电商平台可以看到他们价格也是相近了,本代的70系显卡提价颇高啊。二.RTX 2070/RTX 2080游戏测评RTX 2070/RTX 2080《奇异小队》1080P 测评​RTX 2070/RTX 2080《奇异小队》1080P 测评RTX 2070/RTX 2080《奇异小队》4K 测评​RTX 2070/RTX 2080《奇异小队》4K 测评RTX 2070/RTX 2080《古墓丽影:崛起》1080P 测评​RTX 2070/RTX 2080《古墓丽影:崛起》1080P 测评  RTX 2070/RTX 2080《古墓丽影:崛起》4k测评​RTX 2070/RTX 2080《古墓丽影:崛起》4k测评RTX 2070/RTX 2080《古墓丽影:暗影》1080P测评​RTX 2070/RTX 2080《古墓丽影:暗影》1080P测评  RTX 2070/RTX 2080《古墓丽影:暗影》4K测评​RTX 2070/RTX 2080《古墓丽影:暗影》4K测评  RTX 2070/RTX 2080《全境封锁》1080P测评​RTX 2070/RTX 2080《全境封锁》1080P测评  RTX 2070/RTX 2080《全境封锁》4K测评​RTX 2070/RTX 2080《全境封锁》4K测评RTX 2070/RTX 2080《奇点灰烬》1080P 测评​RTX 2070/RTX 2080《奇点灰烬》1080P 测评  RTX 2070/RTX 2080《奇点灰烬》4K测评​RTX 2070/RTX 2080《奇点灰烬》4K测评游戏体验上来说上面的游戏两款新卡都有所提升。和跑分结果的性能相符合。至于选购啥显卡,还是看自己的预算咯。虽然说RTX 2070 RTX 2080支持光线追踪,但是目前支持的游戏颇少,估计后续有所增多吧。按照买新不买旧的原则大家随意上车吧。​
  • js 日期格式化_JavaScript date format

    这里讲解的是一种通过扩展原生JS的方式进行日期格式化​首先,在需要使用的地方添加以下代码Date.prototype.format = function(fmt) { var o = { "M+" : th这里讲解的是一种通过扩展原生JS的方式进行日期格式化​首先,在需要使用的地方添加以下代码Date.prototype.format = function(fmt) { var o = { "M+" : this.getMonth()+1, //月份 "d+" : this.getDate(), //日 "h+" : this.getHours(), //小时 "m+" : this.getMinutes(), //分 "s+" : this.getSeconds(), //秒 "q+" : Math.floor((this.getMonth()+3)/3), //季度 "S" : this.getMilliseconds() //毫秒 }; if(/(y+)/.test(fmt)) { fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); } for(var k in o) { if(new RegExp("("+ k +")").test(fmt)){ fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); } } return fmt; } 以上代码推荐放在公共js里面,全局引用,可在项目中任意地方使用格式化。date 格式化使用例子:var time1 = new Date().format("yyyy-MM-dd hh:mm:ss"); console.log(time1);搞定
  • 2018 9月CPU天梯图

    一年一度的双十一又到了,今年打算换个电脑么?给你CPU天梯参考图哟.其中包括I5 8600K I7 8700K I9 7980XE等CPU2019 10月CPU天梯图​2019 10月CPU天梯图
  • 全新七代酷睿I3/I5/I7系列参数信息对比

    全新七代酷睿I3/I5/I7系列参数信息对比全新七代酷睿I3/I5/I7系列参数信息对比<br /> I3系列:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="" src="/assist/images/blog/e533fb13-344c-4150-9ea9-44513067c292.jpg" /><br /> I3 7100T/I3 7300T/I3 7100/I3 7300/I3 7320  <br /> 七代酷睿I3系列总共公布了五款型号的参数,其中带T的为节能版本,价格也比普通的地适合做一些入门办公之类用途电脑使用。<br /> <br /> I5系列:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="I5" src="/assist/images/blog/baccb573-b4dd-4dfc-8201-69be2e47f8b0.jpg" /><br /> I5 7400T/I5 7500T/I5 7600T/I5 7400/I5 7500/I5 7600/I5 7600K<br /> I5本代中,I5 7600K是最强的一枚,频率最高到4.2GHZ当然发烧友应该还能发挥更多的性能。<br /> <br /> 重量级I7:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="I7" src="/assist/images/blog/1ec979b2-877d-46b3-9c4a-e0abd9845993.jpg" /><br /> I7 7700T/I7 7700/I7 7700K<br /> 这里的I7是普通级别的I7性能得到了提升,能耗得到了控制。连最高的I7 7700K 最大散热功耗才91W<br />  
  • apache ab 工具进行web压力测试

    apache ab 工具进行web压力测试命令: <pre> <code class="language-html">#ab -r -n 1000 -c 100 -k http://www.your.com/</code></pre> <pre> <code class="language-html">#ab -r -t 600 -c 1000 -k http://www.your.com/</code></pre> <br /> -r 遇到错误继续执行<br /> -n 请求总数量<br /> -c 并发数量<br /> -t 持续时间(秒)<br /> <br /> <br /> https://www.cnblogs.com/dragonflyer/p/6137514.html
  • spring boot shiro redis整合基于角色和权限的安全管理-Java编程

    Java编程之spring boot shiro redis整合基于角色和权限的安全管理,Java编程,spring boot,shiro,权限控制<h2>一、概述</h2>   本博客主要讲解spring boot整合Apache的shiro框架,实现基于角色的安全访问控制或者基于权限的访问安全控制,其中还使用到分布式缓存redis进行用户认证信息的缓存,减少数据库查询的开销。Apache shiro与spring security的作用几乎一样都是简化了Java程序的权限控制开发。 <h2>二、项目</h2> <h3>2.1首先是通过eclipse创建一个最新的spring boot项目,并添加以下依赖:</h3> <strong>pom.xml</strong> <pre> <code class="language-xml"><?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.xqlee.project.demo.shiro</groupId> <artifactId>demo-springboot-shiro</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-springboot-shiro-hello</name> <description>demo-springboot-shiro-hello</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- shiro权限控制框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.3.2</version> </dependency> <!--缓存暂时用简单的 https://mvnrepository.com/artifact/org.ehcache/ehcache --> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib --> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency> <!-- redis缓存 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> </code></pre> <h3>2.2配置redis</h3> application.properties文件中添加配置: <pre> <code>####################Redis 配置信息 ########################## # Redis数据库分片索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=10.1.1.2 # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) spring.redis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=0 #测试redis的缓存日志 logging.level.net.xqlee.project.demo.shiro.config.shiro.cache=DEBUG</code></pre> <br /> Java config的redis配置<br /> <strong>RedisConfig</strong> <pre> <code class="language-java">package net.xqlee.project.demo.shiro.config.redis; import java.lang.reflect.Method; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; @Configuration @EnableCaching // 继承CachingConfigurerSupport并重写方法,配合该注解实现spring缓存框架的启用 public class RedisConfig extends CachingConfigurerSupport { /** 载入通过配置文件配置的连接工场 **/ @Autowired RedisConnectionFactory redisConnectionFactory; @SuppressWarnings("rawtypes") @Autowired RedisTemplate redisTemplate; @Bean RedisTemplate<String, Object> objRedisTemplate() { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } /* * (non-Javadoc) * * @see org.springframework.cache.annotation.CachingConfigurerSupport# * cacheManager() */ @Bean // 必须添加此注解 @Override public CacheManager cacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate); // 设置缓存过期时间 // redisCacheManager.setDefaultExpiration(60);//秒 return redisCacheManager; } /** * 重写缓存的key生成策略,可根据自身业务需要进行自己的配置生成条件 * * @see org.springframework.cache.annotation.CachingConfigurerSupport# * keyGenerator() */ @Bean // 必须项 @Override public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); } }; } } </code></pre> <h3><br /> 2.3创建shiro需要的 redis缓存器和缓存管理实现类</h3> 首先是缓存器cache的实现<br /> RedisCache.java <pre> <code class="language-java">package net.xqlee.project.demo.shiro.config.shiro.cache; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisTemplate; /** * Redis的Shiro缓存对象实现 * * @author xq * * @param <K> * @param <V> */ public class RedisCache<K, V> implements Cache<K, V> { private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); private RedisTemplate<K, V> redisTemplate; private final static String PREFIX = "shiro-cache:"; private String cacheKey; private long globExpire = 30; @SuppressWarnings({ "rawtypes", "unchecked" }) public RedisCache(final String name, final RedisTemplate redisTemplate) { this.cacheKey = PREFIX + name + ":"; this.redisTemplate = redisTemplate; } @Override public V get(K key) throws CacheException { logger.debug("Shiro从缓存中获取数据KEY值["+key+"]"); redisTemplate.boundValueOps(getCacheKey(key)).expire(globExpire, TimeUnit.MINUTES); return redisTemplate.boundValueOps(getCacheKey(key)).get(); } @Override public V put(K key, V value) throws CacheException { V old = get(key); redisTemplate.boundValueOps(getCacheKey(key)).set(value); return old; } @Override public V remove(K key) throws CacheException { V old = get(key); redisTemplate.delete(getCacheKey(key)); return old; } @Override public void clear() throws CacheException { redisTemplate.delete(keys()); } @Override public int size() { return keys().size(); } @Override public Set<K> keys() { return redisTemplate.keys(getCacheKey("*")); } @Override public Collection<V> values() { Set<K> set = keys(); List<V> list = new ArrayList<>(); for (K s : set) { list.add(get(s)); } return list; } @SuppressWarnings("unchecked") private K getCacheKey(Object k) { return (K) (this.cacheKey + k); } } </code></pre> 还有缓存管理器:<br /> <strong>RedisCacheManager.java</strong> <pre> <code class="language-java">package net.xqlee.project.demo.shiro.config.shiro.cache; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.apache.shiro.cache.CacheManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; /** * Redis的Shiro缓存管理器实现 * * @author xq * */ public class RedisCacheManager implements CacheManager { @Autowired private RedisTemplate<String, Object> redisTemplate; @Override public <K, V> Cache<K, V> getCache(String name) throws CacheException { return new RedisCache<>(name, redisTemplate); } } </code></pre> <h3>2.4自定义一个shiro的realm实现</h3> <h3>创建realm之前需要编写一个模拟数据库查询的用户业务处理类,提供给上面的自定义realm使用</h3> 简单的用户登录对象: <pre> <code class="language-java">package net.xqlee.project.demo.shiro.pojo; import java.util.Date; import java.util.List; /** * 用户信息 * * @author xqlee * */ public class LoginAccount { /** 用户名 */ String loginName; List<String> roles;// 测试用 List<String> permissions;// 测试用直接放用户登录对象里面 /** 用户密码 **/ String password; boolean enabled; Date createDate; boolean isExpired; public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public boolean isExpired() { return isExpired; } public void setExpired(boolean isExpired) { this.isExpired = isExpired; } public List<String> getRoles() { return roles; } public void setRoles(List<String> roles) { this.roles = roles; } public List<String> getPermissions() { return permissions; } public void setPermissions(List<String> permissions) { this.permissions = permissions; } } </code></pre> 用户模拟业务处理 <pre> <code class="language-java">package net.xqlee.project.demo.shiro.service; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.stereotype.Component; import net.xqlee.project.demo.shiro.pojo.LoginAccount; /** * 用户业务服务类 * * @author xqlee * */ @Component("userService") public class UserService { /** 由于重点不在数据库,这里需要使用数据库的地方全部用map代替 **/ /** 用户信息 **/ static Map<String, LoginAccount> users = new HashMap<>(); static { // 创建一个用户 LoginAccount account = new LoginAccount(); account.setLoginName("leftso"); account.setPassword("123456"); account.setEnabled(true); account.setExpired(false); // 角色添加 List<String> roles = new ArrayList<>(); roles.add("ROLE_USER"); account.setRoles(roles); List<String> permissions = new ArrayList<>(); permissions.add("query"); permissions.add("delete"); account.setPermissions(permissions); users.put(account.getLoginName(), account); // 创建一个用户 LoginAccount admin = new LoginAccount(); admin.setLoginName("admin"); admin.setPassword("123456"); admin.setEnabled(true); admin.setExpired(false); // 角色添加 roles = new ArrayList<>(); roles.add("ROLE_ADMIN"); admin.setRoles(roles); permissions = new ArrayList<>(); permissions.add("query"); permissions.add("delete"); admin.setPermissions(permissions); users.put("admin", admin); } /** * 通过用户名获取用户权限集合 * * @param loginName * 用户名 * @return 用户的权限集合 */ public List<String> getPermissionsByLoginName(String loginName) { if (users.containsKey(loginName)) { return users.get(loginName).getPermissions(); } return new ArrayList<>(); } /** * 通过用户名获取用户信息 * * @param loginName * 用户名 * @return 用户信息 */ public LoginAccount getLoginAccountByLoginName(String loginName) { if (users.containsKey(loginName)) { return users.get(loginName); } return null; } } </code></pre>   <pre> <code class="language-java">package net.xqlee.project.demo.shiro.config.shiro; import java.util.List; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import net.xqlee.project.demo.shiro.pojo.LoginAccount; import net.xqlee.project.demo.shiro.service.UserService; /** * 实现一个基于JDBC的Realm,继承AuthorizingRealm可以看见需要重写两个方法,doGetAuthorizationInfo和doGetAuthenticationInfo * * @author xqlee * */ @Component("JDBCShiroRealm") public class JDBCShiroRealm extends AuthorizingRealm { private static final Logger logger = LoggerFactory.getLogger(JDBCShiroRealm.class); /*** 用户业务处理类,用来查询数据库中用户相关信息 ***/ @Autowired UserService userService; /*** * 获取用户授权 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { logger.info("##################执行Shiro权限认证##################"); // 获取用户名 String loginName = (String) principalCollection.fromRealm(getName()).iterator().next(); // 判断用户名是否存在 if (StringUtils.isEmpty(loginName)) { return null; } // 查询登录用户信息 LoginAccount account = userService.getLoginAccountByLoginName(loginName); if (account == null) { logger.warn("用户[" + loginName + "]信息不存在"); return null; } // 创建一个授权对象 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 进行权限设置 List<String> permissions = account.getPermissions(); if (permissions != null && !permissions.isEmpty()) { info.addStringPermissions(permissions); } // 角色设置 List<String> roles = account.getRoles(); if (roles != null) { info.addRoles(roles); } return info; } /** * 获取用户认证信息 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { logger.info("##################执行Shiro登陆认证##################"); UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; // 通过表单接收的用户名 String loginName = token.getUsername(); if (loginName != null && !"".equals(loginName)) { // 模拟数据库查询用户信息 LoginAccount account = userService.getLoginAccountByLoginName(loginName); if (account != null) { // 登陆的主要信息: 可以是一个实体类的对象, 但该实体类的对象一定是根据 token 的 username 查询得到的. Object principal = token.getPrincipal(); // 创建shiro的用户认证对象 // 注意该对象的密码将会传递至后续步骤与前面登陆的subject的密码进行比对。 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(principal, account.getPassword(), getName()); return authenticationInfo; } } return null; } } </code></pre> <h3><br /> <br /> 2.5shiro的核心配置文件</h3> <strong>ShiroConfig.java</strong> <pre> <code class="language-java">package net.xqlee.project.demo.shiro.config.shiro; import java.util.LinkedHashMap; import java.util.Map; import org.apache.shiro.SecurityUtils; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.cache.ehcache.EhCacheManager; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import net.xqlee.project.demo.shiro.config.shiro.cache.RedisCacheManager; /*** * shiro权限管理配置 * * @author xqlee * */ @Configuration public class ShiroConfig { /** * ehcache缓存方案<br/> * 简单的缓存,后续可更换为redis缓存,通过自己实现shiro的CacheManager接口和Cache接口 * * @return */ @Bean public CacheManager shiroEhCacheManager() { EhCacheManager cacheManager = new EhCacheManager(); cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); return cacheManager; } /** * redis缓存方案 * * @return */ @Bean public CacheManager shiroRedisCacheManager() { return new RedisCacheManager(); } /**** * 自定义Real * * @return */ @Bean public JDBCShiroRealm jdbcShiroRealm() { JDBCShiroRealm realm = new JDBCShiroRealm(); // 根据情况使用缓存器 realm.setCacheManager(shiroRedisCacheManager());//shiroEhCacheManager() return realm; } /*** * 安全管理配置 * * @return */ @Bean public SecurityManager defaultWebSecurityManager() { // DefaultSecurityManager defaultSecurityManager = new // DefaultSecurityManager(); DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 注意:!!!初始化成这个将会报错java.lang.IllegalArgumentException: // SessionContext must be an HTTP compatible // implementation.:模块化本地测试shiro的一些总结 // 配置 securityManager.setRealm(jdbcShiroRealm()); // 注意这里必须配置securityManager SecurityUtils.setSecurityManager(securityManager); // 根据情况选择缓存器 securityManager.setCacheManager(shiroRedisCacheManager());//shiroEhCacheManager() return securityManager; } /** * 配置shiro的拦截器链工厂,默认会拦截所有请求,并且不可配置 * * @return */ @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean(); // 配置安全管理(必须) filterFactoryBean.setSecurityManager(defaultWebSecurityManager()); // 配置登陆的地址 filterFactoryBean.setLoginUrl("/userNoLogin.do");// 未登录时候跳转URL,如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 filterFactoryBean.setSuccessUrl("/welcome.do");// 成功后欢迎页面 filterFactoryBean.setUnauthorizedUrl("/403.do");// 未认证页面 // 配置拦截地址和拦截器 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();// 必须使用LinkedHashMap,因为拦截有先后顺序 // authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问 filterChainDefinitionMap.put("/userNoLogin.do*", "anon");// 未登录跳转页面不设权限认证 filterChainDefinitionMap.put("/login.do*", "anon");// 登录接口不设置权限认真 filterChainDefinitionMap.put("/logout.do*", "anon");// 登出不需要认证 // 以下配置同样可以通过注解 // @RequiresPermissions("user:edit")来配置访问权限和角色注解@RequiresRoles(value={"ROLE_USER"})方式定义 // 权限配置示例,这里的配置理论来自数据库查询 filterChainDefinitionMap.put("/user/**", "roles[ROLE_USER],perms[query]");// /user/下面的需要ROLE_USER角色或者query权限才能访问 filterChainDefinitionMap.put("/admin/**", "perms[ROLE_ADMIN]");// /admin/下面的所有需要ROLE_ADMIN的角色才能访问 // 剩下的其他资源地址全部需要用户认证后才能访问 filterChainDefinitionMap.put("/**", "authc"); filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); // 全部配置 // anon org.apache.shiro.web.filter.authc.AnonymousFilter 匿名访问 // // authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter // 需要登录,不需要权限和角色可访问 // // authcBasic // org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter // // perms // org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter // 需要给定的权限值才能访问 // // port org.apache.shiro.web.filter.authz.PortFilter // // rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter // // roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter // 需要给定的角色才能访问 // // ssl org.apache.shiro.web.filter.authz.SslFilter // // user org.apache.shiro.web.filter.authc.UserFilter // // logout org.apache.shiro.web.filter.authc.LogoutFilter return filterFactoryBean; } } </code></pre> 上面配置中有两个缓存器可以选择,一个是简单的ehcache,一个是redis,大型项目推荐使用redis <h3><br /> 2.6编写一个测试的controller</h3> <pre> <code class="language-java">package net.xqlee.project.demo.shiro.controller; import javax.servlet.http.HttpServletResponse; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.ExcessiveAttemptsException; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.LockedAccountException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import net.sf.json.JSONObject; /** * 用户登录用 * * @author xqlee * */ @RestController public class LoginController { private static final Logger logger = LoggerFactory.getLogger(LoginController.class); /**** * 用户未登录 * * @return */ @GetMapping("userNoLogin.do") public Object noLogin() { JSONObject object = new JSONObject(); object.put("message", "用户未登录"); return object; } @GetMapping(value = "/login.do") public String login(String loginName, String password) { try { // 创建shiro需要的token UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginName, password.toCharArray()); usernamePasswordToken.setRememberMe(true);// 记住 try { SecurityUtils.getSubject().login(usernamePasswordToken); } catch (UnknownAccountException uae) { logger.info("对用户[" + loginName + "]进行登录验证..验证未通过,未知账户"); return "对用户[" + loginName + "]进行登录验证..验证未通过,未知账户"; } catch (IncorrectCredentialsException ice) { logger.info("对用户[" + loginName + "]进行登录验证..验证未通过,错误的凭证"); ice.printStackTrace(); return "对用户[" + loginName + "]进行登录验证..验证未通过,错误的凭证"; } catch (LockedAccountException lae) { logger.info("对用户[" + loginName + "]进行登录验证..验证未通过,账户已锁定"); return "对用户[" + loginName + "]进行登录验证..验证未通过,账户已锁定"; } catch (ExcessiveAttemptsException eae) { logger.info("对用户[" + loginName + "]进行登录验证..验证未通过,错误次数过多"); return "对用户[" + loginName + "]进行登录验证..验证未通过,错误次数过多"; } catch (AuthenticationException ae) { // 通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景 logger.info("对用户[" + loginName + "]进行登录验证..验证未通过,堆栈轨迹如下"); ae.printStackTrace(); return "用户名或密码不正确"; } return "Login Success!"; } catch (Exception e) { return "登陆时候发生异常," + e.getMessage(); } } @GetMapping("/user/hello.do") public String hello() { return "Hello User, From Server"; } @GetMapping("/admin/hello.do") public String helloAdmin() { return "Hello Admin, From Server"; } @GetMapping("/welcome.do") public String loginSuccess() { return "welcome"; } @GetMapping("/403.do") public Object error403(HttpServletResponse response) { response.setStatus(403); JSONObject object = new JSONObject(); object.put("message", "用户权限不够"); return object; } } </code></pre> <h3>2.7测试</h3> 1.通过spring bootapplication方式启动项目,项目默认监听在8080端口<br /> <br /> 首先访问需要权限的url  http://localhost:8080/user/hello.do<br /> <br /> <img srcset="" width="" size="" class="img-thumbnail" alt="访问需要权限的url" src="/assist/images/blog/9399b39fad254f35b9f4ec1d6ec9d671.jpg" /><br /> 可以看到返回的是用户未登录提示,也就是我们在controller中写的未登录时候调用的方法返回值。<br /> <br /> 现在我们先通过用户名leftso和密码123456进行登录  localhost:8080/login.do?loginName=leftso&password=123456<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="登录" src="/assist/images/blog/3281336d3f4844fd8164a2768271cbaa.png" /><br /> <br /> 可以看到登录成功,这个时候我们再次打开最初访问的:http://localhost:8080/user/hello.do<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="成功访问" src="/assist/images/blog/51efce91cb62475bbd70a0554b8b8323.png" /><br /> 可以看到这次我们成功访问了需要ROLE_USER角色的url,<br /> <br /> 现在用这个登录的信息访问需要ROLE_ADMIN权限的地址http://localhost:8080/admin/hello.do<br /> <br /> <img srcset="" width="" size="" class="img-thumbnail" alt="提示权限不足" src="/assist/images/blog/42e8ee00ac544ebebccb3f95fd157a5a.png" /><br /> 上面可以看到,无法访问,返回的提示是权限不足<br /> <br /> 切换为admin的用户登录,然后访问地址http://localhost:8080/admin/hello.do<br /> <br /> 首先是admin登录<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="admin登录" src="/assist/images/blog/a470702a46cd4f5d901c4689594df9d3.png" /><br /> 然后访问admin权限的地址<br /> <br /> <img srcset="" width="" size="" class="img-thumbnail" alt="admin资源访问成功" src="/assist/images/blog/e16a663b41db45fb887fddd5ede6f3a9.png" /><br /> 上面看到admin也对应的访问成功了。<br /> <br /> 并且,切回eclipse的控制台可以看到:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="redis" src="/assist/images/blog/df831fee0fb74c02aece3421c25b8949.png" /><br /> 我们的redis缓存也起作用了。<br /> <br /> 至此spring boot shiro redis的整合角色和权限控制讲解完毕。<br /> <br /> 留下思考:如何实现spring boot shiro的无状态认证呢?也就是当我们编写一个既要web前后端分离使用也同时需要满足app的接口需求。只能通过无状态的token实现。<br /> <br /> <a target="_blank" href="http://www.leftso.com/blog/593.html">spring boot shiro无状态化配置使用教程点击前往</a>
  • centos6.8切换yum源为国内阿里源

    1.备份已有的源 <pre> <code class="language-bash">#mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup</code></pre> 2.下载阿里yum源 <pre> <code class="language-bash">#wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo </code></pre> 下载中... <pre> <code class="language-bash">--2017-01-15 10:52:45-- http://mirrors.aliyun.com/repo/Centos-6.repo Resolving mirrors.aliyun.com... 112.124.140.210, 115.28.122.210 Connecting to mirrors.aliyun.com|112.124.140.210|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 2572 (2.5K) [application/octet-stream] Saving to: `/etc/yum.repos.d/CentOS-Base.repo' 100%[====================================================================================================================================================================================================================================>] 2,572 --.-K/s in 0s 2017-01-15 10:52:45 (226 MB/s) - `/etc/yum.repos.d/CentOS-Base.repo' saved [2572/2572]</code></pre> 3.刷新yum市场资源 <pre> <code class="language-bash">#yum clean all</code></pre> <pre> <code class="language-bash">[root@VM_66_92_centos ~]# yum clean all Loaded plugins: fastestmirror, security Cleaning repos: base epel extras updates Cleaning up Everything Cleaning up list of fastest mirrors</code></pre> <br /> 资源更新 <pre> <code> #yum makecache</code></pre> <br /> 这里会下载一些资源..需要点时间<br /> <br /> 更新完成后变完成yum源的切换<br /> <span style="color:#FF0000">注意<br /> 所有操作都需要root权限</span><br /> <br /> <br />