<2021SC@SDUSC>山东大学软件工程应用与实践JPress代码分析(十一)

2021SC@SDUSC

本篇文章着重围绕代码模块jpress-service,jpress-service-provider,分析PaymentRecordService、PaymentRecordServiceProvider两个类。这两个类涉及对用户支付记录的相关方法,同样与上篇文章一样,使用了缓存机制。但是本次实现的缓存机制为显式调用的方式,在文章也会作为补充内容体现。

一、PaymentRecordService

1.1 数据库表

在这里插入图片描述

1.2 PaymentRecordService

PaymentRecordService定义了支付状态操作的相关接口,在provider会给予详细实现,在这里简述接口的用途。

PaymentRecord findById(Object id);

通过id寻找商品的支付记录

List<PaymentRecord> findAll();

查询所有的支付记录

boolean deleteById(Object id);

根据id主键删除支付记录

boolean delete(PaymentRecord model);

玩过完整的model(也就是一个对象)进行支付记录的删除

Object saveOrUpdate(PaymentRecord model);

新增或者更新 Model 数据(主键值为 null 就新增,不为 null 则更新),新增或更新成功后,返回该 Model 的主键值

long findCountByColumns(Columns columns);

通过列值进行支付记录的计数

PaymentRecord findByTrxNo(String trxno);

通过支付流水号查询支付的记录

Page<PaymentRecord> paginate(int page, int pagesize, Columns columns);

支付记录使用分页机制进行分页查询与返回

PaymentRecord queryCacheByTrxno(String trx);

从缓存中得到支付记录的支付流水号对应的支付记录

void notifySuccess(long paymentId);

对对应支付记录赋予支付成功的标识

int queryMonthAmount();

月总支付记录的查询

二、Jboot缓存(显式使用)

在provider的代码中,用到了显式使用缓存的代码调用方式,因此我们需要先了解Jboot中如何配置、怎么使用缓存。

2.1 配置

默认情况下,用户无需做任何配置就可以使用 Jboot 的缓存功能,默认情况下 Jboot 是使用 caffeine 作为 Jboot 的缓存方案。

如果需要修把 caffeine 方案修改为使用 redis ,则可以添加如下的配置:

jboot.cache.type = redis

在使用 redis 作为默认的缓存方案时,需要配置上 redis 的相关信息,例如:

jboot.cache.redis.host = 127.0.0.1
jboot.cache.redis.port = 3306
jboot.cache.redis.password
jboot.cache.redis.database
jboot.cache.redis.timeout
jboot.cache.redis.clientName
jboot.cache.redis.testOnCreate
jboot.cache.redis.testOnBorrow
jboot.cache.redis.testOnReturn
jboot.cache.redis.testWhileIdle
jboot.cache.redis.minEvictableIdleTimeMillis
jboot.cache.redis.timeBetweenEvictionRunsMillis
jboot.cache.redis.numTestsPerEvictionRun
jboot.cache.redis.maxAttempts
jboot.cache.redis.maxTotal
jboot.cache.redis.maxIdle
jboot.cache.redis.maxWaitMillis
jboot.cache.redis.serializer

当,以上未配置的时候,Jboot 自动会去寻找 redis 模块来使用,redis 的配置为:

jboot.redis.host
jboot.redis.port
jboot.redis.password
jboot.redis.database
jboot.redis.timeout
jboot.redis.clientName
jboot.redis.testOnCreate
jboot.redis.testOnBorrow
jboot.redis.testOnReturn
jboot.redis.testWhileIdle
jboot.redis.minEvictableIdleTimeMillis
jboot.redis.timeBetweenEvictionRunsMillis
jboot.redis.numTestsPerEvictionRun
jboot.redis.maxAttempts
jboot.redis.maxTotal
jboot.redis.maxIdle
jboot.redis.maxWaitMillis
jboot.redis.serializer

以下是 JbootRedisCacheImpl 的部分代码:

public class JbootRedisCacheImpl extends JbootCacheBase {

    private JbootRedis redis;

    public JbootRedisCacheImpl() {
        JbootRedisCacheConfig redisConfig = Jboot.config(JbootRedisCacheConfig.class);

        //优先使用 jboot.cache.redis 的配置
        if (redisConfig.isConfigOk()) {
            redis = JbootRedisManager.me().getRedis(redisConfig);
        } 
        // 当 jboot.cache.redis 配置不存在时,
        // 使用 jboot.redis 的配置
        else {
            redis = Jboot.getRedis();
        }

        if (redis == null) {
            throw new JbootIllegalConfigException("can not get redis, please check your jboot.properties , please correct config jboot.cache.redis.host or jboot.redis.host ");
        }
    }

    //....
}

2.2 显式代码调用

Jboot 提供了一个工具类 CacheUtil,我们可以直接通过 CacheUtil 来操作缓存。

# 添加内容到缓存
CacheUtil.put("cacheName","key","value")

# 添加内容到缓存,并设置该缓存的有效期为 10 秒钟
CacheUtil.put("cacheName","key","value",10) 

