JVM
运行时数据区域
线程私有的:
程序计数器
虚拟机栈
本地方法栈
线程共享的:
堆
方法区
直接内存
程序控制器用来实现代码的流程控制,以及在多线程情况下实现上下文切换。生命周期和线程相同。
Java方法虚拟机栈用于实现方法调用。方法调用的数据需要通过栈进行传递,每一次方法调用都会有一个对应的栈帧被压入栈中,每一个方法调用结束后,都会有一个栈帧被弹出。生命周期和线程相同。如果超出了栈的内存大小,则会爆出StackOverFLowError错误或者OutofMemoryError。
堆是JVM所管理的内存中最大的一块,**唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。**堆也是垃圾收集器管理的主要区域,因此也被称作GC堆。
方法区之前听到的一种说法和「类」区分开,存储已被虚拟机加载的类信息、字段信息、方法信息、常量、静态变量等信息。
字符串常量池是JVM为了提升性能和减少内存消耗针对String主们开辟的一块区域,主要目的是为了避免字符串的重复创建。
堆空间的基本结构
Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时,Java 自动 ...
Java并发编程
什么是线程和进程
进程
进程是程序的一次执行过程,是系统运行程序的基本单位,进程是动态的。系统运行一个进程就是一个进程从创建、运行到消亡的过程。
在Java中,当我们启动main函数时时就是启动了一个JVM的进程,而main函数所在的线程就是这个进程中的一个线程,也称著线程。
线程
线程是一个比进程更小的执行单位。
与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
关系
线程是进程划分成的更小的运行单位。线程和进程最大的不同在于各进程基本上是独立的;而各线程则不一定,同一进程中的线程很有可能会相互影响。
线程执行开销小,但不利于资源的管理和保护;而进程则相反。
程序计数器为什么是私有的
程序计数器用于记录当前线程执行的位置。所以,程序计数器私有主要是为了线程切换后能恢复到正确的执行位置
虚拟机栈和本地方法栈为什么是私有的
每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引 ...
JavaIO
字节流
InputSteam「字节输入流」
InputStream 用于从源头(通常是文件)读取数据(字节信息)到内存中。
read():返回输入流中下一个字节的数据。如果未读取任何字符,返回-1
close()
readAllBytes():读取输入流中的所有字节
FileInputStream是一个比较常用的字节输入流对象,可直接指定文件路径。
OutputStream「字节输出流」
OutputStream 用于将数据(字节信息)写入到目的地(通常是文件)。
write(int b):将特定字节写入输出流
flush():刷新此输出流并强制写出所有缓冲的输出字节
close()
FileOutputStream 是最常用的字节输出流对象,可直接指定文件路径。
字符流
如果不知道编码类型,字节流很容易出现乱码。因此,I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。
Reader「字符输入流」
Reader 用于从源头(通常是文件)读取数据(字符信息)到内存中 ...
Java集合
集合框架底层数据结构
List
ArrayList:Object[]数组
Vector:Object[]数组,保证线程安全
LinkedList:双向链表
Set
HashSet「无序、唯一」:HashMap
LinkedHashSet:LinkedHashMap
TreeSet「无序、唯一」:红黑树
Queue
PriorityQueue:Object[]数组实现二叉堆
ArrayQueue:Object[]数组+双指针
Map
HashMap:数组➕链表或者红黑树「链表是为了解决哈希冲突」。当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间
LinkedHashMap:数组➕链表或者红黑树
Hashtable:数组➕链表
TreeMap:红黑树
ArrayList与LinkedList
线程安全:都不保证线程安全
底层数据结构:前者使用Object[],后者使用双向链表
快速随机访问:LinkedList不支持, ...
Java基础
JVM、JDK、JRE
JVM是运行Java字节码的虚拟机。JVM有针对不同系统的特定实现,目的是使用相同的字节码,它们都会给出相同的结果。
JDK是功能齐全的Java SDK,它能够创建和编译程序。
JRE是Java运行时环境,它不能用于创建新程序。
8种基本数据类型
6种数据类型
4种整型:byte「1B」、short「2B」、int「4B」、long「8B」
2种浮点型:float「4B」、double「8B」
1种字符类型:char「2B」
1种布尔型:boolean「1B」
基本类型和包装类型
成员变量包装类型不赋值就是null,基本类型有默认值且不是null
包装类型可用于泛型,而基本类型不可以
基本数据类型的局部变量存放在虚拟机栈中,基本数据的成员变量「未被static修饰存放在虚拟机堆中。包装类型属于对象,对象实例都存在堆中
面向对象三大特征
封装、继承、多态
子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方 ...
WebSocket
什么是websocket
有这样一种需求,怎么样才能在用户不做任何操作的情况下,网页能收到消息并发生变更。
最常见的解决方案是,网页的前端代码里不断定时发 HTTP 请求到服务器,服务器收到请求后给客户端响应消息。
又或者是长轮询。如果我们的 HTTP 请求将超时设置的很大,比如 30s,在这 30s 内只要服务器收到了扫码请求,就立马返回给客户端网页。如果超时,那就立马发起下一次请求。
本质上这些方法都是客户端主动去取数据,但场景复杂就不行了。
websocket是一个基于TCP,支持全双工通信的应用层协议。在使用 websocket 协议的网页游戏里,怪物移动以及攻击玩家的行为是服务器逻辑产生的,对玩家产生的伤害等数据,都需要由服务器主动发送给客户端,客户端获得数据后展示对应的效果。
如何建立websocket连接
浏览器在TCP三次握手建立连接之后,都统一使用HTTP协议先进行一次通信。
如果想建立websocket连接,就会在HTTP请求里带上一些特殊的header头。
123Connection: UpgradeUpgrade: websocketSec-WebSocke ...
JWT
什么是JWT
JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,是一种基于 Token 的认证授权机制。从 JWT 的全称可以看出,JWT 本身也是 Token,一种规范化之后的 JSON 结构的 Token。
Token 自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储 Session 信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。
并且, 使用 Token 认证可以有效避免 CSRF 攻击,因为 Token 一般是存在在 localStorage 中,使用 JWT 进行身份验证的过程中是不会涉及到 Cookie 的。
JWT由哪些部分组成
JWT通过「.」切分成三个为Base64编码的部分
Header : 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。
Payload : 用来存放实际需要传递的数据
Signature(签名) :服务器通过 Payload、Header 和一个密钥 (Secret) 使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成
Header和 ...
KOB项目
用户表设计
注册流程
Jwt八股
前端向后端发送请求
Controller层接收到请求并调用具体业务逻辑
Service层处理完请求返回给前端
前端接收到后端发来的数据后进行相关操作
登录流程
前端有两个函数,login函数用来根据用户名和密码生成token,getinfo函数用来根据token得到用户的id、用户名和头像。
user.js
login函数
getinfo函数
获取token
根据token获得相关信息
登出函数
直接纯前端实现。删除local storage里的jwt_token,然后把用户相关的变量清空即可。
bot相关API
一共有三个功能,创建、修改和删除。具体流程和登录注册差不多不再赘述。
需要注意的是,需要在编写一个辅助函数refresh_bots并绑定后端apigetBotsInfo。每次修改完bot都要执行该辅助函数。
还有一件事,每次调用后端API的时候,请求头都要加上jwtToken来验证。
Bot表设计
获取天梯排行榜
前端:点击页码,根据页码去后端获取当前页码相对应的user信息,然后利用函数update_pag ...
nginx
Nginx的特点
内存占用非常少
高并发
跨平台
扩展性好:第三方插件非常多
安装使用简单
稳定性好
开源软件,免费试用
……
Nginx用途
静态资源服务器
Nginx可以将服务器上的静态文件缓存下来,通过HTTP协议展现给客户端。因此可以使用Nginx搭建静态资源Web服务器/缓存服务器。
当客户端第一次请求静态资源的时候,会从服务器直接返回,Nginx同时也会缓存一份静态资源。如果后续客户端请求相同的静态资源,只要对应的缓存未被清理且没有过期,就可以直接从Nginx缓存中取出返回给客户端了。
记得开启Gzip压缩。这样可以使网站的图片、CSS、JS等文件在传输时进行压缩,提高访问速度,优化Nginx性能。
反向代理
客户端将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器,获取数据后再返回给客户端。对外暴露的是反向代理服务器地址,隐藏了真实服务器IP地址。反向代理“代理”的是目标服务器,这一个过程对于客户端而言是透明的。
反向代理隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。一般在处理跨域请求对时候比较常用。
Nginx支持配置反向代理, ...
Spring
什么是Spring IoC
IoC翻译过来是控制反转。控制指的是对象创建「实例化、管理」的权利;反转指的是控制权交给外部环境「Spring框架、IoC容器」。IoC的思想就是将原本在程序中手动创建对象的控制权交由Spring框架处理。
在实际项目中一个 Service 类可能依赖了很多其他的类,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。
在Spring中,IoC容器是Spring用来实现IoC的载体,IoC容器实际上就是个Map,Map中存放的是各种对象。
什么是Spring Bean
简单来说,Bean代指的就是那些被 IoC 容器所管理的对象。我们需要告诉IoC容器帮助我们管理哪些对象,这个是通过配置元数据来定义的。配置元数据可以是XML文件、注解或者Java配置类。
将一个类声明为Bean的注解
@Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bea ...