4.1.20 框架之Session

在日常开发中,我们经常需要把一些通用的信息放入程序执行的上下文中,以便业务开发人员快速获取。那么oinone的PamirsSession就是来解决此类问题的。

一、PamirsSession介绍

在oinone的体系中PamirsSession是执行上下文的承载,您能从中获取业务基础信息、指令信息、元数据信息、环境信息、请求参数,以及前后端MessageHub等。在前面的学习过程中我们已经多次接触到了如何使用PamirsSession:

  1. 在4.1.19【框架之网关协议-后端占位符】一文中,使用PamirsSession.getUserId()来获取当前登入用户Id,诸如此类的业务基础信息;

  2. 在4.1.18【框架之网关协议-variables变量】一文中,使用PamirsSession.getRequestVariables()得到PamirsRequestVariables对象,进而获取前端请求的相关信息;

  3. 在4.1.5【模型之持久层配置】一文中,使用PamirsSession.directive(),来操作元位指令系统,进而影响执行策略;

  4. 在4.1.13【Action之校验】、3.4.1【构建第一个Function】等文章中,都用到PamirsSession.getMessageHub()来设置返回消息。

二、构建模块自身Session(举例)

不同的应用场景对PamirsSession的诉求是不一样的,这个时候我们就可以去扩展PamirsSession来达到我们的目的

构建模块自身Session的步骤

  1. 构建自身特有的数据结构XSessionData

  2. 对XSessionData进行线程级缓存封装

  3. 利用Hook机制初始化XSessionData并放到ThreadLocal中

  4. 定义自身XSessionApi

  5. 实现XSessionApi接口、SessionClearApi。在请求结束时会调用SessionClearApi的clear方法

  6. 定义XSession继承PamirsSession

扩展PamirsSession的经典案例设计图

4.1.20 框架之Session

图4-1-20-1 扩展PamirsSession的经典案例设计图

构建Demo应用自身Session

下面的例子为给Session放入当前登陆用户

Step1 新建DemoSessionData类

构建自身特有的数据结构DemoSessionData,增加一个模型为PamirsUser的字段user,DemoSessionData用Data注解,注意要用Oinone平台提供的@Data

package pro.shushi.pamirs.demo.core.session;

import pro.shushi.pamirs.meta.annotation.fun.Data;
import pro.shushi.pamirs.user.api.model.PamirsUser;

@Data
public class DemoSessionData {

    private PamirsUser user;

}

图4-1-20-2 新建DemoSessionData类

Step2 新建DemoSessionCache

对DemoSessionData进行线程级缓存封装

package pro.shushi.pamirs.demo.core.session;

import pro.shushi.pamirs.meta.api.CommonApiFactory;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.user.api.model.PamirsUser;
import pro.shushi.pamirs.user.api.service.UserService;

public class DemoSessionCache {
    private static final ThreadLocal<DemoSessionData> BIZ_DATA_THREAD_LOCAL = new ThreadLocal<>();
    public static PamirsUser getUser(){
        return BIZ_DATA_THREAD_LOCAL.get()==null?null:BIZ_DATA_THREAD_LOCAL.get().getUser();
    }
    public static void init(){
        if(getUser()!=null){
            return ;
        }
        Long uid = PamirsSession.getUserId();
        if(uid == null){
            return;
        }
        PamirsUser user = CommonApiFactory.getApi(UserService.class).queryById(uid);
        if(user!=null){
            DemoSessionData demoSessionData = new DemoSessionData();
            demoSessionData.setUser(user);
            BIZ_DATA_THREAD_LOCAL.set(demoSessionData);
        }
    }
    public static void clear(){
        BIZ_DATA_THREAD_LOCAL.remove();
    }
}

图4-1-20-3 对DemoSessionData进行线程级缓存封装

Step3 新建DemoSessionHook

利用Hook机制,调用DemoSessionCache的init方法初始化DemoSessionData并放到ThreadLocal中。

@Hook(module= DemoModule.MODULE_MODULE), 规定只有增对DemoModule模块访问的请求该拦截器才会生效,不然其他模块的请求都会被DemoSessionHook拦截。

