1.自定义注释

package com.hsfw.backyard.biz.security.authority;

import java.lang.annotation.*;

/**
* 数据权限过滤自定义注解
*
* @Description
* @Author: liucq
* @Date: 2018/12/14
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UserPermissionAop {
String value() default "";
}

2.Utils

package com.hsfw.backyard.biz.security.authority.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method; public class ReflectUtil {
/**
* 利用反射获取指定对象的指定属性
*
* @param obj 目标对象
* @param fieldName 目标属性
* @return 目标属性的值
*/
public static Object getFieldValue(Object obj, String fieldName) {
Object result = null;
Field field = ReflectUtil.getField(obj, fieldName);
if (field != null) {
field.setAccessible(true);
try {
result = field.get(obj);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return result;
} /**
* 利用反射获取指定对象里面的指定属性
*
* @param obj 目标对象
* @param fieldName 目标属性
* @return 目标字段
*/
private static Field getField(Object obj, String fieldName) {
Field field = null;
for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
try {
field = clazz.getDeclaredField(fieldName);
break;
} catch (NoSuchFieldException e) {
// 这里不用做处理,子类没有该字段可能对应的父类有,都没有就返回null。
}
}
return field;
} /**
* 利用反射设置指定对象的指定属性为指定的值
*
* @param obj 目标对象
* @param fieldName 目标属性
* @param fieldValue 目标值
*/
public static void setFieldValue(Object obj, String fieldName, String fieldValue) {
Field field = ReflectUtil.getField(obj, fieldName);
if (field != null) {
try {
field.setAccessible(true);
field.set(obj, fieldValue);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} /**
* 根据文件路径 获取反射对象并执行对应方法
*
* @author GaoYuan
* @date 2018/4/17 上午9:51
*/
public static Object reflectByPath(String path) {
try {
//获取类名
String className = path.substring(0, path.lastIndexOf("."));
//获取方法名
String methodName = path.substring(path.lastIndexOf(".") + 1, path.length());
// 获取字节码文件对象
Class c = Class.forName(className); Constructor con = c.getConstructor();
Object obj = con.newInstance(); // public Method getMethod(String name,Class<?>... parameterTypes)
// 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
Method method = c.getMethod(methodName);
// 调用obj对象的 method 方法
return method.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.hsfw.backyard.biz.security.authority.util;//package com.foruo.sc.permission.example.util;

import com.hsfw.backyard.biz.security.authority.UserPermissionAop;
import org.apache.ibatis.mapping.MappedStatement; import java.lang.reflect.Method; public class PermissionUtils { public static UserPermissionAop getPermissionByDelegate(MappedStatement mappedStatement) {
UserPermissionAop permissionAop = null;
try {
String id = mappedStatement.getId();
String className = id.substring(0, id.lastIndexOf("."));
String methodName = id.substring(id.lastIndexOf(".") + 1, id.length());
final Class cls = Class.forName(className);
final Method[] method = cls.getMethods();
for (Method me : method) {
if (me.getName().equals(methodName) && me.isAnnotationPresent(UserPermissionAop.class)) {
permissionAop = me.getAnnotation(UserPermissionAop.class);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return permissionAop;
}
}

3.mybatis

package com.hsfw.backyard.biz.security.authority.mybatis;

import com.hsfw.backyard.biz.ContextHolder;
import com.hsfw.backyard.biz.model.sys.User;
import com.hsfw.backyard.biz.security.authority.UserPermissionAop;
import com.hsfw.backyard.biz.security.authority.util.PermissionUtils;
import com.hsfw.backyard.biz.security.authority.util.ReflectUtil;
import com.hsfw.backyard.dal.mapper.model.UserDataManageDO;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import java.sql.Connection;
import java.util.List;
import java.util.Properties; @Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Component
public class PrepareInterceptor implements Interceptor { private static final Logger log = LoggerFactory.getLogger(PrepareInterceptor.class); @Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
} @Override
public void setProperties(Properties properties) {
} @Override
public Object intercept(Invocation invocation) throws Throwable {
if (log.isInfoEnabled()) {
log.info("进入 PrepareInterceptor 拦截器...");
}
if (invocation.getTarget() instanceof RoutingStatementHandler) {
RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(handler, "delegate");
//通过反射获取delegate父类BaseStatementHandler的mappedStatement属性
MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");
BoundSql boundSql = delegate.getBoundSql();
ReflectUtil.setFieldValue(boundSql, "sql", permissionSql(boundSql.getSql(), mappedStatement));
}
return invocation.proceed();
} /**
* 权限sql包装,以及是否需要包装
*
* @param sql
* @return
*/
protected String permissionSql(String sql, MappedStatement mappedStatement) {
UserPermissionAop permissionAop = PermissionUtils.getPermissionByDelegate(mappedStatement);
StringBuilder sbSql = new StringBuilder(sql);
if (permissionAop != null) {
String id = mappedStatement.getId();
String methodName = id.substring(id.lastIndexOf(".") + 1, id.length());
//方法过滤,待讨论
if (methodName.equals("countByCondition") || methodName.equals("pageByCondition")) {
return getAppendSql(sbSql, methodName);
}
}
return sbSql.toString();
} /**
* sql拼接
*
* @param sbSql
* @param methodName
* @return
*/
public String getAppendSql(StringBuilder sbSql, String methodName) {
//当前用户信息
User user = ContextHolder.user();
List<UserDataManageDO> managedUserList = user.getUserDatalist();
String findUserList = String.valueOf(user.getId());
for (int i = 0; i < managedUserList.size(); i++) {
findUserList.concat("," + String.valueOf(managedUserList.get(i).getManagedUserId()));
}
if (methodName.equals("countByCondition")) {
sbSql = sbSql.append(" and operate_user_id in (" + findUserList + ") ");
} else {
sbSql = new StringBuilder("select * from (").append(sbSql).append(" ) temp where temp.operate_user_id in (" + findUserList + ") ");
}
return sbSql.toString();
} }
package com.hsfw.backyard.biz.security.authority.mybatis;

import com.hsfw.backyard.biz.security.authority.UserPermissionAop;
import com.hsfw.backyard.biz.security.authority.util.PermissionUtils;
import com.hsfw.backyard.biz.security.authority.util.ReflectUtil;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import java.lang.reflect.Method;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Properties; @Intercepts({
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
@Component
public class ResultInterceptor implements Interceptor {
/**
* 日志
*/
private static final Logger log = LoggerFactory.getLogger(ResultInterceptor.class); @Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
} @Override
public void setProperties(Properties properties) {
} @Override
public Object intercept(Invocation invocation) throws Throwable {
if (log.isInfoEnabled()) {
log.info("进入 ResultInterceptor 拦截器...");
}
ResultSetHandler resultSetHandler1 = (ResultSetHandler) invocation.getTarget();
//通过java反射获得mappedStatement属性值
//可以获得mybatis里的resultype
MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(resultSetHandler1, "mappedStatement");
//获取切面对象
UserPermissionAop permissionAop = PermissionUtils.getPermissionByDelegate(mappedStatement);
//执行请求方法,并将所得结果保存到result中
Object result = invocation.proceed();
if (permissionAop != null) {
if (result instanceof ArrayList) {
ArrayList resultList = (ArrayList) result;
for (int i = 0; i < resultList.size(); i++) {
Object oi = resultList.get(i);
Class c = oi.getClass();
Class[] types = {String.class};
Method method = c.getMethod("setRegionCd", types);
// 调用obj对象的 method 方法
method.invoke(oi, "");
if (log.isInfoEnabled()) {
log.info("数据权限处理【过滤结果】...");
}
}
}
}
return result;
} }

mybatis拦截器处理的更多相关文章

  1. Mybatis拦截器

    Mybatis拦截器

  2. Mybatis拦截器 mysql load data local 内存流处理

    Mybatis 拦截器不做解释了,用过的基本都知道,这里用load data local主要是应对大批量数据的处理,提高性能,也支持事务回滚,且不影响其他的DML操作,当然这个操作不要涉及到当前所lo ...

  3. MyBatis拦截器原理探究

    MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...

  4. Mybatis拦截器介绍

    拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法.Mybatis拦截器设计的一个初 ...

  5. Mybatis拦截器实现分页

    本文介绍使用Mybatis拦截器,实现分页:并且在dao层,直接返回自定义的分页对象. 最终dao层结果: public interface ModelMapper { Page<Model&g ...

  6. 数据权限管理中心 - 基于mybatis拦截器实现

    数据权限管理中心 由于公司大部分项目都是使用mybatis,也是使用mybatis的拦截器进行分页处理,所以技术上也直接选择从拦截器入手 需求场景 第一种场景:行级数据处理 原sql: select ...

  7. 基于Spring和Mybatis拦截器实现数据库操作读写分离

    首先需要配置好数据库的主从同步: 上一篇文章中有写到:https://www.cnblogs.com/xuyiqing/p/10647133.html 为什么要进行读写分离呢? 通常的Web应用大多数 ...

  8. 通过spring抽象路由数据源+MyBatis拦截器实现数据库自动读写分离

    前言 之前使用的读写分离的方案是在mybatis中配置两个数据源,然后生成两个不同的SqlSessionTemplate然后手动去识别执行sql语句是操作主库还是从库.如下图所示: 好处是,你可以人为 ...

  9. 【Mybatis】1、Mybatis拦截器学习资料汇总

    MyBatis拦截器原理探究 http://www.cnblogs.com/fangjian0423/p/mybatis-interceptor.html [myBatis]Mybatis中的拦截器 ...

  10. spring boot 实现mybatis拦截器

    spring boot 实现mybatis拦截器 项目是个报表系统,服务端是简单的Java web架构,直接在请求参数里面加了个query id参数,就是mybatis mapper的query id ...

随机推荐

  1. Mysql 的安装(压缩文件)和基本管理

    MySql安装和基本管理   本节掌握内容: mysql的安装.启动 mysql破解密码 统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle ...

  2. LINUX-redis & mongodb

    ubuntu安装redis: apt-get -y install redis-serverubuntu启动redis: /etc/init.d/redis-server restart linux安 ...

  3. python-模块入门二(模块循环导入,区分python文件的两种用途,模块搜索路径,软件开发的目录规范)

    一.模块的循环导入问题 run.py # import m1 # 第一次导入 m1.py # 错误示范 ''' print('正在导入m1') from m2 import y #第一次导入m2 x= ...

  4. ElasticSearch搜索数据到底有几种方式?

    Elasticsearch允许三种方式执行搜索请求: GET请求正文: curl -XGET "http://localhost:9200/app/users/_search" - ...

  5. 【转】光盘和U盘安装win7和ubuntu14.04全步骤

    详细步骤见原链接:http://brianway.github.io/2016/01/18/linux-win7-ubuntu-setup-by-USBandCD/ 安装Linux步骤 1. 在win ...

  6. Oracle12c 性能优化攻略:攻略1-3: 匹配表类型与业务需求

    注:目录表 <Oracle12c 性能优化攻略:攻略目录表> 问题描述 你刚开始使用oracle数据库,并且学习了一些关于可用的各种表类型的知识.例如:可以在堆组织表.索引组织表等之间支出 ...

  7. linux之xxx 不在 sudoers 文件中,此事将被报告(转载)

    linux中创建用户命令为:useradd 用户名, eg: useradd test 指定密码:passwd test 但是有时候我们需要使用test运行执行一些root用户才有权限执行的命令,此时 ...

  8. PDF如何设置书签,怎么在PDF上添加书签

    PDF文件现在作为我们使用最多的一种办公文件,当然我们在使用PDF文件的同时还会需要编辑PDF文件,在使用一个PDF文件页数比较多的时候就需要添加书签,不然每次使用的时候都需要从头开始查找是很麻烦又头 ...

  9. cf161d 求距离为k的点对(点分治,树形dp)

    点分治裸题,但是用树形dp也能做 /* dp[u][k]表示在u下距离k的点数量 */ #include<bits/stdc++.h> using namespace std; ]; ], ...

  10. Fiddler抓包1-抓firefox上https请求

    前言 fiddler是一个很好的抓包工具,默认是抓http请求的,对于pc上的https请求,会提示网页不安全,这时候需要在浏览器上安装证书. 一.网页不安全 1.用fiddler抓包时候,打开百度网 ...