SpringBoot+Shiro+Jwt填坑-2
jwt介绍
转载自:一步步带你了解前后端分离利器之JWT - 徐刘根的博客 - CSDN博客
RESTful API认证方式一般来讲,对于RESTful API都会有认证(Authentication)和授权(Authorization)过程,保证API的安全性。
Authentication指的是确定这个用户的身份,Authorization是确定该用户拥有什么操作权限。
Basic Authentication这种方式是直接将用户名和密码放到Header中,使用Authorization: Basic Zm9vOmJhcg==,使用最简单但是最不安全。
TOKEN认证这种方式也是再HTTP头中,使用Authorization: Bearer <token>,使用最广泛的TOKEN是JWT,通过签名过的TOKEN。
OAuth2.0这种方式安全等级最高,但是也是最复杂的。如果不是大型API平台或者需要给第三方APP使用的,没必要整这么复杂。
一般项目中的RESTful API使用JWT来做认证就足够了
下面是JWT介绍
HTTP的无状态性HTTP 是无状态协议,它不对之 ...
Java设计模式-单例模式
对于系统中的某些类来说,只有一个实例很重要
模式动机对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。
如何保证一个类只有一个实例并且这个实例易于被访问呢?
定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象
一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。
单例模式(Singleton Pattern)单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。
要点
某个类只能有一个实例
它必须自行创建这个实例
它必须自行向整个系统提供这个实例
结构
(图源:设计模式从入门到放弃 - 单例模式 - jtahstu的博客)
分析单例模式的目的是保证一个类仅有一个实例,并提供一个访问它的全局访问点 ...
JDK8新特性之Lambda表达式的基本语法
个人感觉Lambda用于内部类即可,其他地方可能还会造成效率低下,难于debug
简介官方文档:Lambda Expressions (The Java™ Tutorials > Learning the Java Language > Classes and Objects)
Lambda表达式,也可称为闭包,它是推动 Java8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑
表达式格式在Java8语言中引入的一种新的语言元素和操作符,这个操作符为->,该操作符被称为Lambda操作符或箭头操作符,它将Lambda分为以下两个部分
左侧 : 指定Lambda表达式需要的参数列表
右侧 : 制定了Lambda体,是抽象方法的实现逻辑,也既Lambda表达式要执行的功能
表达式的语法格式如下:
123(parameters) -> expression或(parameters) ->{ statements; }
本质:作为接口 ...
synchronized保证线程安全
synchronized笔记
线程安全主要诱因
存在共享数据(也称临界资源)
存在多条线程共同操作共享数据
解决问题根本同一时刻有且只有一个线程在操作共享数据,其他线程必须等到该线程处理完数据后再对共享数据进行操作。所以可以引入互斥锁去解决问题
互斥锁
互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程的协调机制,这样在同一时间只有一个线程对需要同步的代码块(复合操作)进行访问。互斥性也称为操作的原子性。
可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作,从而引起不一致。
在 Java 中,关键字synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外一个重要的作用,synchronized可保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代Volatile功能 ...
Java线程的状态
线程的6种状态,sleep与wait的区别,notify与notifyAll的区别,yield,中断线程
线程的状态初识6种状态由jdk8中的java.lang.Thread.State可知,
线程有6个状态
NEW尚未启动的线程处于此状态。
RUNNABLE在Java虚拟机中执行的线程处于此状态。
BLOCKED被阻塞等待监视器锁定的线程处于此状态。
WAITING正在等待另一个线程执行特定动作的线程处于此状态。
TIMED_WAITING正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
TERMINATED已退出的线程处于此状态。
一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。
Thread.State继承关系:
public static enum Thread.State extends Enum
java.lang.Object
java.lang.Enum
java.lang.Thread.State
(图源:Java线程及线程池状态 - 时间朋友 - 博客园)
(图源:线程 ...
倍增求LCA
LCA—最近公共祖先
LCA所谓LCA,是当给定一个有根树T时,对于任意两个结点u、v,找到一个离根最远的结点x,使得x同时是u和v的祖先,x 便是u、v的最近公共祖先(原问题涵盖一般性的有根树,为了简化,多使用二叉树来讨论)。例如下面:
结点3和结点4的最近公共祖先是结点2,即LCA(3, 4)=2 。在此,需要注意到当两个结点在同一棵子树上的情况,如结点3和结点2的最近公共祖先为2,即 LCA(3,2)=2。同理:LCA(5,6)=4,LCA(6,10)=1。
求LCA的方法主要有:
倍增求LCA
ST-RMQ求LCA
Tarjan求LCA
前面两者都是在线算法,最后一个是离线算法
在线和离线可以简单的理解为对于所有的操作是否需要读入完毕。
在线的要求是可以不用先知道所有的操作(类似询问、修改),边读入边执行,类似“走一步,做一步”的思想。
离线则与在线相反,要求必须知道所有的操作,类似“记录所有步,回头再做”的思想,一般用Query[]记录所有操作
转自:在线和离线算法 - 简书
倍增求LCA倍增算法所谓倍增,就是按2的倍数来增大,也就是跳 1,2,4,8,16,3 ...
搭建NginxHttps本地测试环境
利用nginx搭建一个https本地可用的域名
环境利用到的工具:
mkcert—本地生成浏览器信任的本地 https 证书
Nginx
Docker(可选)
本篇教程利用的是docker nginx,安装版也一样的,差不多。
本地环境:
123本机:Arch Linux x86_64 5.2.2-arch1-1-ARCHDocker: Docker version 18.09.8-ce, build 0dd43dd87fNginx:stable-alpine
安装mkcert其他系统的安装方法可以看github上面的介绍,本次按照的是Arch系统的安装方法。
12sudo pacman -S nssyay -S mkcert
生成证书
生成CA(certificate authority,即证书颁发机构),运行下面的命令可以在~/.local/share/mkcert/生成rootCA.pem和rootCA-key.pema两个文件,这个命令只需运行一次,因为生成的CA可以反复使用;
使用mkcert -install命令即可
创建自签名证书,例如要为域名:hehe ...
Java多线程拾遗--start与run--Thread与Runnable
尝试从源码分析start与run的区别,Thread与Runnable的区别
start与run先来看两个程序
12345678910111213141516171819202122232425262728package indi.greenhat.thread;/** * @description: runable与start的区别 * @author: GreenHatHG * @create: 2019-07-23 09:02 **/public class Thread1 { private static void attack(){ System.out.println("attack"); System.out.println("Current Thread is: " + Thread.currentThread().getName()); } public static void main(String[] args) { Thr ...
dfs序
树的dfs
dfs序
这棵树的 DFS 序列就是 C 1 A E 7 H B 8 3 4 F 5 6 9 I G 2 D(按照左优先)
定义子树 x表示结点x及其所有的子孙结点,该序列有一个很重要的性质:每棵子树x在 DFS 序列中一定是连续的一段,结点x一定在这段的开头
1234567891011C 1[A E 7 H B 8 3 4 F]5 6 9 I G 2 D 子树AC 1 A[E 7 H B]8 3 4 F 5 6 9 I G 2 D 子树EC 1 A E 7 H B 8 3 4 F[5 6 9 I G 2 D] 子树5C 1 A E 7 H B 8 3 4 F 5[6 9]I G 2 D 子树6
这使得在子树上进行的修改、查询可以转化为区间修改、区间查询。结合树状数组 or 线段树食用均可
所以dfs序的作用是
相当于把树上的问题转化成了序列上的问题
辅以各种数据结构进行计算
比如ST表、树状数组、线段树
子树求和->区间求和
模板1234 ...
Java虚拟机笔记--垃圾回收
垃圾回收算法与 JVM 垃圾回收器
一览
对象被判定为垃圾的标准GC主要是回收Java堆中的对象,即此对象已经没有了价值,就是变成了“垃圾”,那么对象被判定为垃圾的标准是什么呢?——没有被其他对象引用。
判定对象是否为垃圾的算法引用计数算法主要是判断对象的引用数量
通过判断对象的引用数量来决定对象是否可以被回收
每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1
任何引用计数为0的对象实例都可以被当作垃圾收集
下面就是对一个引用计数的举例:
引用计数法有一个致命的缺陷,如下图,就是当两个对象相互引用时,这两个对象实际是不可获得的,但是由于引用计数不为零,所以均不会被回收。
优点:执行效率高,程序被影响小缺点:无法解决循环引用问题 导致内存泄漏,所以在 Java 的垃圾回收器中没有使用这种算法
可达性分析法通过判断对象的引用链遍历(从GC Root开始)是否可达来决定对象是否可以被回收。
如下图,从GC Root不能到达ObjD,ObjF ,ObjE,所以这三个对象是不可用的。
可作为GC Root的对象:
虚拟机栈中引用的对象(栈帧中的本地变量表)
方法区中的常 ...