如何重写获取首页的方法

介绍

用户登录成功后或者访问网页不带任何路由参数的时候前端会请求全局的首页的视图动作viewAction配置,然后跳转到该视图动作viewAction
如何重写获取首页的方法

方案

我们可以通过在该方法的后置hook自定义获取首页的逻辑,下面以按角色跳转不同首页的需求示例

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

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.auth.api.model.AuthRole;
import pro.shushi.pamirs.boot.base.enmu.BaseExpEnumerate;
import pro.shushi.pamirs.boot.base.model.ViewAction;
import pro.shushi.pamirs.boot.web.loader.PageLoadAction;
import pro.shushi.pamirs.demo.api.model.DemoItemCategory;
import pro.shushi.pamirs.demo.api.model.DemoItemLabel;
import pro.shushi.pamirs.meta.annotation.Hook;
import pro.shushi.pamirs.meta.api.CommonApiFactory;
import pro.shushi.pamirs.meta.api.core.faas.HookAfter;
import pro.shushi.pamirs.meta.api.dto.fun.Function;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.meta.common.exception.PamirsException;
import pro.shushi.pamirs.user.api.model.PamirsUser;

import java.util.List;
import java.util.stream.Collectors;

@Component
public class DemoHomepageHook implements HookAfter {

    private static final String TEST_ROLE_CODE_01 = "ROLE_1211";
    private static final String TEST_ROLE_CODE_02 = "ROLE_1211_1";

    @Override
    @Hook(module = {"base"}, model = {ViewAction.MODEL_MODEL}, fun = {"homepage"})
    public Object run(Function function, Object ret) {
        if (ret == null) {
            return null;
        }
        ViewAction viewAction = getViewActionByCurrentRole();
        if (viewAction != null) {
            ViewAction retNew = CommonApiFactory.getApi(PageLoadAction.class).load(viewAction);
            ViewAction viewActionRet = (ViewAction) ((Object[]) ret)[0];
            viewActionRet.set_d(retNew.get_d());
        }
        return ret;
    }

    protected ViewAction getViewActionByCurrentRole() {
        try {
            PamirsUser user = new PamirsUser();
            user.setId(PamirsSession.getUserId());
            user.fieldQuery(PamirsUser::getRoles);
            List<AuthRole> roles = user.getRoles();
            if (CollectionUtils.isNotEmpty(roles)) {
                List<String> roleCodes = roles.stream().map(AuthRole::getCode).collect(Collectors.toList());
                if (roleCodes.contains(TEST_ROLE_CODE_01)) {
                    return new ViewAction().setModel(DemoItemCategory.MODEL_MODEL).setName("DemoMenus_ItemPMenu_DemoItemAndCateMenu_DemoItemCategoryMenu").queryOne();
                } else if (roleCodes.contains(TEST_ROLE_CODE_02)) {
                    return new ViewAction().setModel(DemoItemLabel.MODEL_MODEL).setName("DemoMenus_ItemPMenu_DemoItemAndCateMenu_DemoItemLabelMenu").queryOne();
                }
            }
        } catch (PamirsException exception) {
            if (PamirsSession.getUserId() == null) {
                throw PamirsException.construct(BaseExpEnumerate.BASE_USER_NOT_LOGIN_ERROR, exception.getCause()).errThrow();
            } else {
                throw exception;
            }
        }
        return null;
    }
}

Oinone社区 作者:nation原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/14500.html

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

Like (0)
nation's avatarnation数式员工
Previous 2024年7月5日 pm10:49
Next 2024年7月9日 pm8:59

