springboot对mapper切⾯,获取mybatis执⾏的sql
⼯作需要,有个需求是这样⼦的:输⼊接⼝地址,能查询出他调⽤了哪些sql,因此才有了本⽂章
采⽤切⾯⽅式,代码如下
ServiceAspect
slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
batis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.t.request.RequestContextHolder;
import org.t.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/
**
* @program: industry
* @description:
* @author: zhangshulong
* @create: 2020-02-18 19:51
**/
@Aspect
@Component
@Slf4j
public class ServiceAspect {
/**
* Pointcut定义切点
* public修饰符的返回值任意 ller包下⾯的任意类的任意⽅法任意参数
*/
@Pointcut("execution(public * dao..*(..))")
public void log(){
}
@Autowired
private SqlSessionFactory sqlSessionFactory;
// @Resource
// private SqlSessionFactoryBean sqlSessionFactoryBean;
@Before("log()")
public void doBefore(JoinPoint joinPoint){
// System.out.println("进⼊切⾯⽅法执⾏前...");
// ServletRequestAttributes sra = (ServletRequestAttributes) RequestAttributes();
// if (!Objects.isNull(sra) && !Objects.Request())){
// HttpServletRequest request = Request();
// System.out.println("url: " + RequestURI());
// System.out.println("method: "+Method()); //post or get? or ?
// System.out.println("hod: " + Signature().getDeclaringTypeName() + "." + Signature().getName());
// System.out.println("args: "+Args());
// }
//
// System.out.println("切⾯结束...");
//kx_parse_mapper id,url,mapperName,mapperMethod,controllerName,cMethod,cMethodNotes
//kx_parse_mapperxml id,xml_name,xml_method(对应标签id 要排除resultMap标签),p_xml_method(⽗标签id,此id指的是标签id属性),xml_content }
}
@After("log()")
public void doAfter(JoinPoint joinPoint){
// System.out.println("进⼊切⾯⽅法执⾏后...");
//
// ServletRequestAttributes sra = (ServletRequestAttributes) RequestAttributes();
// if (!Objects.isNull(sra) && !Objects.Request())){
// HttpServletRequest request = Request();
// System.out.println("url: " + RequestURI());
// System.out.println("method: "+Method()); //post or get? or ?
// System.out.println("hod: " + Signature().getDeclaringTypeName() + "." + Signature().getName());
// System.out.println("args: "+Args());
// }
//
// System.out.println("切⾯结束...");
//kx_parse_mapper id,url,mapperName,mapperMethod,controllerName,cMethod,cMethodNotes
/
/kx_parse_mapperxml id,xml_name,xml_method(对应标签id 要排除resultMap标签),p_xml_method(⽗标签id,此id指的是标签id属性),xml_content }
//环绕通知
@Around("log()")
public Object around(ProceedingJoinPoint pjp)throws Throwable{
System.out.println("++++++++++环绕通知开始+++++++++++");
//1.从redis中获取主数据库,若获取不到直接退出,否则判断当前数据源是会否为主,若不为主,则切换到主数据源
//2.调⽤⽬标⽅法
ServletRequestAttributes sra =(ServletRequestAttributes) RequestAttributes();
if(!Objects.isNull(sra)&&!Objects.Request())){
HttpServletRequest request = Request();
System.out.println("url: "+ RequestURI());
System.out.println("method: "+Method());//post or get? or ?
System.out.println("hod: "+ Signature().getDeclaringTypeName()+"."+ Signature().getName());
System.out.println("args: "+Args());
}
Object proceed = pjp.proceed();
//3.获取SQL
String sql = MybatisSql(pjp, sqlSessionFactory);
System.out.println(">>>>>>>>>>"+sql+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
System.out.println("++++++++++环绕通知结束+++++++++++");
return proceed;
}
}
SqlUtils.java
import com.sun.deploy.util.ArrayUtil;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.flection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.pe.TypeHandlerRegistry;
import org.aspectj.lang.ProceedingJoinPoint;
import org.flect.MethodSignature;
import java.lang.annotation.Annotation;
import flect.Field;
import flect.Method;
import flect.Parameter;
DateFormat;
import java.util.*;
import java.util.*;
public class SqlUtils {
/**
* 获取aop中的SQL语句
* @param pjp
* @param sqlSessionFactory
* @return
* @throws IllegalAccessException
*/
public static String getMybatisSql(ProceedingJoinPoint pjp, SqlSessionFactory sqlSessionFactory)throws IllegalAccessException { Map<String,Object> map =new HashMap<>();
//1.获取namespace+methdoName
MethodSignature signature =(MethodSignature) Signature();
Method method = Method();
String namespace = DeclaringClass().getName();
String methodName = Name();
//2.根据namespace+methdoName获取相对应的MappedStatement
Configuration configuration = Configuration();
MappedStatement mappedStatement = MappedStatement(namespace+"."+methodName);
// //3.获取⽅法参数列表名
// Parameter[] parameters = Parameters();
//4.形参和实参的映射
Object[] objects = Args();//获取实参
Annotation[][] parameterAnnotations = ParameterAnnotations();
for(int i =0;i<parameterAnnotations.length;i++){
Object object = objects[i];
if(parameterAnnotations[i].length ==0){//说明该参数没有注解,此时该参数可能是实体类,也可能是Map,也可能只是单参数Class().getClassLoader()== null && object instanceof Map){
map.putAll((Map<?extends String,?>) object);
System.out.println("该对象为Map");
}else{//形参为⾃定义实体类
map.putAll(objectToMap(object));
springboot aopSystem.out.println("该对象为⽤户⾃定义的对象");
}
}else{//说明该参数有注解,且必须为@Param
for(Annotation annotation : parameterAnnotations[i]){
if(annotation instanceof Param){
map.put(((Param) annotation).value(),object);
}
}
}
}
//5.获取boundSql
BoundSql boundSql = BoundSql(map);
return showSql(configuration,boundSql);
}
/
**
* 解析BoundSql,⽣成不含占位符的SQL语句
* @param configuration
* @param boundSql
* @return
*/
private static String showSql(Configuration configuration, BoundSql boundSql){
Object parameterObject = ParameterObject();
List<ParameterMapping> parameterMappings = ParameterMappings();
String sql = Sql().replaceAll("[\\s]+"," ");
if(parameterMappings.size()>0&& parameterObject != null){
TypeHandlerRegistry typeHandlerRegistry = TypeHandlerRegistry();
if(typeHandlerRegistry.Class())){
sql = placeFirst("\\?",getParameterValue(parameterObject));
}else{
MetaObject metaObject = wMetaObject(parameterObject);
for(ParameterMapping parameterMapping : parameterMappings){
String propertyName = Property();
String[] s = ObjectWrapper().getGetterNames();
if(metaObject.hasGetter(propertyName)){
Object obj = Value(propertyName);
sql = placeFirst("\\?",getParameterValue(obj));
}else if(boundSql.hasAdditionalParameter(propertyName)){
Object obj = AdditionalParameter(propertyName);
sql = placeFirst("\\?",getParameterValue(obj));
}
}
}
}
return sql;
}
/**
* 若为字符串或者⽇期类型,则在参数两边添加''
* @param obj
* @return
*/
private static String getParameterValue(Object obj){
String value = null;
if(obj instanceof String){
value ="'"+ String()+"'";
}else if(obj instanceof Date){
DateFormat formatter = DateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA); value ="'"+ formatter.format(new Date())+"'";
}else{
if(obj != null){
value = String();
}else{
value ="";
}
}
return value;
}
/**
* 获取利⽤反射获取类⾥⾯的值和名称
*
* @param obj
* @return
* @throws IllegalAccessException
*/
private static Map<String, Object>objectToMap(Object obj)throws IllegalAccessException {
Map<String, Object> map =new HashMap<>();
Class<?> clazz = Class();
System.out.println(clazz);
for(Field field : DeclaredFields()){
field.setAccessible(true);
String fieldName = Name();
Object value = (obj);
map.put(fieldName, value);
}
return map;
}
}
在这⾥插⼊图⽚描述
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论