Kyle的天机学堂学习笔记

本文将展示一个小白从0 ->1 完成项目的全部历练已经心得
PS:要求做到真正的自我思考而不是对着教程敲代码,并借用AI进行辅佐与思考

DAY1

Maven

子工程会继承父工程所有依赖
有三套生命周期,互不干扰且同一生命周期内执行命令会以此完成之前的命令

1.clean

2.default(compile,test,package,install)

3.site(deploy)

对象

DTO 数据传输对象,用于服务端与客户端传输对象
PO 持久层对象,用于数据库操作的实体类
VO 视图对象,用于返回前端的对象
QUERY 查询对象,一般用于查询封装条件

关于注解

1.以往注入一般用@Autowired,但是spring推荐用构造器注入,因此我们用Lombok注解@RequiredArgsContructor来批量完成我们的构造器注入而不会导致代码臃肿private final xxx
question:构造器注入的原理是什么
A:强依赖性和不变性,能更早提出报错
2.用@RestControllerAdvice注解来注册一个异常处理器

梳理流程

刚接手项目,我们从git上面拉取代码,拿到对应代码后,
1.我们在nacos注册中心保证对应的服务是自己的ip(通过更改权重或者下线其他ip:遇到raft权限算法我们删除掉nacos服务里面的protocal)
2.将修改好的bug创建新分支上传git,通过web钩子构建到jenkins,接着部署到我们的微服务器上
3本地启用项目注意将bootstrap环境改成local

DAY2

获取当前用户流程

前端会携带请求头TOKEN来访问网关,而网关会解析TOKEN,拿去用户信息,此时我们注意了,要设置一个全局拦截器来将用户判定代码从各个cotroller层解耦出来!
此时我们用到一个线程ThreadLocal,他会给用户信息存储在独立线程之中,这样后面的应用就可以直接在线程里拿去信息而不是进行传递消耗资源
get请求是在url上,因此没必要加@Requestbody

CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
//自动更新sql
一般主键用bitint
注意了:
1 当我们用map来接受类时,我们在map.get()方法时得到的是Object类型,因此需要Integer.of(value.tostring())方法来强转类型在这里插入图片描述
2当我们想用mp操作sql时,一般注入service类来操作,但是遇到循环注入时我们可以注入mapper类,二者都是通过调用底层basemapper来实现的
3用mp的page返回对象是一个包括分页信息和分页数据的类型,消息记录用getrecords方法
4关于一些stream流的知识点
a.stream().map()这里是实现我们的流式操作(集合List、Set、Queue与数组,取出里面的id之类的比如

`List<Long> courseIds = learningLessonPage.getRecords().stream()
                .map(LearningLesson::getCourseId).collect(Collectors.toList());

b.用做集合.entryset()可以把map当作集合再进行流处理
c.stream().collect(Collectors.toMap(function,function)来将集合转换成map,以时间换空间
5 springTask定时任务,在启动类加@EnableScheduling // 开启定时任务
在要定时的类加上@Scheduled(cron = “秒(0-59) 分(0-59) 时(0-23) 日(1-31) 月(1-12) 星期(0-7) [年 (可选)]”)eg. @Scheduled(cron = "0 * * * * *")//每分钟
6 learningLessonService.list(Wrappers.lambdaQuery().ne(LearningLesson::getStatus, LessonStatus.EXPIRED));这里类型要写在lambdaQuery前面
7 learningLessonService.updateBatchById(list); 的意思是:
在每个 LearningLesson 实体对象中:
使用 id(主键)作为更新的定位依据,更新这个对象中非 null 的字段到数据库中对应那一行。

DAY4不太熟悉的高并发处理
不用定时任务用延时任务
JUC知识点

// 项目启动后,当前类实例化 属性注入值后 该方法会运行,一般用于初始化工作
    @PostConstruct
    public void init() {
        log.info("init方法执行了");
        // 核心线程数等于CPU核心数
        Integer corePoolSize = Runtime.getRuntime().availableProcessors();
        // 创建线程池
        executor = Executors.newFixedThreadPool(corePoolSize);
        CompletableFuture.runAsync(this::handleDelayTask);
        // executor.execute(this::handleDelayTask);
    }
    // 项目销毁前后,关闭延迟队列
    @PreDestroy
    public void destroy() {
        log.debug("关闭学习记录处理的延迟任务");
        // 关闭线程池
        executor.shutdown();
        begin = false;
    }

//注解使用区别
Kyle的天机学堂学习笔记_第1张图片

讲一下线程池如何使用

//创建线程池
Executors.newFixedThreadPool();//固定线程,但是会引发内存益处
        Executors.newCachedThreadPool();//线程数是0,动态调整
        Executors.newSingleThreadExecutor();//单一线程,用来顺序处理
        Executors.newScheduledThreadPool();//延时线程,适用场景(如心跳检测、定时日志等)
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(16, 60, TimeUnit.MINUTES, new LinkedBlockingDeque<>(10));

        threadPoolExecutor.submit(new Runnable() {
            @Override
            public void run() {
                
            }
        })

Kyle的天机学堂学习笔记_第2张图片
DAY 06
自己写一个点赞系统微服务
删除module撤回后变成文件夹怎么办
经常会遇到从GitHub上download的progect在idea里面打开是普通文件夹形式,而并不是我们想要的module形式(文件夹图标右下角有个蓝色的tag),那么如何快速转换成我们想要的module形式呢?

1、右击project,选择第二项“add framework support”,然后从对话框左侧选择“Maven”,OK即可

2、设置maven仓库地址:右击file,选择settings,找到maven,设置maven home directory以及后面两项。(图片大小超过限制。。我就不传图了)

3、OK完成,等加载刷新。


第二种情况:Remove Module(当你把project下中的一个module删除delete之后,会发现该文件夹右下角的蓝色flag消失了,但文件还在)。。那么如果你想重新把它加入module的话,该如何操作呢?

1、右击该普通文件夹的父级(即它上一级的module),选择Open Module Settings,之后会弹出一个框

2、在中间文件夹这一列找到刚刚的父级module,选中后点击列顶部的加号“+”,在弹出框选择“Import Module”,找到要加入module的子级文件夹,点击OK

3、弹出框,选择“Next”,always,最后一步选择“Select all”,然后点击“Finish”,搞定!

此时你会发现,消失的蓝色flag又恢复啦!

分页思路mp

new Page对象,传页码和一页内容数
new arraylist集合itemList
new一个OrderItem来设置按什么字段排序,升序还是降序,并放入集合
把集合放入page中
最后调用lambdaQuerry.page(page)

@RequestParam接受list集合参数

Feign使用以及整合sentinel做降级
引入依赖
首先我们需要把module的controller写在api的module里面,并写上注解@Feign,同时指明client和fallbackfactory

@FeignClient(contextId = "remark", value = "remark-service", fallbackFactory = RemarkClientFallBack.class)
public interface RemarkClient {

在该package下写一个fallback,implement FallbackFactory<对应的Client>,返回null,避免雪崩
最后在nacos的feign配置开启sentinel
ps:微服务之间如何获取userId,答:在权限模块里编写feign拦截器里传递

这里我们在捋一遍登录逻辑
我们专门设计一个登录拦截器用来获取userId
从规定好的前端请求request获取对应信息,转换成Long类型
这里我们编写一个UseContext工具类来把信息放进ThreadLocal里面,方便操作读取信息
最后我们要写一个拦截器配置类implement WebMvcConfigurer
用registry.addInterceptor方法添加拦截器.order来确定顺序

与登录implements HandlerInterceptor重写prehandler不同所以我们Feign则是implementRequestInterceptor 重写apply方法

关于时间

DateTimeFormatter yearMonth = DateTimeFormatter.ofPattern("yyyyMM");
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + time.format(yearMonth);

redis删除

delete同步
unlink异步
小bug
当我们用xxl执行创建表单-持久化表单-删除redis缓存时,
在持久化用到了分片任务,这时其中一个分片完成后会执行删除,导致第二个分片无法执行
解决:比如我们将前两个任务在每月一日,第三个任务集中在第三日,也就是预估前两个任务执行时间再集中删除

你可能感兴趣的:(学习,笔记)