Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize Multi-tenant function based on MybatisPlus plug-in TenantLineInnerInterceptor

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces how to achieve multi-tenant function based on the MybatisPlus plug-in TenantLineInnerInterceptor. It is very detailed and has a certain reference value. Interested friends must read it!

The basic concepts of multi-tenant technology:

Multi-tenant technology (English: multi-tenancy technology), or multi-lease technology, is a kind of software architecture technology, which discusses how to share the same system or program components in a multi-user environment, and still ensures the isolation of data among users.

With the blessing of cloud computing, multi-tenant technology is widely used in the development of various cloud services, whether IaaS,PaaS or SaaS, we can see the shadow of multi-tenant technology.

Previously introduced the interaction between GitEgg framework and database using Mybatis enhancement tool Mybatis-Plus,Mybatis-Plus provides TenantLineInnerInterceptor tenant processor to achieve multi-tenant function, the principle is that Mybatis-Plus implements a custom Mybatis interceptor (Interceptor), which automatically adds tenant query conditions after the sql that needs to be executed, the actual and paging plug-ins, data rights interceptor is the same way.

In short, multi-tenant technology allows a system to provide services to different customers through configuration, and each customer sees his own data, as if each customer has his own independent and perfect system.

The following is the application configuration in the GitEgg system:

1. Create new multi-tenant component configuration files TenantProperties.java and TenantConfig.java,TenantProperties.java under the gitegg-platform-mybatis project to read configuration files for the system. Here, the specific configuration information of multiple groups of households will be set in the Nacos configuration center. TenantConfig.java is the configuration that the plug-in needs to read. There are three configuration items:

TenantId tenant ID, TenantIdColumn multi-tenant field names, ignoreTable tables that do not require multi-tenant isolation.

TenantProperties.java:

