苍穹外卖零碎知识

最最重要的是理解项目的逻辑,只有深刻理解了这个项目是干啥的,各个数据库之间有啥联系等逻辑才能更好的写代码。

我个人喜好按层分。Pojo,controller,service,Dao层。
 

层名注释名注释作用
Pojo@Component
@Data产生get和set方法
Controller@RestController@Controller+@RespondBody
@RequestMapping设置默认访问路径
@ApiSwgger注解
@RequestBody把传进来的请求体转为对应的实体类
@RequestParamurl里获取查询参数,例如?name=liming
@PathVariable获取路径参数,/depts/{id}

AOP,面向切面编程,就是把某个方法无痛前面加上一些命令,后面加上一些命令。

一般用*来省略包名和类名而不用..

方法参数一般用..

1. 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)

2. 通知:Advice,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法)

3. 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用
在aop的开发当中,我们通常会通过一个切入点表达式来描述切入点

4. 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
当通知和切入点结合在一起,就形成了一个切面。通过切面就能够描述当前aop程序需要针对于哪个原始方法,在什么时候执行什么样的操作。
5. 目标对象:Target,通知所应用的对象

(这样看来,连接点不一定是切入点,但切入点一定是连接点。)

定义全局异常处理器非常简单,就是定义一个类,在类上加上一个注解

@RestControllerAdvice,加上这个注解就代表我们定义了一个全局异常处理器。

在全局异常处理器当中,需要定义一个方法来捕获异常,在这个方法上需要加上注解@ExceptionHandler。通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常

一般在mapper里加AOP的annotation注解

再学一下javase的反射

获取joinPoint的方法签名(因为传进来的示例通常只有一个方法,所以直接获取到了需要的方法签名)

MethodSignature signature = (MethodSignature) joinPoint.getSignature();

获取该方法上的切面注解实例

切面注解名 小写切面注解名 = signature.getMethod().getAnnotation(自定义的切面注解名.class)

获取该切面注解实例的值,以便后续对连接点进行操作

OperationType operationType = autoFill.value();

获取到当前被拦截的方法(连接点)的参数--实体对象

Object[] args = joinPoint.getArgs();

因为被拦截的方法是我们自己定义的,所以参数有啥咱们门清,直接需要哪个参数就提取哪个参数

Object entity = args[0];

获取该实体对象的需要的方法,第一个参数是方法名,第二个是方法的参数的类型

Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);

利用反射将该entity属性赋值

setCreateTime.invoke(entity,now);

以上一系列操作是把mapper层传入的DTO内的属性进行修改,真正将DTO数据写入数据库仍需在sql语句中实现。

String objectName = UUID.randomUUID().toString() + extension;
String filePath = aliOssUtil.upload(file.getBytes(), objectName);
return Result.success(filePath);

文件上传功能直接调用接口得了,记得是返回个文件地址字符串就行。

分页查询时,PageHelper.starPage后跟mapper.pageQuery(DTO),查询结果返回的是许多VO,把这许多VO装到Page这个容器里,所以变成Page<VO> page = mapper.pageQuery(DTO)。把Page看成list就行。

page有getTotal和getResult方法,得到总数据条数和多条VO数据。

mapper层返回Page<数据库数据类型>类

service层返回的是PageResult类。return new PageResult(page.gettotal(),page.getResult);

controller层里,如果当前端传入的字段很多时,我们常常用DTO来作为controller的方法参数,此时不能给DTO加@RequestParam,因为spring会将传入的字段名和DTO的属性名一一对应,能对应上就给DTO的属性赋值。

如果我们不使用DTO,就想一个一个来创建方法参数,此时就要使用@RequestParam了。

总结,DTO不加@RequestParam。多个方法参数要使用@RequestParam

@RequestBody是接受json参数(请求体)的。例如客户端采用put方式,就会给服务端传送一个json数据{ "id": 12345 }。如果我们使用@RequestBody Long id是不对的,因为这个意思是Spring Boot 期望接收到的请求体是一个纯数字。但是收到的请求体一定是个json,所以我们应该创建个DTO来接收json数据。总结,客户端传来的json数据一定要用DTO接收。

@PathVariable接受路径参数。(URL里有{}占位符)

@RequestParam接受查询参数(URL后接?查询字符串)@RequestParam(“begin”)如果不加注释,也可以,但是要求客户端传来的查询参数名和controller的方法形参名一模一样。

