
Java学习笔记——JavaWeb
Web基础
分层解耦
三层架构
- Controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据。
- Service:业务逻辑层,处理具体的业务逻辑。
- Dao:数据访问层(Data Access 0bject)(持久层),负责数据访问操作,包括数据的增、删、改、查。
处理请求时,Controller进行接收并调用Service,Service调用Dao进行数据访问并进行业务处理,然后将结果返回给Controller,Controller再对前端进行响应。
分层解耦
- 耦合:衡量软件中各个层/各个模块的依赖关联程度。
- 内聚:软件中各个功能模块内部的功能联系。
- 软件设计原则:高内聚低耦合。
IOC&DI
- 控制反转:Inversion Of Control, IOC。对象的创建控制权由程序自身转移到外部(容器)。
- 依赖注入:Dependency Injection, DI。容器为应用程序提供运行时所依赖的资源。
- Bean对象:IOC容器中创建、管理的对象。
实现分层解耦:将项目中的类交给IOC容器管理,应用程序需要什么对象直接依赖容器为其提供。
@Component 将当前类交给IOC容器管理
@Autowired 应用程序运行时自动查询该类型的bean对象,并赋值给该成员变量
IOC
注解 | 位置 | 说明 |
---|---|---|
@Component | 不属于以下三类时用此注解 | 声明bean的基础注解 |
@Controller | 标注在控制层类上 | @Component的衍生注解 |
@Service | 标注在业务层类上 | @Component的衍生注解 |
@Repository | 标注在数据访问层类上 | @Component的衍生注解 |
DI
- 属性注入
1
2
3
4
5
public class UserController {
private UserService userService;
}- 优点:代码简洁,方便快速开发
- 缺点:隐藏了类之间的依赖关系,可能会破坏类的封装性。
- 构造函数注入
1
2
3
4
5
6
7
8
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
}- 优点:能清晰地看到类的依赖关系,提高了代码的安全性。
- 缺点:代码繁琐,如果构造参数过多,可能会导致构造函数臃肿。
- setter注入
1
2
3
4
5
6
7
8
public class UserController {
private UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
}
MyBatis
数据库连接池
数据库连接池是个容器,负责分配、管理数据库连接。
它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏。
增删改查
#{…} | 占位符。执行时替换为?,生成预编译SQL |
${…} | 拼接符。直接将参数拼接在SQL语句中,存在SQL注入问题 |
1 |
|
苍穹外卖
JWT认证机制
JSON Web Token(JSON Web令牌)
传统Session
http协议本身是一种无状态的协议,如果用户向服务器提供了用户名和密码来进行用户认证,下次请求时,用户还要再一次进行用户认证才行。因为根据http协议,服务器并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储─份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样应用就能识别请求来自哪个用户。
JWT认证
- 前端通过Web表单将自己的用户名和密码发送到后端的接口。该过程一般是HTTP的POST请求。建议的方式是通过SSL加密的传输(https协议),从而避免敏感信息被嗅探。
- 后端核对用户名和密码成功后,将用户的id等其他信息作为JWT Payload(负载),将其与头部分别进行Base64编码拼接后签名,形成一个JWT(Token)。
- 后端将JWT字符串作为登录成功的返回结果返回给前端。前端可以将返回的结果保存在localStorage(浏览器本地缓存)或sessionStorage(session缓存)上,退出登录时前端删除保存的JWT即可。
- 前端在每次请求时将JWT放入HTTP的Header中的Authorization位。(解决XSS和XSRF问题)
后端检查是否存在,如存在验证JWT的有效性。例如,检查签名是否正确﹔检查Token是否过期;检查Token的接收方是否是自己 - 验证通过后后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应结果。
Nginx
Nginx反向代理的好处:
- 提供缓存提高访问速度
- 进行负载均衡,把大量请求分配给集群中的服务器
- 保证后端服务安全,前端无法直接请求到后端服务,要通过Ngnix转发
负载均衡策略
名称 | 说明 |
---|---|
轮询 | 默认方式 |
weight | 权重方式,默认为1,权重越高,被分配的客户端请求就越多 |
ip_hash | 依据ip分配方式,每个访客可以固定访问一个后端服务 |
least_conn | 依据最少连接方式,把请求优先分配给连接数少的后端服务 |
url_hash | 依据url分配方式,相同的url会被分配到同一个后端服务 |
fari | 依据响应时间方式,响应时间短的服务将会被优先分配 |
ThreadLocal
每个请求中的操作同属一个线程。
ThreadLocal为每个线程提供一份单独的存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
1 | public void set(T value); // 设置当前线程的线程局部变量的值 |
AOP
Aspect Orient Programming,面向切面编程
在不修改源代码的前提下,为系统中的业务组件添加某种通用功能。
采取横向抽取机制(动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。
主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。
名称 | 说明 |
---|---|
Joinpoint(连接点) | 可以被动态代理拦截目标类的方法 |
Pointcut(切入点) | 被拦截的连接点 |
Advice(通知) | 对切入点增强的内容 |
Target(目标) | 代理的目标对象 |
Weaving(植入) | 把增强代码应用到目标上,生成代理对象的过程 |
Proxy(代理) | 生成的代理对象 |
Aspect(切面) | 切入点和通知的结合 |
Redis
Redis是一个基于内存的 key-value 结构数据库。
- 基于内存存储,读写性能高
- 适合存储热点数据(热点商品、资讯、新闻)
常用数据类型
- 字符串 string
- 哈希 hash
- 列表 list
- 集合 set
- 有序集合 sorted set / zset
常用命令
字符串
SET key value | 设置指定 key 的值 |
GET key | 获取指定 key 的值 |
SETEX key seconds value | 设置指定 key 的值,并将 key 的过期时间设为 seconds 秒 |
SETNX key value | 只有在 key 不存在时设置 key 的值 |
哈希
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
HSET key field value | 将哈希表 key 中的字段 field 的值设为 value |
HGET key field | 获取存储在哈希表中指定字段的值 |
HDEL key field | 删除存储在哈希表中的指定字段 |
HKEYS key | 获取哈希表中所有字段 |
HVALS key | 获取哈希表中所有值 |
列表
Redis 列表是简单的字符串列表,按照插入顺序排序。
LPUSH key valuel [value2] | 将一个或多个值插入到列表头部 |
LRANGE key start stop | 获取列表指定范围内的元素 |
RPOP key | 移除并获取列表最后一个元素 |
LLEN key | 获取列表长度 |
集合
Redis set 是 string 类型的无序集合。集合成员是唯一的,集合中不能出现重复的数据。
SADD key member1 [member2] | 向集合添加一个或多个成员 |
SMEMBERS key | 返回集合中的所有成员 |
SCARD key | 获取集合的成员数 |
SINTER key1 [key2] | 返回给定所有集合的交集 |
SUNION key1 [key2] | 返回所有给定集合的并集 |
SREM key memberl [member2] | 删除集合中一个或多个成员 |
有序集合
Redis 有序集合是 string 类型元素的集合,且不允许有重复成员。每个元素都会关联一个 double 类型的分数。
ZADD key scorel memberl [score2 member2] | 向有序集合添加一个或多个成员 |
ZRANGE key start stop [WITHSCORES] | 通过索引区间返回有序集合中指定区间内的成员 |
ZINCRBY key increment member | 有序集合中对指定成员的分数加上增量 increment |
ZREM key member [member…] | 移除有序集合中的一个或多个成员 |
通用命令
KEYS pattern | 查找所有符合给定模式(pattern)的 key |
EXISTS key | 检查给定 key 是否存在 |
TYPE key | 返回 key 所储存的值的类型 |
DEL key | 在 key 存在时删除 key |
Spring Cache
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如:
- EHCache
- Caffeine
- Redis
常用注解
注解 | 说明 |
---|---|
@EnableCaching | 开启缓存注解功能,通常加在启动类上 |
@Cacheable | 在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中 |
@CachePut | 将方法的返回值放到缓存中 |
@CacheEvict | 将一条或多条数据从缓存中删除 |
微信支付
cron表达式
提供cron表达式可以定义任务触发的时间
构成规则:分为 6 或 7 个域,由空格分隔开,每个域代表一个含义
每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选)
WebSocket
WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。
HTTP VS WebSocket
- HTTP 是短连接;WebSocket 是长连接
- HTTP 通信是单向的,基于请求响应模式;WebSocket 支持双向通信
- HTTP 和 WebSocket 底层都是 TCP 连接
应用场景
- 视频弹幕
- 网页聊天
- 体育实况更新
- 股票基金报价实时更新