Package com.gitegg.platform.mybatis.props;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;import java.util.List;/** * whitelist configuration * / @ Data@Configuration@ConfigurationProperties (prefix = "tenant") public class TenantProperties {/ * whether tenant mode is enabled * / private Boolean enable / * Multi-tenant field name * / private String column; / * Table of multi-tenancy to be excluded * / private List exclusionTable;}

TenantConfig.java:

Package com.gitegg.platform.mybatis.config;import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;import com.gitegg.platform.boot.util.GitEggAuthUtils;import com.gitegg.platform.mybatis.props.TenantProperties;import lombok.RequiredArgsConstructor;import net.sf.jsqlparser.expression.Expression;import net.sf.jsqlparser.expression.NullValue;import net.sf.jsqlparser.expression.StringValue;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.AutoConfigureBefore Import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * Multi-tenant configuration Center * * @ author GitEgg * / @ Configuration@RequiredArgsConstructor (onConstructor_ = @ Autowired) @ AutoConfigureBefore (MybatisPlusConfig.class) public class TenantConfig {private final TenantProperties tenantProperties / * New multi-tenant plug-in configuration, one ease and two ease follow the rules of mybatis * need to set MybatisConfiguration#useDeprecatedExecutor = false * to avoid cache problems in case of problems * * @ return TenantLineInnerInterceptor * / @ Bean public TenantLineInnerInterceptor tenantLineInnerInterceptor () {return new TenantLineInnerInterceptor (new TenantLineHandler () {/ *) get Tenant ID * @ return Expression * / @ Override public Expression getTenantId () {String tenant = GitEggAuthUtils.getTenantId () If (tenant! = null) {return new StringValue (GitEggAuthUtils.getTenantId ());} return new NullValue () } / * get the multi-tenant field name * @ return String * / @ Override public String getTenantIdColumn () { Return tenantProperties.getColumn () } / * filter tables that do not need to be isolated by tenants * this is the default method The default return of false means that all tables need to spell the multi-tenant condition * @ param tableName table name * / @ Override public boolean ignoreTable (String tableName) {return tenantProperties.getExclusionTable () .stream () .anyMatch ( (t)-> t.equalsIgnoreCase (tableName)) });}}

2. You can create a new application.yml under the project to configure the information that needs to be configured on the Nacos in the future:

Tenant: # whether to enable tenant mode enable: true # the table of multi-tenancy to be excluded exclusionTable:-"t_sys_district"-"oauth_client_details" # tenant field name column: tenant_id

3. Modify the MybatisPlusConfig.java to add the multi-tenant filter to make it effective:

Package com.gitegg.platform.mybatis.config;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;import com.gitegg.platform.mybatis.props.TenantProperties;import lombok.RequiredArgsConstructor;import org.mybatis.spring.annotation.MapperScan Import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration@RequiredArgsConstructor (onConstructor_ = @ Autowired) @ MapperScan ("com.gitegg.**.mapper.**") public class MybatisPlusConfig {private final TenantLineInnerInterceptor tenantLineInnerInterceptor; private final TenantProperties tenantProperties / * the new paging plug-in follows the rules of mybatis. You need to set MybatisConfiguration#useDeprecatedExecutor = false * to avoid cache problems (this attribute will be removed after the old plug-in is removed) * / @ Bean public MybatisPlusInterceptor mybatisPlusInterceptor () {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor () / / Multi-tenant plug-in if (tenantProperties.getEnable ()) {interceptor.addInnerInterceptor (tenantLineInnerInterceptor);} / paging plug-in interceptor.addInnerInterceptor (new PaginationInnerInterceptor (DbType.MYSQL)); / / plugin to prevent full table updates and deletions: BlockAttackInnerInterceptor BlockAttackInnerInterceptor blockAttackInnerInterceptor = new BlockAttackInnerInterceptor (); interceptor.addInnerInterceptor (blockAttackInnerInterceptor); return interceptor } / * optimistic lock plug-in hopes that when updating a record, the record has not been updated * https://mybatis.plus/guide/interceptor-optimistic-locker.html#optimisticlockerinnerinterceptor * / @ Bean public OptimisticLockerInnerInterceptor optimisticLockerInterceptor () {return new OptimisticLockerInnerInterceptor ();}}

4. Add a public method to obtain tenant information in the GitEggAuthUtils method. The tenant information is set when the Gateway is forwarded. Later, how to set the tenant information to the Header:

Package com.gitegg.platform.boot.util;import cn.hutool.json.JSONUtil;import com.gitegg.platform.base.constant.AuthConstant;import com.gitegg.platform.base.domain.GitEggUser;import org.springframework.util.StringUtils;import javax.servlet.http.HttpServletRequest;import java.io.UnsupportedEncodingException;import java.net.URLDecoder Public class GitEggAuthUtils {/ * get user information * * @ return GitEggUser * / public static GitEggUser getCurrentUser () {HttpServletRequest request = GitEggWebUtils.getRequest (); if (request = = null) {return null;} try {String user = request.getHeader (AuthConstant.HEADER_USER) If (StringUtils.isEmpty (user)) {return null;} String userStr = URLDecoder.decode (user, "UTF-8"); GitEggUser gitEggUser = JSONUtil.toBean (userStr, GitEggUser.class); return gitEggUser;} catch (UnsupportedEncodingException e) {e.printStackTrace (); return null }} / * get tenant Id * * @ return tenantId * / public static String getTenantId () {HttpServletRequest request = GitEggWebUtils.getRequest (); if (request = = null) {return null;} try {String tenantId = request.getHeader (AuthConstant.TENANT_ID) String user = request.getHeader (AuthConstant.HEADER_USER); / / if the tenantId in the request header is empty, try to get the tenant id if (StringUtils.isEmpty (tenantId) & &! StringUtils.isEmpty (user)) {String userStr = URLDecoder.decode (user, "UTF-8") from the logged-in user. GitEggUser gitEggUser = JSONUtil.toBean (userStr, GitEggUser.class); if (null! = gitEggUser) {tenantId = gitEggUser.getTenantId ();}} return tenantId;} catch (UnsupportedEncodingException e) {e.printStackTrace (); return null;}

5. The AuthGlobalFilter of gitegg- gateway sub-project in GitEgg-Cloud project adds the filtering method of setting TenantId.

String tenantId = exchange.getRequest (). GetHeaders (). GetFirst (AuthConstant.TENANT_ID); String token = exchange.getRequest (). GetHeaders (). GetFirst (AuthConstant.JWT_TOKEN_HEADER); if (StrUtil.isEmpty (tenantId) & & StrUtil.isEmpty (token)) {return chain.filter (exchange);} Map addHeaders = new HashMap () / / if tenant mode is enabled in the system configuration, set tenantId if (enable & & StrUtil.isEmpty (tenantId)) {addHeaders.put (AuthConstant.TENANT_ID, tenantId);}

6. The above are the multi-tenant function integration steps at the backend. In the actual project development process, we need to consider the configuration of the front-end page on the tenant information, and implement the idea. Tenants who are not in use have different domain names. The front-end page obtains the corresponding tenant information according to the current domain name, and sets the TenantId parameters in the public request method to ensure that the tenant information can be carried in each request.

/ / request interceptorrequest.interceptors.request.use (config = > {const token = storage.get (ACCESS_TOKEN) / / if token exists / / Let each request carry a custom token, please modify if (token) {config.headers ['Authorization'] = token} config.headers [' TenantId'] = process.env.VUE_APP_TENANT_ID return config} according to the actual situation. ErrorHandler) these are all the contents of the article "how to implement multi-tenancy based on the MybatisPlus plug-in TenantLineInnerInterceptor" Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report