package pro.shushi.pamirs.demo.core.hook;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.api.DemoModule;
import pro.shushi.pamirs.demo.core.session.DemoSessionCache;
import pro.shushi.pamirs.meta.annotation.Hook;
import pro.shushi.pamirs.meta.api.core.faas.HookBefore;
import pro.shushi.pamirs.meta.api.dto.fun.Function;

@Component
public class DemoSessionHook implements HookBefore {
    @Override
    @Hook(priority = 1,module = DemoModule.MODULE_MODULE)
    public Object run(Function function, Object... args) {
        DemoSessionCache.init();
        return function;
    }
}

图4-1-20-4 新建DemoSessionHook

Step4 新建DemoSessionApi

package pro.shushi.pamirs.demo.core.session;

import pro.shushi.pamirs.meta.api.CommonApi;
import pro.shushi.pamirs.user.api.model.PamirsUser;

public interface DemoSessionApi extends  CommonApi {
    PamirsUser getUser();
}

图4-1-20-5 新建DemoSessionApi

Step5 新建DemoSessionHolder

  1. 实现DemoSessionApi接口

  2. 实现SessionClearApi接口,在请求结束时会调用SessionClearApi的clear方法

package pro.shushi.pamirs.demo.core.session;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.meta.api.core.session.SessionClearApi;
import pro.shushi.pamirs.user.api.model.PamirsUser;

@Component
public class DemoSessionHolder implements DemoSessionApi, SessionClearApi {
    @Override
    public PamirsUser getUser() {
        return DemoSessionCache.getUser();
    }

    @Override
    public void clear() {
        DemoSessionCache.clear();
    }
}

图4-1-20-6 新建DemoSessionHolder

Step6 新建DemoSession

package pro.shushi.pamirs.demo.core.session;

import pro.shushi.pamirs.meta.api.CommonApiFactory;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.user.api.model.PamirsUser;

public class DemoSession extends PamirsSession {
    public static PamirsUser getUser(){
        return CommonApiFactory.getApi(DemoSessionApi.class).getUser();
    }
}

图4-1-20-7 新建DemoSession

Step7 修改UserPlaceHolder

使用DemoSession.getUser().getId()替代PamirsSession.getUserId()

package pro.shushi.pamirs.demo.core.placeholder;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.core.session.DemoSession;
import pro.shushi.pamirs.user.api.AbstractPlaceHolderParser;

@Component
public class UserPlaceHolder extends AbstractPlaceHolderParser {
    @Override
    protected String value() {
        return DemoSession.getUser().getId().toString();
    }

    @Override
    public Integer priority() {
        return 10;
    }

    @Override
    public Boolean active() {
        return Boolean.TRUE;
    }

    @Override
    public String namespace() {
        return "currentUserId";
    }
}

图4-1-20-8 修改UserPlaceHolder

Step8 重启看效果

效果跟4.1.19【框架之网关协议-后端占位符】一文中的例子一样

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9295.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
史, 昂's avatar史, 昂数式管理员
Previous 2024年5月23日 am8:43
Next 2024年5月23日 am8:45