Jwt令牌创建在controller层的登录方法里。

jwt令牌的claims可以填入啥内容由JwtClaimsConstant规定。

jwt的秘匙作用是和header和claims结合,生成signature。

controller层登录逻辑:
用传入得DTO调用service层,当service遇到用户名不正确或密码不正确等问题时,自会抛出异常。当都对得适合,service就会返回一个entity。之后再根据entity得id生成个hashmap的claims。然后再用jwtProperties的keysecret和ttl(过期时间)来制作jwt字符串。再把这个字符串传入VO,最后返回Result(VO)。

当前端传入请求时,会携带jwt令牌(除登录外),所以在任何请求前都要校验jwt令牌是否存在,jwt令牌是否正确。此时可以用interceptor拦截器。

AOP和拦截器

拦截器拦截的是URL,request,response。可以获取执行的方法的名称,请求(HttpServletRequest),可以控制请求的控制器和方法,但控制不了请求方法里的参数(只能获取参数的名称,不能获取到参数的值)

AOP拦截的是方法,可以获取执行方法的参数( ProceedingJoinPoint.getArgs() ),然后对方法的参数进行修改(比如给参数的属性赋值)

redis的opsForValue.get(key)在java中不仅可以取字符串,你放进去是啥就可以取出啥,但是要加强转 List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);

全局工具类BaseContext,现在个人理解就是,因为它都用得static,所以是类变量和类方法,整个JVM里只有一个,所以可以全局调用。

因为用户端的显示是按照分类显示的,所以按照分类ID来把数据库内的菜品和套餐缓存到Redis内存。

用户端查询时,如果redis没有缓存,那么从数据库查,再插入到redis。如果redis有缓存,则直接返回缓存的数据。

管理端插入新数据,修改数据,删除数据时,防止redis和数据库数据不一致,进行删除redis内缓存操作。

chacheable一般用在用户端的查询上。但是当controller方法的返回值是Result时,redis里缓存的value就是Result。所以

cacheevict一般用在管理端的增删改上。

购物车用注释的时候的逻辑:

首先原来代码的list返回的是个Result,里面带着从数据库查询的数据。当给这个方法加上Cacheable后,每次调用list方法时都先从Redis里通过注释里设置的key查找有没有这个Result的value;如果有则直接让list方法返回这个Result;没有的话调用service的语句,正常走list的逻辑最后返回Result,然后把这个Result添加到redis里。

原来代码的save和delete都是修改了数据库内容,此时数据库内容和redis的内容就不一致了,需要将redis的内容和数据库内容同步。因为运行save和delete之后必定会运行list,所以只需要让save和delete之后把redis内容清空,再运行list时,就会因为redis内容为空,正常走list语句从数据库查询后,再将Result存入redis,此时redis就和数据库内容一致了。(利用了Cacheable的如果内存没有则从数据库查询的特性,巧妙使用cacheevict)

如果不用注释也可以直接调用redistemplate的语句对redis进行操作。

application.properties是springboot中属性注入的默认文件。

application.properties与 application.yaml都可以作为Spring Boot的配置文件,只是书写格式不同而已。但同级目录下读取的顺序是先读取application.properties,读取application.yaml。

开发SpringBoot应用的时候,通常程序需要在测试环境测试成功后才会上线到生产环境。而测试环境和生产环境的数据库地址、服务器端口等配置都不同。在为不同环境打jar包时,需要频繁的修改application.yml配置文件,十分麻烦。
可以采用创建多个配置文件的方法解决这一问题。

创建以下三个文件,配置不同环境的地址信息,存放在application.yml同一目录下:

application-dev.yml:本地开发环境
application-test.yml:测试环境
application-prod.yml:生产环境

默认情况下,一开始创建spring boot 项目只有application.properties文件,没有xxxx.yml文件。

其中application.yml存放公共配置,可通过修改active切换读取的配置文件,比如active: dev改成active: test就是将读取application-dev.yml改为application-test.yml,环境也从本地开发变成了测试环境

也就是先寻找active指定的配置文件里面的内容,如果没有找到则去找application.yml中的内容。

一般会在XxProperties类里使用@ConfigurationProperties(prefix = "sky.jwt")来进行属性注入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值