spring boot 利用切面和反射进行自动关联查询

1.定义注解类:

QueryAuto:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * ClassName: Query 
* Function: 模块关联查询注解
用于返回list等方法上 */ @Documented @Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface QueryAuto { }

 QueryField:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * ClassName: QueryField 
* Function: 模块关联查询注解
*

比如字典数据,我们表里面都存的字典id,之前的开发模式是在业务模块的sql里各种left join去查询字典名称.

*

现在的做法是在实体对象的字典id属性上加上此注解,并写上字典名称属性,会自动去查询数据库,赋值于字典名称属性上去.

*/ @Documented @Inherited @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface QueryField { /** * module:(业务模块编码,默认为Dic 字典模块,其他模块的话需要遵循一定的命名规则, * 详见com.talkweb.query.common.QueryConstant 模块定义常量).
* @author gavin * @return */ public String module() default "Dic"; /** * nameField:(字典数据名称属性字段).
* @author gavin * @return */ public String nameField(); }

2.定义自动查询的属性实体类

import java.io.Serializable;

/**
 * ClassName:QueryFieldEntity 
* Function: 需要自动查询的字段属性对象.
*/ public class QueryFieldEntity implements Serializable { private static final long serialVersionUID = 1L; private String idFieldName; //id属性的字段名称 private String nameFieldName; //name属性字段名称 private String module; //需要查询的模块名称 public String getIdFieldName() { return idFieldName; } public void setIdFieldName(String idFieldName) { this.idFieldName = idFieldName; } public String getNameFieldName() { return nameFieldName; } public void setNameFieldName(String nameFieldName) { this.nameFieldName = nameFieldName; } public String getModule() { return module; } public void setModule(String module) { this.module = module; } }

3.定义查询工具类:用于获取需要查询的字段

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.annotation.QueryField;
import com.query.entity.QueryFieldEntity;

/**
 * ClassName:QueryUtil 
* Function: 自动查询工具类.
*/ public class QueryUtil { /** * getQueryAutoField:(得到对象中需要自动查询的字段).
* @author gavin * @param object * @return */ public static List getQueryAutoField(Object object){ List list = new ArrayList(); Class cls = object.getClass(); Field[] fields = cls.getDeclaredFields(); List fieldList = new ArrayList(Arrays.asList(fields)); //获取父类字段 Class supercls = cls.getSuperclass(); Field[] superfields = supercls.getDeclaredFields(); fieldList.addAll( new ArrayList(Arrays.asList(superfields))); for (Field field : fieldList) { field.setAccessible(true); QueryField queryField = field.getAnnotation(QueryField.class); if(queryField != null){ QueryFieldEntity entity = new QueryFieldEntity(); entity.setIdFieldName(field.getName()); entity.setNameFieldName(queryField.nameField()); entity.setModule(queryField.module()); list.add(entity); } } return list; } /** * getQueryAutoField:(得到对象中需要自动查询的字段).
* @author gavin * @param object * @return */ public static List getSuperQueryAutoField(Object object){ List list = new ArrayList(); Class supercls = object.getClass().getSuperclass(); Field[] fields = supercls.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); QueryField queryField = field.getAnnotation(QueryField.class); if(queryField != null){ QueryFieldEntity entity = new QueryFieldEntity(); entity.setIdFieldName(field.getName()); entity.setNameFieldName(queryField.nameField()); entity.setModule(queryField.module()); list.add(entity); } } return list; } }

4.定义查询接口:用于处理不同类型的数据

/**
 * ClassName:Query 
* Function: TODO ADD FUNCTION.
* Date: 2017年6月27日 上午9:47:04
*/ public interface Query { /** * doPage:(处理分页数据).
* @author gavin * @param object */ public void doPage(Object object); /** * doList:(处理简单列表数据).
* @author gavin * @param object */ public void doList(Object object); /** * doObject:(处理简单实体对象数据).
* @author gavin * @param object */ public void doObject(Object object); }

 

package com.query.query.impl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.common.Page;
import com.query.adapter.QueryAdapter;
import com.query.common.QueryUtil;
import com.query.entity.QueryFieldEntity;
import com.query.query.Query;

/**
 * ClassName:QueryImpl 
* Function: 自动查询实现类.
* Date: 2017年6月27日 上午9:54:02
* @author gavin * @since JDK 1.6 */ @Component public class QueryImpl implements Query { @Resource(name="queryAdapter") private QueryAdapter queryAdapter; @Override public void doPage(Object object) { Page page = (Page)object; try { Method m = page.getClass().getMethod("getContent"); List list = (List)m.invoke(page); if(list != null && list.size() > 0){ Object o = list.get(0); List fieldList = QueryUtil.getQueryAutoField(o); if(fieldList != null && fieldList.size() > 0){ for(Object ob : list){ for(QueryFieldEntity field : fieldList){ queryAdapter.handle(ob, field); } } } } } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } @Override public void doList(Object object) { List list = (List)object; if(list != null && list.size() > 0){ Object o = list.get(0); List fieldList = QueryUtil.getQueryAutoField(o); if(fieldList != null && fieldList.size() > 0){ for(Object ob : list){ for(QueryFieldEntity field : fieldList){ queryAdapter.handle(ob, field); } } } } } @Override public void doObject(Object object) { List fieldList = QueryUtil.getQueryAutoField(object); if(fieldList != null && fieldList.size() > 0){ for(QueryFieldEntity field : fieldList){ queryAdapter.handle(object, field); } } } }

  

5.定义查询适配器:用于使用不同的模块(关联表)

package com.talkweb.query.adapter;

import java.lang.reflect.Field;