相关推荐

  • 4.2.5 框架之网络请求-Request

    在中后台业务场景中,大部分的请求时候是可以被枚举的,比如创建、删除、更新、查询。在上文中,我们讲了httpClient如何自定义请求,来实现自己的业务诉求。本文中讲到的Request是离业务更近一步的封装,他提供了开箱即用的API,比如insertOne、updateOne,它是基于HttpClient做的二次封装,当你熟悉Request时,在中后台的业务场景中,所有的业务接口自定义将事半功倍。 一、Request详细介绍 元数据-model 获取模型实例 import { getModel } from '@kunlun/dependencies' getModel('modelName'); 图4-2-5-1 获取模型实例 清除所有缓存的模型 import { cleanModelCache } from '@kunlun/dependencies' cleanModelCache(); 图4-2-5-2 清除所有缓存的模型 元数据-module 获取应用实例,包含应用入口和菜单 import { queryModuleByName } from '@kunlun/dependencies' queryModuleByName('moduleName') 图4-2-5-3 获取应用实例 查询当前用户所有的应用 import { loadModules } from '@kunlun/dependencies' loadModules() 图4-2-5-4 查询当前用户所有的应用 query 分页查询 import { queryPage } from '@kunlun/dependencies' queryPage(modelName, { pageSize: 15, // 一次查询几条 currentPage, 1, // 当前页码 condition?: '' // 查询条件 maxDepth?: 1, // 查几层模型出来,如果有2,会把所有查询字段的关系字段都查出来 sort?: []; // 排序规则 }, fields, variables, context) 图4-2-5-5 分页查询 自定义分页查询-可自定义后端接口查询数据 import { customQueryPage } from '@kunlun/dependencies' customQueryPage(modelName, methodName, { pageSize: 15, // 一次查询几条 currentPage, 1, // 当前页码 condition?: '' // 查询条件 maxDepth?: 1, // 查几层模型出来,如果有2,会把所有查询字段的关系字段都查出来 sort?: []; // 排序规则 }, fields, variables, context) 图4-2-5-6 自定义分页查询 查询一条-根据params匹配出一条数据 import { queryOne } from '@kunlun/dependencies' customQueryPage(modelName, params, fields, variables, context) 图4-2-5-7 根据params匹配出一条数据 自定义查询 import { customQuery } from '@kunlun/dependencies' customQuery(methodName, modelName, record, fields, variables, context) 图4-2-5-8 自定义查询 update import { updateOne } from '@kunlun/dependencies' updateOne(modelName, record, fields, variables, context) 图4-2-5-9 update insert import { insertOne } from '@kunlun/dependencies' insertOne(modelName, record, fields, variables, context) 图4-2-5-10 insert delete import { deleteOne } from '@kunlun/dependencies'…

    2024年5月23日
    1.8K00
  • 陈浩

    自2017年中国推进数字建设以来,数字经济规模持续增长,“十四五”规划和2035远景目标纲要中明确强调企业和政府需大力推动数字化转型,中国正在迈进一个崭新的数字经济时代。 在这个过程中,软件已经从工具变成信息化的基础设施,如何有效应对该变化所带来的一系列新的核心技术挑战,是整个软件行业发展遇到的另一难题。我认为,开源创新是解决这些难题的有效手段之一,也是未来软件发展的重要方向。如果说,数字化转型是时代趋势,那么开源创新也已成为时代主流。十四五规划纲要首提开源,2021年11月工信部印发《十四五软件和信息技术服务业发展规划》中提到开源重塑软件发展新生态,并将开源重塑软件发展新生态作为十四五期间我国软件产业的四大发展形势之一进行重点阐述。支持国产化开源创新体系发展,建设自己的开源社区和开源平台,其所具有的大众协同、开放共享、持续创新等特点,可有效推动各行业自主可控的数字化转型。 Oinone所倡导的开源理念和生态共建,与国家开源战略不谋而合:将开源作为一种合作手段,通过完善社区注重开源治理,吸引更多的企业和个体参与其中。湖南大学作为首批国家示范性软件学院的双一流建设高校,一直致力于推进和引导国产化开源软件体系的建设,并为此开展多种形式的产学研研究和实践。基于Oinone微服务分布式的设计理念和面向生态的开源特性,湖南大学结合自身在大数据分布式存储、多元异构数据汇聚融合和大数据智能分析等方面的研究成果,与Oinone展开了深度的技术创新合作,并在多个大中型企业数字化应用和数字政府应用中取得了良好的效果。 随着Oinone的开源,相信能激发更多的开发者参与到国产软件建设中,通过开源模式实现更广泛参与方的共享、共创、共生、共赢,构建价值驱动的数字创新生态平台,为我国数字经济发展贡献科技力量。 湖南大学教授:陈浩

    Oinone 7天入门到精通 2024年5月23日
    2.3K00
  • 4.1.6 模型之元数据详解

    介绍Model相关元数据,以及对应代码注解方式。大家还是可以通读并练习每种不同的使用方式,这个是oinone的设计精华所在。当您不知道如何配置模型、字段、模型间的关系、以及枚举都可以到这里找到。 一、模型元数据 安装与更新 使用@Model.model来配置模型的不可变更编码。模型一旦安装,无法在对该模型编码值进行修改,之后的模型配置更新会依据该编码进行查找并更新;如果仍然修改该注解的配置值,则系统会将该模型识别为新模型,存储模型会创建新的数据库表,而原表将会rename为废弃表。 如果模型配置了@Base注解,表明在studio中该模型配置不可变更;如果字段配置了@Base注解,表明在studio中该字段配置不可变更。 注解配置 模型类必需使用@Model注解来标识当前类为模型类。 可以使用@Model.model、@Fun注解模型的模型编码(也表示命名空间),先取@Model.model注解值,若为空则取@Fun注解值,若皆为空则取全限定类名。 模型元信息 模型的priority,当展示模型定义列表时,使用priority配置来对模型进行排序。 模型的ordering,使用ordering属性来配置该模型的数据列表的默认排序。 模型元信息继承形式: 不继承(N) 同编码以子模型为准(C) 同编码以父模型为准(P) 父子需保持一致,子模型可缺省(P=C) 注意:模型上配置的索引和唯一索引不会继承,所以需要在子模型重新定义。数据表的表名、表备注和表编码最终以父模型配置为准;扩展继承父子模型字段编码一致时,数据表字段定义以父模型配置为准。 名称 描述 抽象继承 同表继承 代理继承 多表继承 基本信息 displayName 显示名称 N N N N summary 描述摘要 N N N N label 数据标题 N N N N check 模型校验方法 N N N N rule 模型校验表达式 N N N N 模型编码 model 模型编码 N N N N 高级特性 name 技术名称 N N N N table 逻辑数据表名 N P=C P=C N type 模型类型 N N N N chain 是否是链式模型 N N N N index 索引 N N N N unique 唯一索引 N N N N managed 需要数据管理器 N N N N priority 优先级,默认100 N N N N ordering 模型查询数据排序 N N N N relationship 是否是多对多关系模型 N N N N inherited 多重继承 N N N N unInheritedFields 不从父类继承的字段 N N N N unInheritedFunctions 不从父类继承的函数 N N N N 高级特性-数据源 dsKey 数据源 N P=C P=C N 高级特性-持久化 logicDelete 是否逻辑删除 P P P N logicDeleteColumn 逻辑删除字段 P P P N logicDeleteValue 逻辑删除状态值 P P P N logicNotDeleteValue 非逻辑删除状态值 P P P N underCamel 字段是否驼峰下划线映射 P P P N capitalMode 字段是否大小写映射…

    2024年5月23日
    1.7K00
  • 书籍封面

    2024年5月23日
    3.6K00
  • 6.5 权限体系(改)

    做好企业级软件,首先得过权限这一关 在企业的IT部门沟通中,权限是避免不了。自嘲下在我们刚出来创业时,为了收获客户对我们技术能力的信任,每每与跟客户沟通时都会说我们是阿里出来的,但在权限设计这个环节不那么灵验,反而被打上了不懂B端权限设计的标签,会问很多问题。我就很奇怪难道大厂就没有内部管理系统了?大厂只有C端交易,没有B端交易?但从侧面说明权限不简单还特别重要。做好企业级软件,首先得过权限这一关。 整体介绍 对于平台运行来说,权限是必须,但我们的auth模块不是必须的,auth模块只是我们提供的一种默认实现,客户可以根据平台的spi机制进行替换。auth模块利用了平台的Hook特性做到与业务无关,在我们开发上层应用的时,是不用感知它的存在的。 auth模块涉及:功能权限、数据权限 数据权限:行权限和列权限。备注:数据权限的控制只能用于【存储模型】 表级权限:表达的语义是:是否该表可读/写(修改和新增) 列权限:表达的语义是:是否该列可读/写(修改和新增) 行权限:表达的语义是:是否对该行可读/写(修改)/删除 功能权限:表达的语义是ServerAction/Function是否可执行/展示,viewAction是否可展示,菜单是否可以显示 范围说明: 配置多个权限项的时候,取并集 配置多个角色的时候,取并集 模型设计 产品体验 Step1 创建角色 通过App Finder 切换至【权限】应用,点击新增按钮创建一个名为oinone的角色 Step2 创建数据权限项 在【权限项列表】菜单,点击【创建】按钮新增一个名为【宠物达人数据权限项】,同时宠物达人的数据权限设置为只能查看性别为男的记录 配置说明: 名称: 代表该项配置的权限的名字(必填)(必须是全系统唯一) 权限模型: 选择需要拦截的数据所在的表,即为模型,可以搜索使用 描述:对该权限项的描述 权限条件的配置: 满足全部:对条件一和条件二要同时满足的数据才能被看见 满足任一:对条件一和条件二要任意满足的数据都能被看见 读权限:对该数据是否有读取的权限 写权限:对该数据是否有修改的权限 删除权限:对该条件内的数据是否有删除的权限 Step3 为角色配置权限 编辑oinone角色,只开通oinoneDemo工程应用 选中【数据权限】选项卡点击【添加】按钮,勾选宠物达人数据权限项点击【确定】按钮 整体点击保存,回到列表页记得点击【权限生效】按钮 Step4 新建用户绑定角色 切换到用户中心模块,点击【创建】按钮填写必要信息,并在角色选中oinone权限组。 退出admin用户,用oinone登陆,权限效果: 只能看见demo模块 oinone登陆只能看到性别为男的宠物达人记录 admin用户登陆 oinone用户登陆 因为宠物达人的页面没有把性别字段放出来,我们看下数据库数据 auth模块扩展 在日常项目开发中,难免会碰到一些针对权限管理的特殊需求,或是为提升性能做的特殊逻辑。接下来我给大家介绍auth模块扩展性。 权限全局配置 对所有权限角色都做限制,而且不想让用户感知,可以实现PermissionFunApi接口,API接口实现的配置方式【只能用于支持全局的数据权限配置】 实现接口PermissionFunApi 将实现托管给SpringAOP 接口的具体实现看下图的代码 package pro.shushi.pamirs.demo.core.service; import org.springframework.stereotype.Component; import pro.shushi.pamirs.auth.api.service.PermissionFunApi; import pro.shushi.pamirs.demo.api.model.PetTalent; @Component public class PetTalentPermissionFunApi implements PermissionFunApi { @Override public String permissionDomain(Object… args) { //获取当前组织中 return "name == '张学友'"; } @Override public String nameSpace() { return PetTalent.MODEL_MODEL; } } 不参与权限控制 如果某一接口不想做权限控制,则可以在启动工程的application-dev.yml文件中配置不需要权限过滤的接口 pamirs: auth: fun-filter: – namespace: demo.PetTalent fun: queryPage 换一个没有配置宠物达人权限的用户(除管理员以外)进入系统,则也可以看到数据。注意【权限全局控制】还是生效的 API 1. 获取当前用户对该模型的行权限 Result<String> result = CommonApiFactory.getApi(AuthApi.class).canReadAccessData("Model"); 返回值为 { 'data':"name=in=('hahaha')" 'success':true … } 用法 : 场景:前端发起的请求都会经过权限拦截,后端代码逻辑发起的数据请求都是不经过任何权限的过滤,但是某些特殊情况需要在后端代码逻辑发起的数据请求也带上权限过滤 入参:请求的模型 出参:Result 数据结构中data会存储一段字符串,该字符串为Rsql 将该Rsql追加到wrapper中 Result<String> result = CommonApiFactory.getApi(AuthApi.class).canReadAccessData("base.UeModule"); String data=result.getData(); QueryWrapper<UeModule> wrapper = Pops.query(); wrapper.setEntity(ueModule); if (!StringUtils.isBlank(data)) { wrapper.apply(data); }

    2024年5月23日
    1.9K00

Leave a Reply

Please Login to Comment