11.3 优化前git linux Redis
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
Git命令
git在之前学过一遍,做博客的时候也应用过,已经很熟悉了。记下命令吧
本地仓库的操作
命令 |
作用 |
git status |
查看文件状态 |
git add |
将文件修改加入暂存区 |
git reset |
将暂存区的文件取消暂存或者切换版本 |
git commit |
将暂存区的文件修改提交到版本库 |
git log |
查看日志 |
远程仓库操作
命令 |
作用 |
git remote |
查看远程仓库 |
git remote add |
添加远程仓库 |
git clone |
从远程仓库克隆 |
git pull |
从远程仓库拉取 |
git push |
推送到远程仓库 |
标签操作 可以切换版本和更新时间
命令 |
作用 |
git tag |
列出已有的标签 |
git tag [name] |
创建标签 |
git push [shortName] [name] |
将标签推送远程仓库 |
git checkout -b [branch] [name] |
检出标签 |
在IDEA中集成使用Git
==在上面VCS中,点commit 选git 然后把路径改成自己git.exe安装的路径 就完成了IDEA集成,设置和远程仓库,就能用了==
- 本地初始仓库
- 选择VCS选项卡 —> 创建Git仓库 —> 选择需要被Git管理的目录 —> 确定
- 从远程仓库克隆(常用)
- 这个可以自己选择克隆的本地位置
- 可以直接把远程仓库的代码都克隆到本地
- 远程克隆下来的项目会自带一个文件:
.gitignore
文件,在里面的信息是代表哪些文件不需要交给git管理
Linux
比较简单和基础,过一遍发现是自己都会的,简单的安装软件配置环境,还是很easy的
Redis
跟着视频把Redis安装完成了
Linux安装Redis
-
将Redis安装包上传Linux
-
解压安装包,改成你自己的redis版本,路径解压到/usr/local
1
| tar -zxvf redisVersion.tar.gz -C /usr/local
|
-
安装Redis的依赖环境gcc,编译
-
进入redis,编译
1 2 3 4 5
| cd /usr/local/redis根目录
make
|
-
进入redis的src目录,进行安装
1 2 3 4
| cd /usr/local/redis根目录/src
make install
|
Redis启动和停止
设置一个后台运行,需要先修改redis.conf文件把aemonize on
字段,将其修改为daemonize yes
1 2
| src/redis-server ./redis.conf
|
Redis添加密码登陆
还是修改redis.conf配置文件,找到requirepass
这行,将其注释去掉,并在后面写上自己的密码
1 2 3 4 5 6
| src/redis-server ./redis.conf
src/redis-cli -h localhost -p 6379 -a 密码
|
3. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
IDEA集成Git,一直报错,自己另外提交了一个就没问题,不知道什么原因。
CSDN搜到原因了,是文件在本地仓库和远程仓库上不一致,但是不知道如何解决,看两个库中唯一一个共同的文件是.gitnore打开,的确是不一样,就干脆直接把远程仓库的.gitnore删除了,再次提交,成功了
4.扩展学习部分
5.总结
今天的学习其实主要是复习和巩固,之前粗略学习的git和redis,全部重新过了一下,难度不大,就是晚上想把瑞吉上传到码云的时候,出了些问题,搞了有点久了,在前面的基本没什么问题,分支那边懂是懂了,但是没有实际操作过,因为自己做项目就一个分支就好了。明天试着把瑞吉部署到服务器中,就彻底结束SpringBotot的学习了。
11.4 瑞吉外卖优化
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
Git部署
之前git已经集成IDEA成功,直接commit完了直接提交没有报错,很顺利也很简单。
缓存优化
缓存优化用Redis,导入SpringDataRedis坐标
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
|
修改yml配置文件
1 2 3 4 5
| redis: host: 172.16.1.76 port: 6379 password: 123456 database: 0
|
配置序列化器
方便图形化界面中看我们存入的数据
1 2 3 4 5 6 7 8 9 10 11
| @Configuration public class RedisConfig extends CachingConfigurerSupport { @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(connectionFactory); return redisTemplate; } }
|
代码改造
因为实现的思路比较长,就写代码注释中了,这里使用一个butterfly自带的标签外挂把代码合并了,
+
为增加的代码 -
为原来的代码删除的
u7-u7.github.io效果是分页的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @PostMapping("/sendMsg") public Result<String> sendMsg(@RequestBody User user, HttpSession session) throws MessagingException { String phone = user.getPhone(); if (!phone.isEmpty()) { String code = MailUtils.achieveCode(); log.info(code); MailUtils.sendTestMail(phone, code); redisTemplate.opsForValue().set("code", code,5, TimeUnit.MINUTES); return Result.success("验证码发送成功"); } return Result.error("验证码发送失败"); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| @GetMapping("/list") public Result<List<DishDto>> get(Dish dish) { + List<DishDto> dishDtoList; + String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus(); + dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key); + //如果有,则直接返回 + if (dishDtoList != null){ + return Result.success(dishDtoList); + } + //如果无,则查询 //条件查询器 LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>(); //根据传进来的categoryId查询 queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId()); //只查询状态为1的菜品(在售菜品) queryWrapper.eq(Dish::getStatus, 1); //简单排下序,其实也没啥太大作用 queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime); //获取查询到的结果作为返回值 List<Dish> list = dishService.list(queryWrapper); log.info("查询到的菜品信息list:{}",list); //item就是list中的每一条数据,相当于遍历了 - List<DishDto> dishDtoList = list.stream().map((item) -> { + dishDtoList = list.stream().map((item) -> { //创建一个dishDto对象 DishDto dishDto = new DishDto(); //将item的属性全都copy到dishDto里 BeanUtils.copyProperties(item, dishDto); //由于dish表中没有categoryName属性,只存了categoryId Long categoryId = item.getCategoryId(); //所以我们要根据categoryId查询对应的category Category category = categoryService.getById(categoryId); if (category != null) { //然后取出categoryName,赋值给dishDto dishDto.setCategoryName(category.getName()); } //然后获取一下菜品id,根据菜品id去dishFlavor表中查询对应的口味,并赋值给dishDto Long itemId = item.getId(); //条件构造器 LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>(); //条件就是菜品id lambdaQueryWrapper.eq(itemId != null, DishFlavor::getDishId, itemId); //根据菜品id,查询到菜品口味 List<DishFlavor> flavors = dishFlavorService.list(lambdaQueryWrapper); //赋给dishDto的对应属性 dishDto.setFlavors(flavors); //并将dishDto作为结果返回 return dishDto; //将所有返回结果收集起来,封装成List }).collect(Collectors.toList()); + //将查询的结果让Redis缓存,设置存活时间为60分钟 + redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES); return Result.success(dishDtoList); }
|
因为菜品中save和update和status都需要,加入清理缓存的逻辑,单独把修改的代码放出来 同样使用diff放修改的代码
1 2 3 4 5 6 7 8
| @PostMapping public Result<String> save(@RequestBody DishDto dishDto) { log.info("接收到的数据为:{}", dishDto); dishService.saveWithFlavor(dishDto); + String key = "dish_" + dishDto.getCategoryId() + "_1"; + redisTemplate.delete(key); return Result.success("添加菜品成功"); }
|
1 2 3 4 5 6 7 8
| @PutMapping public Result<String> update(@RequestBody DishDto dishDto) { log.info("接收到的数据为:{}", dishDto); dishService.updateWithFlavor(dishDto); + String key = "dish_" + dishDto.getCategoryId() + "_1"; + redisTemplate.delete(key); return Result.success("修改菜品成功"); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @PostMapping("/status/{status}") public Result<String> status(@PathVariable Integer status, @RequestParam List<Long> ids) { log.info("status:{},ids:{}", status, ids); LambdaUpdateWrapper<Dish> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.in(ids != null, Dish::getId, ids); updateWrapper.set(Dish::getStatus, status); + LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.in(Dish::getId, ids); + List<Dish> dishes = dishService.list(lambdaQueryWrapper); + for (Dish dish : dishes) { + String key = "dish_" + dish.getCategoryId() + "_1"; + redisTemplate.delete(key); + } dishService.update(updateWrapper); return Result.success("批量操作成功"); }
|
删除的话不需要修改的原因的是,我们删除之前需要修改为停售状态,所以我们已经给修改状态加入了清理缓存,所以要删除的话,一定会先清理过缓存的。
SpringCache
一个框架,能实现基本注解的缓存功能,就是加注解就能清理缓存,常用注解网上都搜得到用法,我就记项目中所使用的说明一下,@Cacheable和@CacheEvict
@cacheable
的作用主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@CachEvict
的作用主要针对方法配置,能够根据一定的条件对缓存进行清空
项目使用SpringCache
导入坐标
1 2 3 4 5 6 7 8 9
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
|
配置yml为Redis缓存
1 2 3 4 5 6 7 8 9
| spring: redis: host: 172.16.1.76 port: 6379 password: 123456 database: 0 cache: redis: time-to-live: 1800000
|
缓存套餐
导入坐标配置好文件,然后在启动项加@EnableCaching 开启缓存注解
SetmealController的list方法上加上@Cacheale
注解 和之前的不注解差不多 就是把值写注解里面了
1 2 3 4 5 6 7 8 9 10 11 12 13
| @GetMapping("/list") @Cacheable(value = "setmealCache", key = "#setmeal.categoryId + '_' + #setmeal.status") public Result<List<Setmeal>> list(Setmeal setmeal) { LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId()); queryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, 1); queryWrapper.orderByDesc(Setmeal::getUpdateTime); List<Setmeal> setmealList = setmealService.list(queryWrapper); return Result.success(setmealList); }
|
SetmealController的save、update和status方法,加入清理缓存的逻辑 很简单直接复制就行改成true全部填返回值
1 2 3 4 5 6 7 8
| @PostMapping
@CacheEvict(value = "setmealCache", allEntries = true) public Result<String> save(@RequestBody SetmealDto setmealDto) { log.info("套餐信息:{}", setmealDto); setmealService.saveWithDish(setmealDto); return Result.success("套餐添加成功"); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @PutMapping @CacheEvict(value = "setmealCache", allEntries = true) public R<Setmeal> updateWithDish(@RequestBody SetmealDto setmealDto){ List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes(); Long id = setmealDto.getId(); LambdaQueryWrapper<SetmealDish> qw = new LambdaQueryWrapper<>(); qw.eq(SetmealDish::getSetmealId,id); setmealDishService.remove(qw); setmealDishes.stream().map((item) -> { item.setSetmealId(id); return item; }).collect(Collectors.toList()); setmealService.updateById(setmealDto); setmealDishService.saveBatch(setmealDishes); return R.success(setmealDto); }
|
1 2 3 4 5 6 7 8 9
| @PostMapping("/status/{status}") @CacheEvict(value = "setmealCache", allEntries = true) public R<String> status(@PathVariable String status, @RequestParam List<Long> ids) { LambdaUpdateWrapper<Setmeal> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.in(Setmeal::getId, ids); updateWrapper.set(Setmeal::getStatus, status); setmealService.update(updateWrapper); return R.success("批量操作成功"); }
|
==!!! R需要实现Serializable接口,因为有个序列化的过程==
读写分离
读写分离比较麻烦,需要先实现MySQL的主从表,让阿贵克隆了两台虚拟机。一个为主库,一个为从库。跟着步骤来就行,唯一有问题的点就是,因为是克隆的,所以mysql需要修改uuid。这里自己出过BUG。
修改方法 查看uuid
1 2 3 4 5 6
| mysql> select uuid(); + | uuid() | + | 26532364-4f8d-11ed-a300-005056307198 | +
|
1
| vi /var/lib/mysql/auto.cnf
|
别忘记重启服务
项目实现读写分离
创建一个新的分支,测试没问题再并入main
导入坐标
1 2 3 4 5
| <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.0.0-RC1</version> </dependency>
|
修改原来的mysql配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| spring: application: name: reggie_take_out shardingsphere: datasource: names: master,slave master: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://172.16.1.77:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true username: root password: root slave: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://172.16.1.78:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true username: root password: root masterslave: load-balance-algorithm-type: round_robin name: dataSource master-data-source-name: master slave-data-source-names: slave props: sql: show: true main: allow-bean-definition-overriding: true
|
3. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
这是mysql主从复制,查询主从信息的时候正常的显示,但是自己显示的是Connecting to source,网上搜都说的uuid的问题,但是自己uuid修改了很多次,还是失败,就重连了一下,然后全部重新配置了uuid和Slave_Io_Running,就好了。
4.扩展学习部分
5.总结
今天周五上午练车,下午把基本的优化知识学了,修改了原来没加入缓存和读写分离的项目,开了两台虚拟机,调配下载软件,今天的学习难度是很简单的,明天就可以部署到h3c的服务器上面了,配置方面总是会出问题的,mysql自己修了近一个半小时,linux命令也在修bug的路上,越发熟练,明天部署完停下来,梳理一下这段时间所学的知识。
11.7 部署项目在h3c
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
配置环境
三台服务器
172.16.1.76 Redis缓存 启动Redis服务的
172.16.1.77 Nginx放前端项目和反向代理 Mysql 主从复制结构的主库
172.16.1.78 Mysql 主从复制结构的从库 jar jdk git maven 放后端项以及配置
部署前端项目
在77中修改nginx.conf 把课件中的dist文件放html目录中去
1 2 3 4 5 6 7 8 9 10 11 12 13
| server { listen 80; server_name localhost;
location / { root html/dist; #前端页面存放位置 index index.html; } location ^~ /api/ { rewrite ^/api/(.*)$ /$1 break; proxy_pass http://172.16.1.78:8080; #后端 } }
|
部署后端项目
后端这块自己出了些问题,首先安装好JDK git Mysql Maven 查看的命令也很简单
1 2 3
| java -version git -v mvn -v
|
然后把IDEA中的项目执行git commit 然后push 上传到gittee码云 创建一个/usr/local/app
1
| git clone https://gitee.com/u7u7-sjh/reggie_take_out.git
|
sh脚本 自己包名跟这个不太一样,然后自己修改了一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #!/bin/sh echo ================================= echo 自动化部署脚本启动 echo =================================
echo 停止原来运行中的工程 APP_NAME=reggie_take_out
tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'` if [ ${tpid} ]; then echo 'Stop Process...' kill -15 $tpid fi sleep 2 tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'` if [ ${tpid} ]; then echo 'Kill Process!' kill -9 $tpid else echo 'Stop Success!' fi
echo 准备从Git仓库拉取最新代码 cd /usr/local/app/reggie_take_out
echo 开始从Git仓库拉取最新代码 git pull echo 代码拉取完成
echo 开始打包 output=`mvn clean package -Dmaven.test.skip=true`
cd target echo 启动项目 nohup java -jar reggie_take_out-1.0-SNAPSHOT.jar &> reggie_take_out.log & echo 项目启动完成
|
3. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
进来后端全是报错,不知道什么原因,看项目是没问题的,但是我linux中的打包是自己添加的,并不是git中克隆下来的,然后把linux中app中克隆的文件删除,重新把IDEA中main和target都上传,然后再克隆下来就没问题了。
4.扩展学习部分
5.总结
今天上午考完科二,下午把项目部署到了h3c,就后端出了一点点问题,但是也成功了,还是小有成就的。明天上午缓冲一下,下午可以大概的进入SpringCloud的学习了,问题应该不是很大,可以带着vue学一下,感觉前端的知识还是很必要的,晚上整改一下图床的管理,买一个阿里云OSS图床,这样以后自己的Typora文件,发给别人图片加载不出来的情况也就没有了。上传到CSDN和Github 语雀也不会有图片不显示的情况了。