苍穹外卖12天完结(4.9-4.20)

4.9(day1)初始化

nginx负载均衡

1.反向代理,转发到指定路径

2.负载均衡策略

①轮训:依此分发

upstream backend_servers {

server 192.168.1.101;

server 192.168.1.102;

}

②带权轮训:按权重分发

upstream backend_servers {

server 192.168.1.101 weight=3; # 处理3个请求后轮到下一台

server 192.168.1.102 weight=1;

}

③哈希:固定分发(会话保持)

upstream backend_servers {

ip_hash;

server 192.168.1.101;

server 192.168.1.102;

}

④最少连接:分发到连接最少的服务器

upstream backend_servers {

least_conn;

server 192.168.1.101;

server 192.168.1.102;

}

MD5加密(不适用于密码)

如果两个密码​​完全相同​ ​(包括字符大小写、空格、特殊字符等),并且在计算MD5哈希值时采用​​相同的编码方式​ ​(如UTF-8),那么它们的MD5哈希值一定是相同的。这是因为MD5是一种​​确定性哈希函数​​,相同的输入必然生成相同的输出。因为hash算法是固定的,所以同一个字符串计算出来的hash串是固定的。

解决办法:加盐

​为哈希添加随机盐(Salt)​​是防止彩虹表攻击。随机盐方式较为繁琐。

使用 BCrypt(推荐,需第三方库)​​更安全的密码哈希方案

复制代码
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-crypto</artifactId>
    <version>5.7.3</version>
</dependency>
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
复制代码
public class BCryptExample {
    public static void main(String[] args) {
        String rawPassword = "123456";

        // 哈希密码(自动生成盐)
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12); // 强度系数 12
        String hashedPassword = encoder.encode(rawPassword);

        // 验证密码
        boolean isValid = encoder.matches(rawPassword, hashedPassword);
        System.out.println("验证结果: " + isValid);
    }
}

彩虹表攻击

是一种预先计算的​​哈希值到明文密码的映射表​​,通过对比数据库泄露的哈希值与彩虹表中的条目,直接获取原始密码。

  • 生成大量可能的密码。
  • 对每个密码计算哈希值。
  • 明文密码 -> 哈希值 的映射存储为表

Knife4j

复制代码
@Api(tags = "员工相关接口")写在Controller上
复制代码
@ApiOperation("员工登录")写在Controller方法上

参数中有实体类,会自动解析

复制代码
@ApiModel(description = "员工登录时传递的数据模型")写在实体类方法上
复制代码
@ApiModelProperty("用户名")写在实体类方法的属性上

打开接口文档http://localhost:8080/doc.html,图示对应上方代码顺序

4.10(day2)

JWT

生成token(Header.Payload.Signature)

Header:Base64编码(对称加密算法HS256) 注:只是算法名称,并未加密

Payload:Base64编码(参数)

Signature:HS256加密(Header+Payload)

ThreadLocal

线程隔离,为线程提供独立的副本,由ThreadLocalMap存储,一般用于传递用户信息

get/set 获取/设置当前线程变量

remove 防止线程泄漏

线程和进程

进程

计算机程序在进行某数据集合的一次运行活动,是操作系统进行资源分配的最小单位,是一次程序的实例

线程

线程是进程的执行单元,共享进程的共享资源,是CPU调度的基本单位

序列化

对象转为字节流,实现Serialization类

用途:

验证数据版本一致性(VersionID)

持久化存储 / 深拷贝

MVC消息转换器

将Http中的内容转化为JAVA对象,重写WebMvcConfigurationSupport类中的MappingJackson2HttpMessageConverter方法,基于反序列化实现,应用于多种数据格式的转换

4.12(day3)

MyBatis 中的 ​​动态 SQL​​ 和 ​​静态 SQL​​

静态SQL:SQL固定不变,建议直接写Mapper层(注解方式)

复制代码
 name = #{name},

动态SQL:根据传入的参数动态拼接SQL语句

复制代码
 <if test="name != null">name = #{name},</if>

仅更新传递时带有的参数,其它参数不做更新

优点:多复用,状态更改,更新数据

4.13(day4)

AOP切面实现公共字段填充(INSERT,UPDATE)

自定义注解 @interface

复制代码
@Target( ElementType.METHOD)//方法注解
@Retention(RetentionPolicy.RUNTIME)//运行时注解
复制代码
OperationType value();枚举类
复制代码
@Aspect 切面类
复制代码
@Pointcut切点方法上
复制代码
@Before("autoFillPointcut()")切点执行前执行

禁用外键约束

首先,外键一定是另一个表的主键,就会涉及到多个表之间的关联查询。

1.Upadte和Delete时都需要考虑外键约束

2.并发时行级锁导致性能下降

3.级联时会导致级联删除

4.导致耦合度高

@ConditionalOnMissingBean

用于配置类,避免Bean重复创建

Bean生命周期

实例化=>属性赋值=> 初始化 =>使用 =>销毁

4.14(day5)

4.15(day6)