mybatis多个拦截时配置问题
1.配置XML
OffsetLimitInterceptor为mybatis自带的分页拦截器
AuthorityFilterPlugin为自定义拦截器
2.编写自定义拦截器
图中部分一定要这么写,千万不能用java反射来使用,否则当不走分页拦截器OffsetLimitInterceptor时自定义拦截器也无效
private static final Logger log = LoggerFactory.getLogger(AuthorityFilterPlugin.class);
static int MAPPED_STATEMENT_INDEX = 0;// 这是对应上面的args的序号
static int PARAMETER_INDEX = 1;
static int ROWBOUNDS_INDEX = 2;
static int RESULT_HANDLER_INDEX = 3;
/**
* 这里是每次执行操作的时候,都会进行这个拦截器的方法内
*
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 对sql进行处理
Object[] queryArgs = invocation.getArgs();
MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
Object parameter = queryArgs[PARAMETER_INDEX];
BoundSql boundSql = ms.getBoundSql(parameter);
// 获取到SQL ,进行调整
String sql = boundSql.getSql();
log.debug("原sql:" + sql);
// 获取request信息,得到当前登录用户信息
RequestAttributes req = RequestContextHolder.getRequestAttributes();
if (req == null) {
return invocation.proceed();
}
// 处理request
HttpServletRequest request = ((ServletRequestAttributes) req).getRequest();
List<String> roleComid = (List<String>) request.getSession().getAttribute("roleComid");
if (roleComid == null || roleComid.size() <= 0) {
return invocation.proceed();
}
String para = "comid";
if ((sql.contains("limit ?") && (sql.indexOf("?") != sql.lastIndexOf("?"))) || (!sql.contains("limit ?") && sql.contains("?"))) {
sql = this.permissionSqlOther(sql, roleComid, para);
}else
sql = this.permissionSql(sql, roleComid, para);
log.debug("拼接后sql:" + sql);
BoundSqlSource boundSqlSource = new BoundSqlSource(boundSql);
MappedStatement newMappedStatement = copyFromMappedStatement(ms, boundSqlSource);
MetaObject metaObject = MetaObject.forObject(newMappedStatement,
new DefaultObjectFactory(), new DefaultObjectWrapperFactory(),
new DefaultReflectorFactory());
metaObject.setValue("sqlSource.boundSql.sql", sql);
queryArgs[MAPPED_STATEMENT_INDEX] = newMappedStatement;
return invocation.proceed();
}
private MappedStatement copyFromMappedStatement(MappedStatement ms,SqlSource newSqlSource) {
Builder builder = new Builder(ms.getConfiguration(),ms.getId(),newSqlSource,ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.keyGenerator(ms.getKeyGenerator());
if(ms.getKeyProperties() != null && ms.getKeyProperties().length !=0){
StringBuffer keyProperties = new StringBuffer();
for(String keyProperty : ms.getKeyProperties()){
keyProperties.append(keyProperty).append(",");
}
keyProperties.delete(keyProperties.length()-1, keyProperties.length());
builder.keyProperty(keyProperties.toString());
}
//setStatementTimeout()
builder.timeout(ms.getTimeout());
//setStatementResultMap()
builder.parameterMap(ms.getParameterMap());
//setStatementResultMap()
builder.resultMaps(ms.getResultMaps());
builder.resultSetType(ms.getResultSetType());
//setStatementCache()
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
private class BoundSqlSource implements SqlSource {
private BoundSql boundSql;
private BoundSqlSource(BoundSql boundSql) {
this.boundSql = boundSql;
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
return boundSql;
}
}
/**
* 主要是为了把这个拦截器生成一个代理放到拦截器链中
*/
@Override
public Object plugin(Object target) {
// 官方推荐写法
return Plugin.wrap(target, this);
}
/**
* 插件初始化的时候调用,也只调用一次,插件配置的属性从这里设置进来
*
* @param properties
*/
@Override
public void setProperties(Properties properties) {
}