回到目录
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中配置正确的邮件服务参数. 默认使用阿里元短信服务,相关配置参数如下图所示:
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(); } }