注:仅使用于MyBatis-Plus 3.4.0+
直接上实现
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper
import com.baomidou.mybatisplus.core.toolkit.PluginUtils
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor
import net.sf.jsqlparser.expression.Expression
import net.sf.jsqlparser.expression.HexValue
import net.sf.jsqlparser.expression.LongValue
import net.sf.jsqlparser.expression.StringValue
import net.sf.jsqlparser.expression.operators.conditional.AndExpression
import net.sf.jsqlparser.expression.operators.relational.EqualsTo
import net.sf.jsqlparser.expression.operators.relational.ExpressionList
import net.sf.jsqlparser.expression.operators.relational.InExpression
import net.sf.jsqlparser.schema.Column
import net.sf.jsqlparser.schema.Table
import net.sf.jsqlparser.statement.select.FromItem
import net.sf.jsqlparser.statement.select.PlainSelect
import net.sf.jsqlparser.statement.select.Select
import org.apache.ibatis.executor.Executor
import org.apache.ibatis.mapping.BoundSql
import org.apache.ibatis.mapping.MappedStatement
import org.apache.ibatis.session.ResultHandler
import org.apache.ibatis.session.RowBounds
/**
* Created by @author x on 2021/7/30
*/
class CustomizeDataPermissionHandler : JsqlParserSupport(), InnerInterceptor {
override fun beforeQuery(executor: Executor?, ms: MappedStatement?, parameter: Any?, rowBounds: RowBounds?, resultHandler: ResultHandler<*>?, boundSql: BoundSql?) {
if (!InterceptorIgnoreHelper.willIgnoreDataPermission(ms!!.id)) {
val mpBs = PluginUtils.mpBoundSql(boundSql)
mpBs.sql(parserSingle(mpBs.sql(), ms.id))
}
}
override fun processSelect(select: Select, index: Int, sql: String?, obj: Any?) {
val threadLocal = DataAuthThreadLocalUtil.current() ?: return
val plainSelect = select.selectBody as PlainSelect
if (!plainSelect.joins.isNullOrEmpty()) {
plainSelect.joins.forEach {
val onExpression = it.onExpression
it.onExpression = buildExpression(onExpression, it.rightItem, threadLocal)
}
}
var where = plainSelect.where
if (where == null) {
where = HexValue(" 1 = 1 ")
}
val formItem = plainSelect.fromItem as Table
plainSelect.where = buildExpression(where, formItem, threadLocal)
}
private fun buildExpression(where: Expression, formItem: FromItem, listTable: MutableList<TableInfo>): Expression {
val table = formItem as Table
var expression = where
listTable.forEach {
if (it.tableName == table.name) {
val columns = it.columnData
if (!columns.isNullOrEmpty()) {
columns.forEach { (key, value) ->
if (value.size > 1) {
val itemsList = ExpressionList()
val inValues = mutableListOf<Expression>()
value.forEach { va ->
inValues.add(this.changeDataType(va))
}
itemsList.expressions = inValues
expression = AndExpression(expression, InExpression(Column(formItem, key), itemsList))
} else {
val equalsTo = EqualsTo()
equalsTo.leftExpression = Column(formItem, key)
equalsTo.rightExpression = this.changeDataType(value[0])
expression = AndExpression(expression, equalsTo)
}
}
}
}
}
return expression
}
private fun changeDataType(value: Any): Expression {
return if (value is String) {
StringValue(value)
} else {
LongValue(value.toString())
}
}
}
配置
/**
* Created by @author x on 2021/7/30
*/
@Configuration
class MybatisPlusConfig {
@Bean
fun mybatisPlusInterceptor(): MybatisPlusInterceptor {
val interceptor = MybatisPlusInterceptor()
// 数据权限
interceptor.addInnerInterceptor(CustomizeDataPermissionHandler())
return interceptor
}
}
TableInfo
/**
* Created by @author x on 2021/7/30
*/
class TableInfo(var tableName: String?, var columnData: MutableMap<String, MutableList<Any>>?)
DataAuthThreadLocalUtil
/**
* Created by @author x on 2021/7/30
*/
class DataAuthThreadLocalUtil {
companion object {
private val threadLocal = ThreadLocal<MutableList<TableInfo>>()
fun current(): MutableList<TableInfo>? {
return threadLocal.get()
}
fun setTableInfo(tableInfo: MutableList<TableInfo>) {
threadLocal.set(tableInfo)
}
fun clear() {
threadLocal.remove()
}
}
}