今日完结任务:
学习了HttpClient是什么
学习了微信小程序的开发流程
完成了苍穹外卖用户端的用户微信登录接口
完成了商品数据查看,并使它们到Redis缓存
今日收获:
1.完成了用户端的微信登录接口
微信登录流程
流程图:

步骤分析:
- 小程序端,调用wx.login()获取code,就是授权码。
- 小程序端,调用wx.request()发送请求并携带code,请求开发者服务器(自己编写的后端服务)。
- 开发者服务端,通过HttpClient向微信接口服务发送请求,并携带appId+appsecret+code三个参数。
- 开发者服务端,接收微信接口服务返回的数据,session_key+opendId等。opendId是微信用户的唯一标识。
- 开发者服务端,自定义登录态,生成令牌(token)和openid等数据返回给小程序端,方便后绪请求身份校验。
- 小程序端,收到自定义登录态,存储storage。
- 小程序端,后绪通过wx.request()发起业务请求时,携带token。
- 开发者服务端,收到请求后,通过携带的token,解析当前登录用户的id。
- 开发者服务端,身份校验通过后,继续相关的业务逻辑处理,最终返回业务数据。
接口设计
通过微信登录的流程,如果要完成微信登录的话,最终就要获得微信用户的openid。在小程序端获取授权码后,向后端服务发送请求,并携带授权码,这样后端服务在收到授权码后,就可以去请求微信接口服务。最终,后端向小程序返回openid和token等数据。
服务器端:
调用微信接口服务,获取用户唯一ID:

UserService层:

除此之外,我们也需要拦截器把未登录状态时候的一切请求进行拦截(查询餐厅状态和登录请求除外)
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getAdminTokenName());
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
log.info("当前员工id:", empId);
//通过ThreadLocal来存储empId,使得它在同一个线程的其他包中可以使用
BaseContext.setCurrentId(empId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
拦截器的思想就是校验下发的token令牌,如果令牌无法被解析或者没有令牌,说明当前用户处于未登陆状态,就不可以访问未开放的网络请求
最后我们还需要在配置类中注册拦截器
registry.addInterceptor(jwtTokenUserInterceptor)
.addPathPatterns("/user/**")
.excludePathPatterns("/user/user/login")
.excludePathPatterns("/user/shop/status");
2.学习了对菜品数据缓存的功能
用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大。就会导致用户在访问时系统响应慢、用户体验差。
实现思路

因此为了提高我们的用户效率,我们采用这样一种思想:建立一块缓存区,在用户查询对应数据的时候,先看看缓存区有没有,如果缓存区有,直接发送缓存区中的数据,如果缓存区没有,再查询数据库,并且把查询到的数据同时存到缓冲区中,便捷下次查询的效率。
而我们建立缓存区的方法是使用Redis数据库,在前面我们就介绍过Redis,他是一个存储在内存中的键值类型的数据库,这大大优化了查询效率。
代码开发
修改用户端接口 DishController 的 list 方法,加入缓存处理逻辑:
@Autowired
private RedisTemplate redisTemplate;
/**
* 根据分类id查询菜品
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
//构造redis中的key,规则:dish_分类id
String key = "dish_" + categoryId;
//查询redis中是否存在菜品数据
List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
if(list != null && list.size() > 0){
//如果存在,直接返回,无须查询数据库
return Result.success(list);
}
////////////////////////////////////////////////////////
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
//如果不存在,查询数据库,将查询到的数据放入redis中
list = dishService.listWithFlavor(dish);
////////////////////////////////////////////////////////
redisTemplate.opsForValue().set(key, list);
return Result.success(list);
}
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!
9万+

被折叠的 条评论
为什么被折叠?