# 获取缓存内容
String value = CacheUtil.get("cacheName","key");

# 删除缓存
CacheUtl.remove("cacheName","key")

# 重新设置某个缓存的有效期
CacheUtil.setTtl("cacheName","key")

当一个系统有多个缓存组件的时候,可能有 redis 或者 ehcache 等,则可以使用如下use(“type”) 进行操作。

CacheUtil.use("redis").put("cacheName","key","value")

CacheUtil.use("ehcache").put("cacheName","key","value")

三、PaymentRecordServiceProvider

实现了PaymentRecordService中的重要函数,给上层Controller的菜单操作提供接口。接下来进行provider主方法的详细解析。

3.1 findByTrxNo

@Override
public PaymentRecord findByTrxNo(String trxno) {
    return StrUtil.isBlank(trxno) ? null : DAO.findFirstByColumn(Column.create("trx_no", trxno));
}
  • 该函数通过io.jboot.utils.StrUtil的isBlank进行支付流水号是否为空的判断,,如果是就返回空,不是则返回他的支付流水号。
  • StrUtil继承自StrKit,底层继承自com.jfinal.kit.StrKit,实现了一个JPress对字符串操作的工具包,包括url解码、url重定向、map类型与string类型的相互转换、是否为空判断等等操作。

3.2 queryCacheByTrxno

@Override
public PaymentRecord queryCacheByTrxno(String trx) {
    return CacheUtil.get("payment_trx", trx);
}
  • 该函数通过io.jboot.utils.CacheUtil的get方法,从缓存中得到支付记录的支付流水号对应的支付记录,并将其以PaymentRecord对象返回。
  • CacheUtil是Jboot定义的对缓存的显式代码调用的工具类,在上文第二大点中已经对其进行介绍过。它还包含着各种对缓存的使用的函数。

3.3 notifySuccess

@Override
public void notifySuccess(long paymentId) {
    PaymentRecord payment = findById(paymentId);
    PaymentManager.me().notifySuccess(payment);
    CacheUtil.put("payment_trx", payment.getTrxNo(), payment, 60 * 60);
}
  • 通过findById方法,从数据库中找到了对应id的支付记录。
  • 调用io.jpress.core.finance中的PaymentManager类,me()返回类型为PaymentManager的一个静态对象,调用其中的notifySuccess()方法,将本身的支付状态改为支付成功。
  • 最后使用工具类设置name=“payment_trx”,key=payment.getTrxNo(),value=payment,有效时间为60分钟。

3.4 queryMonthAmount

@Override
public int queryMonthAmount() {
    return Db.queryInt("select coalesce(sum(pay_success_amount),0) from payment_record where created > ? and pay_status >= ?",
            DateUtils.truncate(new Date(), Calendar.MONTH), PayStatus.SUCCESS_ALIPAY.getStatus());
}
  • 该方法使用com.jfinal.plugin.activerecord.Db,即之前的文章中JFinal独特的DB+Record的调用方式,对每月的支出进行操作。
  • 首先采用queryInt()方法,输入sql语句与参数值。
  • 最后使用org.apache.commons.lang3.time.DateUtil进行函数的调用。
  • 参数使用truncate()方法进行赋值。

四、补充:JFinal的Cache缓存

了解Jboot中的缓存之后,在这里我们重点补充JFinal框架的缓存形式实现:ehchache。

4.1 使用 Ehcache 缓存

ActiveRecord 可以使用缓存以大大提高性能,默认的缓存实现是 ehcache,使用时需要引入 ehcache 的 jar 包及其配置文件,以下代码是Cache使用示例:

public void list() {
    List<Blog> blogList = Blog.dao.findByCache("cacheName", "key", "select * from blog");
    setAttr("blogList", blogList).render("list.html");
}

上例findByCache方法中的cacheName需要在ehcache.xml中配置如:<cache name=“cacheName” …>。此外Model.paginateByCache(…)、Db.findByCache(…)、Db.paginateByCache(…)方法都提供了cache支持。在使用时,只需传入cacheName、key以及在ehccache.xml中配置相对应的cacheName就可以了。

4.2 使用任意缓存实现

除了要把使用默认的 ehcache 实现以外,还可以通过实现 ICache 接口切换到任意的缓存实现上去,下面是个简单提示意性代码实现:

public void list() {
    List<Blog> blogList = Blog.dao.findByCache("cacheName", "key", "select * from blog");
    setAttr("blogList", blogList).render("list.html");
}

如上代码所示,MyCache 需要实现 ICache 中的四个抽象方法,然后通过下面的配置方式即可切换到自己的 cache 实现上去:

ActiveRecordPlugin arp = new ActiveRecordPlugin(...);
arp.setCache(new MyCache());

如上代码所示,通过调用 ActiveRecordPlugin.setCache(…) 便可切换 cache 实现。

五、总结

本篇文章详细分析了PaymentRecordServiceProvider——对支付记录的操作提供相关的接口,并在上一篇文章提到缓存的注解实现的基础上,详细解释了另一种显式代码的实现方式,并补充了JFinal的缓存机制与实现。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值