DaaS 服务端 Java二次开发指南-Lesson 3:使用和扩展UserContext

607 阅读4分钟

回到目录

Lesson 3:使用和扩展UserContext

使用UserContext

前面例子中讲到过,所有接口函数的第一个参数都是UserContext。

根据项目不同,会自动生成不同名字的UserContext类。 你有所有的源代码,可以查看相关的部分了解更多的细节。

这里简单说明一下常用的方法(以下用ctx代指usercontext对象):

发送短信

请首先在infra.properties中配置正确的短信服务参数.

默认使用阿里云短信服务,相关配置参数如下图所示:

发送短信的代码如下例:

public void useUserContext(BankUserContext ctx) throws Exception {
    String dest = "19968542341";    // 接收短信的手机号
    String fromWho = "test";        // 发送短信的‘签名’。请使用你从服务商获取的签名。
    String template = "SMS_136459";    // 短信模板代码
    Map<String, String> parameters     // 短信参数。本例需要一个 code 参数,发送验证码短信
        = MapUtil.put("code", RandomUtil.randomNum(6)).into_map(String.class);

   ctx.sendMessage(dest, fromWho, template, parameters);
}

发送邮件

请首先在infra.xml中配置正确的邮件服务参数. 默认使用阿里元短信服务,相关配置参数如下图所示:

如果不希望在XML中配置,还可以通过环境变量配置:

SMTP_SENDER_ADDRESS
SMTP_USERNAME
SMTP_HOST
SMTP_PASSWORD
SMTP_SENDER_NAME

既可以用jvm参数 -D 的形式设置,也可以在外部用环境变量的形式配置。jvm参数优先于环境变量。

发送的代码如下例:

public void useUserContext(BankUserContext ctx) throws Exception {
    String to = "user1@company1.com,user2@company2.com";
    String subject = "邮件标题";
    String content = "邮件内容";
    ctx.sendEmail(to, subject, content);
}

判断当前是否生产环境

有时需要获取当前运行的版本是否生产环境,例如在测试环境中,我们不会真的发送短信给输入的‘dest’,而是替换为一个固定的测试人员的手机号。

此时可以使用

if (ctx.isProductEnvironment()) {
    dest = getTesterMobile();
}

有时需要获取当前运行的环境名称,例如发送报告时,需要知道是从哪个运行实例发出的,此时可以使用

String evnName = ctx.getEnvironmentName();

运行环境的属性可以通过环境变量设置:

SKY_ENVIRONMENT_NAME

默认的行为是,以 product 开头的是生产环境。

也可以直接在spring xml文件中配置:

配置了‘productEnvironment’的情况下,是否生产环境以它为准; 否则用‘environmentName’的名字判断。

  • XML 中的配置,优先于环境变量配置。
  • 什么都不配置的情况下,环境名称为“dev_default”;

缓存服务

UserContext提供缓存服务,接口非常简单. 如下例:

public Object useUserContext(BankUserContext ctx) throws Exception {
    String key = ctx.tokenId()+":test_cache";
    Map<String, Object> data = MapUtil.put("name", "测试")
          .put("age", 16)
          .put("money", new BigDecimal("134.80"))
           .into_map();
    // 以上数据,缓存30分钟
    ctx.putToCache(key, data,
       (int)(30 * DateTimeUtil.MINUTE_IN_MS/DateTimeUtil.SECOND_IN_MS));
    // ...
    Thread.sleep(10*DateTimeUtil.SECOND_IN_MS);
    // 从缓存中取出数据
    Map<String, Object> cachedData = ctx.getCachedObject(key, Map.class);
    return cachedData;
}

执行结果:

扩展UserContext

userContext的创建是在代码CustomSecUserManagerImpl.java 中的 createNewConext() 例如:
protected StoredevUserContextImpl createNewConext(String path) {
    return new StoredevUserContextImpl();
}

你可以重载这个方法,来创建你的定制后的userContext实现

userContext的初始化则是在同一个类的 init() 方法中。 你可以重载这个方法,来定制你的userContext的初始化

默认的,userContext已经生成了一个层级结构:

  • 最顶层的 "UserContextImpl" 提供了基本的接口实现,在所有项目中都是通用的,请不要复写它;

  • 接下来的 "XXXUserContextImpl" 提供了项目级别的基本接口实现,由于引用了项目内的特定对象,所以命名格式为 <项目>UserContextImpl

    你可以在这里看到项目的资源文件引入,查找用户APP等基本功能。这个文件也会被自动生成,请不要复写它;

  • 再接下来的是 "XXXBizUserContextImpl" 提供了项目中业务层面的基础实现,主要是一些常用的变量在上下文中的传递功能,例如'mobile','verifyCode'这些常用的变量。

    这个文件属于‘best practice’的一部分中的‘自动生成部分’,不会被自动使用。 请不要复写它。

  • 最底层的是“CustomXXXUserContextImpl”. 这个文件属于‘best practice’的一部分中的‘定制化部分’,默认的实现是个空实现。你可以在这里添加你的定制化代码。

  • 目前生成的代码中,不是必须使用 “XXXBizUserContextImpl”和 “CustomXXXUserContextImpl”,如果要使用它,你需要在文件: SecUserCustomManagerImpl.java 中添加代码,重载函数 createNewConext:

      public class SecUserCustomManagerImpl extends CustomSecUserManagerImpl{
       
          @Override
          protected BankUserContextImpl createNewConext(String path) {
              return new CustomBankUserContextImpl();
          }
      }
    

回到目录