From 556f7b9672b22440303527ba0b8825be6dbc27ad Mon Sep 17 00:00:00 2001 From: wh Date: Thu, 9 Apr 2026 13:31:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(common):=20=E6=B7=BB=E5=8A=A0=20MybatisPlu?= =?UTF-8?q?sConfig/StateValidator=EF=BC=8C=E4=BF=AE=E5=A4=8D=20jsqlparser?= =?UTF-8?q?=20=E4=BE=9D=E8=B5=96=20(T010/T011)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MybatisPlusConfig: TenantLineInnerInterceptor + PaginationInnerInterceptor - StateValidator: 通用状态机校验,失败抛出 INVALID_STATE_TRANSITION - pom.xml: 新增 mybatis-plus-jsqlparser 3.5.9(3.5.7+ 必须显式引入) --- pom.xml | 7 +++ .../common/config/MybatisPlusConfig.java | 57 +++++++++++++++++++ .../common/statemachine/StateValidator.java | 36 ++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 src/main/java/com/label/common/config/MybatisPlusConfig.java create mode 100644 src/main/java/com/label/common/statemachine/StateValidator.java diff --git a/pom.xml b/pom.xml index 3ac5aa1..86420a7 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,13 @@ 3.5.9 + + + com.baomidou + mybatis-plus-jsqlparser + 3.5.9 + + org.apache.shiro diff --git a/src/main/java/com/label/common/config/MybatisPlusConfig.java b/src/main/java/com/label/common/config/MybatisPlusConfig.java new file mode 100644 index 0000000..2b52882 --- /dev/null +++ b/src/main/java/com/label/common/config/MybatisPlusConfig.java @@ -0,0 +1,57 @@ +package com.label.common.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import com.label.common.context.CompanyContext; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.NullValue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Arrays; +import java.util.List; + +@Configuration +public class MybatisPlusConfig { + + // Tables that do NOT need tenant isolation (either global or tenant root tables) + private static final List IGNORED_TABLES = Arrays.asList( + "sys_company", // the tenant root table itself + "sys_config" // has company_id=NULL for global defaults; service handles this manually + ); + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + + // 1. Tenant isolation - auto-injects WHERE company_id = ? + interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() { + @Override + public Expression getTenantId() { + Long companyId = CompanyContext.get(); + if (companyId == null) { + return new NullValue(); + } + return new LongValue(companyId); + } + + @Override + public String getTenantIdColumn() { + return "company_id"; + } + + @Override + public boolean ignoreTable(String tableName) { + return IGNORED_TABLES.contains(tableName); + } + })); + + // 2. Pagination interceptor (required for MyBatis Plus Page queries) + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + + return interceptor; + } +} diff --git a/src/main/java/com/label/common/statemachine/StateValidator.java b/src/main/java/com/label/common/statemachine/StateValidator.java new file mode 100644 index 0000000..cf4385b --- /dev/null +++ b/src/main/java/com/label/common/statemachine/StateValidator.java @@ -0,0 +1,36 @@ +package com.label.common.statemachine; + +import com.label.common.exception.BusinessException; +import org.springframework.http.HttpStatus; + +import java.util.Map; +import java.util.Set; + +/** + * Generic state machine validator. + * Validates state transitions against a predefined transitions map. + */ +public final class StateValidator { + + private StateValidator() {} + + /** + * Assert that a state transition from {@code current} to {@code next} is valid. + * + * @param transitions the allowed transitions map + * @param current the current state + * @param next the desired next state + * @param the state type (enum) + * @throws BusinessException with code INVALID_STATE_TRANSITION if transition not allowed + */ + public static void assertTransition(Map> transitions, S current, S next) { + Set allowed = transitions.get(current); + if (allowed == null || !allowed.contains(next)) { + throw new BusinessException( + "INVALID_STATE_TRANSITION", + String.format("不允许的状态转换: %s → %s", current, next), + HttpStatus.CONFLICT + ); + } + } +}