import com.config.ApplicationContextRegister;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ContextLoader;

import com.query.entity.QueryFieldEntity;
import com.query.query.QueryModule;

/**
 * ClassName:QueryAdapter 
* Function: 自动查询适配器.
*/ @Component("queryAdapter") public class QueryAdapter { /** * handle:(根据不同模块,适配不同的接口实现类处理查询).
* @author gavin * @param object * @param field */ public void handle(Object object,QueryFieldEntity field) { if(field.getModule() != null && !"".equals(field.getModule())){ //这里必须注意,关于字段上的配置的Module属性,必须要和QueryModule接口实现类的后缀一致, //这里getBean的bean的名称就是queryModuleOf + Module属性!!!! QueryModule queryModule = (QueryModule) ApplicationContextRegister.getApplicationContext() .getBean("queryModuleOf"+field.getModule()); if(queryModule != null){ try { Field idField ; try{ idField = object.getClass().getDeclaredField(field.getIdFieldName()); } catch(NoSuchFieldException e){ idField = object.getClass().getSuperclass().getDeclaredField(field.getIdFieldName()); } idField.setAccessible(true); String id = (String)idField.get(object); if(id != null && !"".equals(id)){ String name = queryModule.query(id,object, field); if(name != null ){ //这里只判断null,不做空判断,因为空可能是数据本身值 Field nameField ; try{ nameField = object.getClass().getDeclaredField(field.getNameFieldName()); } catch(NoSuchFieldException e){ nameField = object.getClass().getSuperclass().getDeclaredField(field.getNameFieldName()); } nameField.setAccessible(true); nameField.set(object, name); } } } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } } } } }

  

6.定义模块处理类

package com.query.query;

import com.query.entity.QueryFieldEntity;

/**
 * ClassName:QueryModule 
* Function: 查询具体模块字段接口.
* Date: 2017年6月27日 上午11:30:00
* @author gavin * @since JDK 1.6 */ public interface QueryModule { /** * query:(查询具体模块方法,可以直接拿到id去做相应查询,然后返回).
* @author gavin * @param id id属性的值 * @param object 具体的实体对象 * @param field 反射需要用到的相关属性 * @return */ public String query(String id, Object object, QueryFieldEntity field); }

  

package com.query.query.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.entity.pub.Dic;
import com.query.entity.QueryFieldEntity;
import com.query.query.QueryModule;
import com.service.pub.impl.DicService;

/**
 * ClassName:QueryModuleOfDic 
* Function: 字典模块查询服务.
*/ @Component("queryModuleOfDic") //用于适配器中上下文获取bean public class QueryModuleOfDic implements QueryModule { @Autowired private DicService dicService; @Override public String query(String id, Object object, QueryFieldEntity fieldEntity) { String name = null; if(id != null && !"".equals(id)){ Dic dic = dicService.get(id); //根据id查询字典值 if(dic != null){ name = dic.getName(); } } return name; } }

  

7.定义查询切面类  

 

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.annotation.QueryAuto;
import com.query.query.Query;

/**
 * ClassName:QueryAop 
* Function: 自动查询切面类.
*/ @Aspect @Component public class QueryAop { @Autowired private Query query; private static final Logger LOG = Logger.getLogger(QueryAop.class); //execution为执行的意思,*代表任意返回值,然后是包名,.*意思是包下面的所有子包 *(..)代表各种方法. && @annotation(queryAuto) 表示并且方法上有为queryAuto的注解 @Pointcut(value="execution(* com.service..*.*(..)) && @annotation(queryAuto) " , argNames="queryAuto") private void queryAuto(QueryAuto queryAuto){}//定义流程切入点 /** * queryAuto:(自动查询切面方法).
* @author gavin * @param point * @param queryAuto * @return * @throws Throwable */ @Around(value = "queryAuto(queryAuto)" , argNames="queryAuto") public Object queryAuto(ProceedingJoinPoint point,QueryAuto queryAuto) throws Throwable { long start = System.currentTimeMillis(); System.out.println("QueryAuto--->进入自动查询AOP"); LOG.info("QueryAuto--->进入自动查询AOP"); Object object = point.proceed();//执行方法 if(object != null){ if(object instanceof com.talkweb.common.Page){ //返回类型为page对象 query.doPage(object); } else if(object instanceof java.util.List){ //返回类型为List query.doList(object); } else if(object instanceof java.util.Map){ //返回类型为Map //map 不作处理 } else if(object.getClass().getName().indexOf("com.talkweb.entity") >=0 ){ //默认为系统业务实体对象,如果为其他的比如:String Integer...基础数据类型,不作处理 query.doObject(object); } } System.out.println("QueryAuto--->退出自动查询AOP方法。方法执行时长: "+ (System.currentTimeMillis() - start) + "ms"); LOG.info("QueryAuto--->退出自动查询AOP方法。方法执行时长: "+ (System.currentTimeMillis() - start) + "ms"); return object; } }

  

8.使用

1.在实体类中定义查询字段

@QueryField(module=QueryConstant.MODULE_AssumeComPany,nameField="fill_park_name")
private String fill_park_pid;	//填报所在园区,当前填报人所在的园区
private String fill_park_name;

  

2.在service类中添加自动查询注解

@QueryAuto
	@Override
	public Page list(int pageNum, int pageSize, Map parameter) {
		PageHelper.startPage(pageNum, pageSize, pageNum == 0 ? false : true);
		List reuslt = getDao().list(parameter);
		Page page = new Page(reuslt);
		return page;
	}

  

 

转载于:https://www.cnblogs.com/L-zh/p/10445078.html

你可能感兴趣的:(spring boot 利用切面和反射进行自动关联查询)