相关推荐

  • 函数之触发与定时配置和示例

    异步任务总体介绍 函数的触发和定时在很多场景中会用到,也是一个oinone的基础能力。比如我们的流程产品中在定义流程触发时就会让用户选择模型触发还是时间触发,就是用到了函数的触发与定时能力。 触发任务TriggerTaskAction 触发任务的创建,使用sql-record模块监听mysql的binlog事件,通过rocketmq发送变更数据消息,收到MQ消息后,创建TriggerAutoTask。 触发任务的执行,使用TBSchedule拉取触发任务后,执行相应函数。 项目中引入依赖 1、项目的API工程引入依赖pamirs-core-trigger模块 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-api</artifactId> </dependency> 2、DemoModule在模块依赖定义中增加@Module(dependencies={TriggerModule.MODULE_MODULE}) @Component @Module( name = DemoModule.MODULE_NAME, displayName = "oinoneDemo工程", version = "1.0.0", dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE, UserModule.MODULE_MODULE, TriggerModule.MODULE_MODULE} ) @Module.module(DemoModule.MODULE_MODULE) @Module.Advanced(selfBuilt = true, application = true) @UxHomepage(PetShopProxy.MODEL_MODEL) public class DemoModule implements PamirsModule { ……其他代码 } 3、项目的boot工程引入依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-core</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-bridge-tbschedule</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-sql-record-core</artifactId> </dependency> yml文件修改(applcation-xxx.yml) a. 修改pamris.event.enabled和pamris.event.schedule.enabled为trueb. pamirs_boot_modules增加启动模块:trigger、sql_record pamirs: record: sql: #改成自己路径 store: /opt/pamirs/logs … event: enabled: true schedule: enabled: true rocket-mq: namesrv-addr: 127.0.0.1:9876 boot: init: true sync: true modules: – base -…… – trigger – sql_record -…… 新建触发任务 新建PetTalentTrigger类,当PetTalent模型的数据记录被新建时触发系统做一些事情 package pro.shushi.pamirs.demo.core.trigger; import pro.shushi.pamirs.demo.api.model.PetTalent; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.trigger.annotation.Trigger; import pro.shushi.pamirs.trigger.enmu.TriggerConditionEnum; @Fun(PetTalent.MODEL_MODEL) @Slf4j public class PetTalentTrigger { @Function @Trigger(displayName = “PetTalent创建时触发”,name = “PetTalent#Trigger#onCreate”,condition = TriggerConditionEnum.ON_CREATE) public PetTalent onCreate(PetTalent data){ log.info(data.getName() + “,被创建”); //可以增加逻辑 return data; } } 定时任务 定时任务是一种非常常见的模式,这里就不介绍概念了,直接进入示例环节 新建PetTalentAutoTask实现ScheduleAction getInterfaceName()需要跟taskAction.setExecuteNamespace定义保持一致,都是函数的命名空间 taskAction.setExecuteFun("execute");跟执行函数名“execute”一致 TaskType需配置为CYCLE_SCHEDULE_NO_TRANSACTION_TASK,把定时任务的schedule线程分开,要不然有一个时间长的任务会导致普通异步或触发任务全部延时。 package pro.shushi.pamirs.demo.core.task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import pro.shushi.pamirs.core.common.enmu.TimeUnitEnum; import pro.shushi.pamirs.demo.api.model.PetTalent; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.meta.domain.fun.FunctionDefinition; import pro.shushi.pamirs.middleware.schedule.api.ScheduleAction; import pro.shushi.pamirs.middleware.schedule.common.Result; import pro.shushi.pamirs.middleware.schedule.domain.ScheduleItem; import pro.shushi.pamirs.middleware.schedule.eunmeration.TaskType; import pro.shushi.pamirs.trigger.enmu.TriggerTimeAnchorEnum; import pro.shushi.pamirs.trigger.model.ScheduleTaskAction; import pro.shushi.pamirs.trigger.service.ScheduleTaskActionService; @Slf4j @Component @Fun(PetTalent.MODEL_MODEL) public class PetTalentAutoTask implements…

    2024年5月25日
    1.9K00
  • 多模型联表查询

    多模型联表查询 多对一或者一对一关联关系,通过关联模型的字段查询数据 模型结构定义 模型A @Model(displayName = "A") @Model.model(A.MODEL_MODEL) public class A extends IdModel { public final static String MODEL_MODEL = "test.A"; @Field(displayName = "b") @Field.many2one @Field.Relation(relationFields = {"bId"}, referenceFields = {"id"}) private B b; @Field(displayName = "bId") @Field.Integer private Long bId; @Field(displayName = "B审批状态") @Field.Enum @Field.Related(related = {"b", "approvalEnum"}) private ApprovalEnum approvalEnum; } 模型B @Model(displayName = "B") @Model.model(B.MODEL_MODEL) public class B extends IdModel { public final static String MODEL_MODEL = "test.B"; @Field(displayName = "审批状态") @Field.Enum private ApprovalEnum approvalEnum; } 页面设计 在界面设计器中, 设计相对应的表格页面。 A模型related字段拖到搜索栏中。 发布页面 自定义Hook import cz.jirutka.rsql.parser.ast.RSQLOperators; import org.apache.commons.lang3.ArrayUtils; import org.springframework.stereotype.Component; import pro.shushi.pamirs.framework.connectors.data.sql.AbstractWrapper; import pro.shushi.pamirs.framework.connectors.data.sql.query.QueryWrapper; import pro.shushi.pamirs.meta.annotation.Hook; import pro.shushi.pamirs.meta.api.Models; import pro.shushi.pamirs.meta.api.core.faas.HookBefore; import pro.shushi.pamirs.meta.api.core.orm.convert.ClientDataConverter; import pro.shushi.pamirs.meta.api.core.orm.template.context.ModelComputeContext; import pro.shushi.pamirs.meta.api.dto.config.ModelConfig; import pro.shushi.pamirs.meta.api.dto.config.ModelFieldConfig; import pro.shushi.pamirs.meta.api.dto.fun.Function; import pro.shushi.pamirs.meta.api.session.PamirsSession; import pro.shushi.pamirs.meta.base.D; import pro.shushi.pamirs.meta.common.spi.Spider; import pro.shushi.pamirs.meta.domain.model.ModelField; import pro.shushi.pamirs.meta.enmu.TtypeEnum; import pro.shushi.pamirs.resource.api.constants.FieldConstants; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 通用 queryData处理。 */ @Slf4j @Component public class QueryDataHook implements HookBefore { @Override @Hook(priority = 30) public Object run(Function function, Object… args) { getValueByType(args); return function; } private void getValueByType(Object… args) { if (ArrayUtils.isEmpty(args)) { return; } for (int index = 0; index < args.length &&…

    2025年1月9日
    2.1K00
  • Excel导入扩展点-整体导入(批量导入)

    1、【导入】在有些场景,需要获取Excel导入的整体数据,进行批量的操作或者校验 可以通过实现导入扩展点的方式实现,入参data是导入Excel的数据列表;业务可以根据实际情况进行数据校验 1)Excel模板定义,需要设置setEachImport(false) 2)导入扩展点API定义 pro.shushi.pamirs.file.api.extpoint.ExcelImportDataExtPoint#importData 3)示例代码参考: pro.shushi.pamirs.translate.extpoint.ResourceTranslationImportExtPoint#importData @Slf4j @Component @Ext(ExcelImportTask.class) public class ResourceTranslationImportExtPoint extends AbstractExcelImportDataExtPointImpl<List<ResourceTranslationItem>> { @Override //TODO 表达式,可以自定义,比如可以支持1个模型的多个【导入名称】的不同模板 @ExtPoint.Implement(expression = "importContext.definitionContext.model==\"" + ResourceTranslation.MODEL_MODEL + "\"") public Boolean importData(ExcelImportContext importContext, List<ResourceTranslationItem> dataList) { //TODO dataList就是excel导入那个sheet的所有内容 return true; } } 2、【导入】逐行导入的时候做事务控制 在模板中定义中增加事务的定义,并设置异常后回滚。参加示例代码: excel模板定义 @Component public class DemoItemImportTemplate implements ExcelTemplateInit { public static final String TEMPLATE_NAME = "商品导入模板"; @Override public List<ExcelWorkbookDefinition> generator() { //定义事务(导入处理中,只操作单个表的不需要事务定义。) //是否定义事务根据实际业务逻辑确定。比如:有些场景在导入前需要删除数据后在进行导入就需要定义事务 InitializationUtil.addTxConfig(DemoItem.MODEL_MODEL, ExcelDefinitionContext.EXCEL_TX_CONFIG_PREFIX + TEMPLATE_NAME); return Collections.singletonList( ExcelHelper.fixedHeader(DemoItem.MODEL_MODEL, TEMPLATE_NAME) .setType(ExcelTemplateTypeEnum.IMPORT) .createSheet("商品导入-sheet1") .createBlock(DemoItem.MODEL_MODEL) .addUnique(DemoItem.MODEL_MODEL,"name") .addColumn("name","名称") .addColumn("description","描述") .addColumn("itemPrice","单价") .addColumn("inventoryQuantity","库存") .build().setEachImport(true) //TODO 设置异常后回滚的标识,这个地方会回滚事务 .setHasErrorRollback(true) .setExcelImportMode(ExcelImportModeEnum.SINGLE_MODEL) ); } } 导入逻辑处理 @Slf4j @Component @Ext(ExcelImportTask.class) public class DemoItemImportExtPoint extends AbstractExcelImportDataExtPointImpl<DemoItem> implements ExcelImportDataExtPoint<DemoItem> { @Autowired private DemoItemService demoItemService; @Override @ExtPoint.Implement(expression = "importContext.definitionContext.model == \"" + DemoItem.MODEL_MODEL + "\"") public Boolean importData(ExcelImportContext importContext, DemoItem data) { ExcelImportTask importTask = importContext.getImportTask(); try { DemoItemImportTask hrExcelImportTask = new DemoItemImportTask().queryById(importTask.getId()); String publishUserName = Optional.ofNullable(hrExcelImportTask).map(DemoItemImportTask::getPublishUserName).orElse(null); data.setPublishUserName(publishUserName); demoItemService.create(data); } catch(PamirsException e) { log.error("导入异常", e); } catch (Exception e) { log.error("导入异常", e); } return Boolean.TRUE; } }

    2023年12月7日
    2.3K00
  • 模型字段之序列化方式

    本文核心是带大家全面了解oinone的序列方式,包括支持的序列化类型、注意点、如果新增客户化序列化方式以及字段默认值的反序列化。 字段序列化方式说明 序列化方式 说明 备注 JSON JSON序列化 主要用于模型相关类型字段的序列化,是@Field.serialize默认选项 DOT 点拼接集合元素 COMMA 逗号拼接集合元素 BIT 按位与,2次幂数求和 非@Field.serialize可选项列表,用于二进制枚举序列化不需要配置,由oinone自动推断 字段序列化方式举例 1、给模型PetItemDetail 增加两个字段:petItemDetails类型为List 和 tags类型为List,并设置为不同的序列化方式,petItemDetails为JSON(缺省就是JSON,可不配),tags为COMMA。2、同时设置 @Field.Advanced(columnDefinition = "varchar(1024)"),防止序列化后存储过长。 @Model.model(PetItem.MODEL_MODEL) @Model(displayName = "宠物商品",summary="宠物商品",labelFields = {"itemName"}) public class PetItem extends AbstractDemoCodeModel{ public static final String MODEL_MODEL="demo.PetItem"; @Field(displayName = "品种") @Field.many2one @Field.Relation(relationFields = {"typeId"},referenceFields = {"id"}) private PetType type; @Field(displayName = "品种类型",invisible = true) private Long typeId; @Field(displayName = "详情", serialize = Field.serialize.JSON, store = NullableBoolEnum.TRUE) @Field.Advanced(columnDefinition = "varchar(1024)") private List<PetItemDetail> petItemDetails; @Field(displayName = "商品标签",serialize = Field.serialize.COMMA,store = NullableBoolEnum.TRUE,multi = true) @Field.Advanced(columnDefinition = "varchar(1024)") private List<String> tags; } 字段序列化注意点 必须使用Field#store属性将字段存储设置为NullableBoolEnum.TRUE。 使用Field#serialize属性指定序列化方式,默认为JSON。 如把PetItemDetail设置为存储模型,须在PetItem的petItemDetails字段上使用Field.Relation#store属性将关联关系存储设置为false。不然会同时存储petItemDetails字段和对应的PetItemDetail表记录 注册自己的序列化器 注册自己的序列化器(实现pro.shushi.pamirs.meta.api.core.orm.serialize.Serializer接口), 如oinone的DOT的序列化方式,用type()方法返回值做匹配,serialize和deserialize分别对应序列化和反序列化方法。 package pro.shushi.pamirs.framework.compute.serialize; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.meta.api.core.orm.serialize.Serializer; import pro.shushi.pamirs.meta.common.constants.CharacterConstants; import pro.shushi.pamirs.meta.enmu.SerializeEnum; import pro.shushi.pamirs.meta.util.TypeUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 点表达式序列生成处理器实现 * @author shushi@shushi.pro * @version 1.0.0 */ @SuppressWarnings("rawtypes") @Slf4j @Component public class DotSerializeProcessor implements Serializer<Object, String> { @Override public String serialize(String ltype, Object value) { if (null == value) { return null; } if (List.class.isAssignableFrom(value.getClass())) { return StringUtils.join((List) value, CharacterConstants.SEPARATOR_DOT); } else { return StringUtils.join(Collections.singletonList(value), CharacterConstants.SEPARATOR_DOT); } } @SuppressWarnings("unchecked") @Override public Object deserialize(String ltype, String ltypeT, String value,…

    2024年5月24日
    2.4K00
  • Oinone远程调用链路源码分析

    前提 源码分析版本是 5.1.x版本 概要 在服务启动时,获取注解REMOTE的函数,通过dubbo的泛化调用发布。在调用函数时,通过dubbo泛化调用获取结果。 注册服务者 在spring 启动方法installOrLoad中初始化 寻找定义REMOTE的方法 组装dubbo的服务配置 组装服务对象实现引用,内容如下,用于注册 调用前置处理 放信息到SessionApi 函数调用链追踪,放到本地TransmittableThreadLocal 从redis中获取到的数据进行反序列化并存在到本地的线程里 Trace信息,放一份在sessionApi中 和ThreadLocal 调用函数执行 返回数据转成特定格式 通过线程组调用dubbo的ServiceConfig.export 服务发布 时序图 源码分析 根据条件判断,确定向dubbo进行服务发布RemoteServiceLoader public void publishService(List<FunctionDefinition> functionList,Map<String,Runnable> isPublished) { // 因为泛化接口只能控制到namespace,控制粒度不能到fun级别,这里进行去重处理 Map<String, Function> genericNamespaceMap = new HashMap<>(); for (FunctionDefinition functionDefinition : functionList) { Function function = new Function(functionDefinition) try { //定义REMOTE, 才给予远程调用 if (FunctionOpenEnum.REMOTE.in(function.getOpen()) && !ClassUtils.isInterface(function.getClazz())) { genericNamespaceMap.putIfAbsent(RegistryUtils.getRegistryInterface(function), function); } } catch (PamirsException e) { } } // 发布远程服务 for (String namespace : genericNamespaceMap.keySet()) { Function function = genericNamespaceMap.get(namespace); if(isPublished.get(RegistryUtils.getRegistryInterface(function)) == null){ // 发布,注册远程函数服务,底层使用dubbo的泛化调用 Runnable registryTask = () -> remoteRegistry.registryService(function); isPublished.put(RegistryUtils.getRegistryInterface(function),registryTask); }else{ } } } 构造ServiceConfig方法,设置成泛化调用,进行发布export()DefaultRemoteRegistryComponent public void registryGenericService(String interfaceName, List<MethodConfig> methods, String group, String version, Integer timeout, Integer retries) { …. try { ServiceConfig<GenericService> service = new ServiceConfig<>(); // 服务接口名 service.setInterface(interfaceName); // 服务对象实现引用 service.setRef(genericService(interfaceName)); if (null != methods) { service.setMethods(methods); } // 声明为泛化接口 service.setGeneric(Boolean.TRUE.toString()); // 基础元数据 constructService(group, version, timeout, retries, service); service.export(); } catch (Exception e) { ….. } } // 服务对象实现引用 private GenericService genericService(String interfaceName) { return (method, parameterTypes, args) -> { PamirsSession.clear(); Function function = Objects.requireNonNull(PamirsSession.getContext()).getFunction(RegistryUtils.getFunctionNamespace(method), RegistryUtils.getFunctionFun(method)); if (log.isDebugEnabled()) { log.debug("interfaceName: " + interfaceName + ",…

    2024年9月4日
    2.0K00

Leave a Reply

Please Login to Comment