# 内置缓存

系统默认缓存是基于flat-cache (opens new window)的内置缓存,它是一个内存缓存,同时可以将数据保存到磁盘,重启数据不会丢失。

# 切换缓存(redis)

当然你如果觉得它不够强大,或者说你需要部署多个服务实例,你也可以随时将缓存的实现替换成其他的,如redis:

当然,官方也提供了redis插件midwayjs-cool-redis (opens new window)

yarn add midwayjs-cool-redis

src/configuration.ts 中引入组件

import { App, Configuration } from '@midwayjs/decorator';
import { ILifeCycle, IMidwayContainer } from '@midwayjs/core';
import { Application } from 'egg';
import * as orm from '@midwayjs/orm';
import * as cool from 'midwayjs-cool-core';
import * as wxpay from 'midwayjs-cool-wxpay';
import * as oss from 'midwayjs-cool-oss';
import * as redis from 'midwayjs-cool-redis';
import * as queue from 'midwayjs-cool-queue';
import * as alipay from 'midwayjs-cool-alipay';
//import * as socket from 'midwayjs-cool-socket';

@Configuration({
  // 注意组件顺序 cool 有依赖orm组件, 所以必须放在,orm组件之后 cool的其他组件必须放在cool 核心组件之后
  imports: [
    // 必须,不可移除, https://typeorm.io  打不开? https://typeorm.biunav.com/zh/
    orm,
    // 必须,不可移除, cool-admin 官方组件 https://www.cool-js.com
    cool,
    // oss插件,需要到后台配置之后才有用,默认是本地上传
    oss,
    // 将缓存替换成redis
    redis,
    // 队列
    queue,
    // 微信支付
    wxpay,
    // 支付宝支付
    alipay,
    // socket
    //socket
  ],
})
export class ContainerLifeCycle implements ILifeCycle {
  @App()
  app: Application;
  // 应用启动完成
  async onReady(container?: IMidwayContainer) {
  }
  // 应用停止
  async onStop() {}
}

登录后台管理系统,插件管理-插件列表修改redis的配置,这样整个框架的缓存就切换成了redis。

# 操作缓存

import { Inject, Provide } from '@midwayjs/decorator';
import { BaseService } from 'midwayjs-cool-core';
import { InjectEntityModel } from '@midwayjs/orm';
import { Repository } from 'typeorm';
import { DemoAppGoodsEntity } from '../entity/goods';
import { ICoolCache } from 'midwayjs-cool-core';

/**
 * 商品
 */
@Provide()
export class DemoGoodsService extends BaseService {
    @InjectEntityModel(DemoAppGoodsEntity)
    demoAppGoodsEntity: Repository<DemoAppGoodsEntity>;
    // 注入缓存实例,该缓存实例是midwayjs-cool-core组件提供的,注入它需要加命名空间前缀
    @Inject('cool:cache')
    coolCache: ICoolCache;

    /**
     * 返回所有数据
     */
    async all() {
        return this.demoAppGoodsEntity.find();
    }
}

# ICoolCache

方法 方法参数 说明
set key(缓存键): string, val(缓存值): any, ttl?(过期时间 单位:秒 不传不会过期): number 设置缓存
get key(缓存键): string 获得缓存
del key(缓存键): string 删除缓存
keys pattern?(redis模式下有效而且是必传参数,"*"为所有key): string 获得所有缓存键
getMode 获得缓存模式 local(内置) redis(redis缓存)
getMetaCache 获得原生的操作实例,如redis的客户端实例,local的flat-cache实例,可以通过这种方式操作缓存的更多方法

# 方法缓存

有些业务场景,我们并不希望每次请求接口都需要操作数据库,如:今日推荐、上个月排行榜等,数据存储在redis,注:缓存注解只在service层有效

框架提供了 @Cache 方法装饰器,方法设置缓存,让代码更优雅

import { Inject, Provide } from '@midwayjs/decorator';
import { BaseService, Cache } from 'midwayjs-cool-core';
import { InjectEntityModel } from '@midwayjs/orm';
import { Repository } from 'typeorm';
import { DemoAppGoodsEntity } from '../entity/goods';
import { ICoolCache } from 'midwayjs-cool-core';

/**
 * 商品
 */
@Provide()
export class DemoGoodsService extends BaseService {
    @InjectEntityModel(DemoAppGoodsEntity)
    demoAppGoodsEntity: Repository<DemoAppGoodsEntity>;

    // 注入缓存实例,该缓存实例是midwayjs-cool-core组件提供的,注入它需要加命名空间前缀
    @Inject('cool:cache')
    coolCache: ICoolCache;

    /**
     * 返回所有数据  
     */
    // 表示缓存数据5秒,5秒内被调用直接返回缓存中的内容,不会实际调用方法
    @Cache(5) 
    async all() {
        return this.demoAppGoodsEntity.find();
    }
}

# 注意事项

框架的缓存可以动态切换,当设置了其他缓存如redis时,框架内部会动态切换到redis缓存,但是有些情况下无法动态切换缓存。如:注入的实例为单例,单例实例框架启动就会将缓存注入好,进程级别的,这时候注入的还是内置的缓存flat-cache (opens new window),如果要使用动态缓存,需要动态获取CoolCache实例。

如中间件就是一种单例模型

import { Provide } from '@midwayjs/decorator';
import { IWebMiddleware, IMidwayWebNext } from '@midwayjs/web';
import { Context } from 'egg';

/**
 * 描述
 */
@Provide()
export class XxxMiddleware implements IWebMiddleware {
  resolve() {
    return async (ctx: Context, next: IMidwayWebNext) => {
      // 动态获得缓存实例
      const coolCache = await ctx.requestContext.getAsync('cool:cache');
      // 控制器前执行的逻辑
      const startTime = Date.now();
      // 执行下一个 Web 中间件,最后执行到控制器
      await next();
      // 控制器之后执行的逻辑
      console.log(Date.now() - startTime);
    };
  }
}