SpringSecurity学习
何为SpringSecurity?
Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。
一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多,因为相比与SpringSecurity,Shiro的上手更加的简单。
一般Web应用的需要进行认证和授权。
认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户
授权:经过认证后判断当前用户是否有权限进行某个操作
而认证和授权也是SpringSecurity作为安全框架的核心功能。
快速入门我们先要搭建一个简单的SpringBoot工程
① 设置父工程 添加依赖
12345678910111213141516<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifact ...
剑指Offer【滑动窗口的最大值】
题目描述给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
示例:
123456789101112输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值--------------- -----[1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
提示:
你可以假设 k 总是有效的,在输入数组 不为空 的情况下,1 ≤ k ≤ nums.length。
解法
单调队列
本题的难点在于如何以时间复杂度O(1)的情况下获取单次滑动窗口的最大值
假设窗口的左指针 ...
剑指Offer【从上到下打印二叉树I,II,III】
题目描述从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:给定二叉树: [3,9,20,null,null,15,7],
12345 3 / \9 20 / \ 15 7
返回:
1[3,9,20,15,7]
提示:
节点总数 <= 1000
解法
广度优先遍历
12345678910111213141516171819202122232425262728class Solution { public int[] levelOrder(TreeNode root) { //1.特殊判断 if (root == null) { return new int[0]; } //2.利用队列进行bfs Queue<TreeNode> queue = new LinkedList<>(); List<Integer> res = new ArrayLis ...
剑指Offer【树的子结构】
题目描述输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
例如:给定的树 A:
12345 3 / \ 4 5 / \1 2
给定的树 B:
123 4 /1
返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。
示例 1:
12输入:A = [1,2,3], B = [3,1]输出:false
示例 2:
12输入:A = [3,4,5,1,2], B = [4,1]输出:true
限制:
0 <= 节点个数 <= 10000
解法
先用先序遍历找到A中B的相等节点
再以这个节点为根节点开始判断两个树结构是否相等
如果结构不相等再继续寻找下一个相等节点
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354import leetcode.TreeNode;class Solution ...
Java并发编程
相关概念进程:程序是静止的,进程实体的运行过程就是进程,是系统进行资源分配的基本单位
进程的特征:并发性、异步性、动态性、独立性、结构性
线程:线程是属于进程的,是一个基本的 CPU 执行单元,是程序执行流的最小单元。线程是进程中的一个实体,是系统独立调度的基本单位,线程本身不拥有系统资源,只拥有一点在运行中必不可少的资源,与同属一个进程的其他线程共享进程所拥有的全部资源
关系:一个进程可以包含多个线程,这就是多线程,比如看视频是进程,图画、声音、广告等就是多个线程
线程的作用:使多道程序更好的并发执行,提高资源利用率和系统吞吐量,增强操作系统的并发性能
并发并行:
并行:在同一时刻,有多个指令在多个 CPU 上同时执行
并发:在同一时刻,有多个指令在单个 CPU 上交替执行
同步异步:
需要等待结果返回,才能继续运行就是同步
不需要等待结果返回,就能继续运行就是异步
线程进程对比:
进程基本上相互独立的,而线程存在于进程内,是进程的一个子集
进程拥有共享的资源,如内存空间等,供其内部的线程共享
进程间通信较为复杂
同一台计算机的进程通信称为 IPC(Inter-proc ...
剑指Offer【把数字翻译成字符串】
题目描述给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
123输入: 12258输出: 5解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
提示:
0 <= num < 2^31
解法
动态规划
dp[i]表示为从0-i能翻译的种类数
可以i单独作为一位来翻译,此时最后一位肯定是固定的只有一种,那么种类数在dp[i-1]就确定了
如果第i−1位和第i位组成的数字在10到25之间,可以把这两位连起来翻译,同类种类数在dp[i-2]就固定了
动态转移方程为:
1234567891011121314151617181920212223242526class Solution { p ...
剑指Offer【和为s的连续正数序列】
题目描述输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
12输入:target = 9输出:[[2,3,4],[4,5]]
示例 2:
12输入:target = 15输出:[[1,2,3,4,5],[4,5,6],[7,8]]
限制:
1 <= target <= 10^5
解法
滑动窗口
套滑动窗口模板,l是窗口左边界,r是窗口右边界,窗口中的值一定是连续值。
当窗口中数字和小于target时,r右移; 大于target时,l右移; 等于target时就获得了一个解
答案中会出现的最大数字(target+1)/2
12345678910111213141516171819202122232425262728293031323334353637383940class Solution { public int[][] findContinuousSequence(int target) { ...
剑指Offer【二叉搜索树的最近公共祖先】
题目描述给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大( 一个节点也可以是它自己的祖先 )。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
123输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8输出: 6 解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:
123输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4输出: 2解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。
解法
两次遍历
我们从根节点开始遍历;
如果当前节点就是 p,那么成功地找到了节点;
...
剑指Offer【剪绳子】
题目描述给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
示例 1:
123输入: 2输出: 1解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:
123输入: 10输出: 36解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示:
2 <= n <= 58
注意:本题与主站 343 题相同:https://leetcode-cn.com/problems/integer-break/
解法
动态规划
12345678910111213141516class Solution { public int cuttingRope(int n) { int[] dp=new int[n+1];//从1开始,dp ...
JVM
⚒️内存结构概述
🌕️类加载子系统类的加载过程
加载
通过一个类的全限定名获取定义此类的二进制字节流
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
方法区:jdk7之前叫永久代,之后叫元空间
方法区只是一种规范,具体实现是永久代和元空间
在内存中生成一个代表这个类的java.lang.class对象,作为方法区这个类的各种数据的访问入口
连接验证
目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。
主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。:
准备
为类变量分配内存并且设置该类变量的默认初始值,即零值。
这里不包含用final修饰的static,因为final在编译的时候就会分配了,准备阶段会显式初始化;
这里不会为实例变量分配初始化,类变量(静态变量)会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。
解析
将常量池内的符号引用转换为直接引用的过程。
事实上,解析操作往往会伴随着JVM在执行完初始化之后再执行。
符号引用就是一组符号来描述所引用的目标。符号 ...