您好,登錄后才能下訂單哦!
這篇文章主要介紹了如何基于SpringBoot實現(xiàn)自動裝配返回屬性,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
在業(yè)務(wù)開發(fā)中經(jīng)常會有這個一個場景,A(業(yè)務(wù)表)表中會記錄數(shù)據(jù)的創(chuàng)建人,通常我們會用userId字段記錄該數(shù)據(jù)的創(chuàng)建者,但數(shù)據(jù)的使用方會要求展示該數(shù)據(jù)的創(chuàng)建者姓名,故我們會關(guān)聯(lián)用戶表拿該用戶的姓名。還有一些枚舉值的含義也要展示給前端。導(dǎo)致原本一個單表的sql就要寫成多表的關(guān)聯(lián)sql,以及枚舉含義的轉(zhuǎn)換很是惡心。
例如:業(yè)務(wù)對象BusinessEntity.java
public class BusinessEntity { /** * 創(chuàng)建者id */ private Long createUserId; * 創(chuàng)建者名稱 (需要關(guān)聯(lián)用戶表) private String userName; * 數(shù)據(jù)狀態(tài)(0:有效,1失效) private String status; * 數(shù)據(jù)狀態(tài)含義(需要解析0或1的含義給前端) private String statusName; * 數(shù)據(jù)集合 private List<BusinessEntity> list; }
就像@JsonFormat注解,可以指定返回日期格式。我們是不是可以也自定義一個注解,通過這個注解,我們可以自動的把需要聯(lián)表的數(shù)據(jù)userName自動填充,需要解析的數(shù)據(jù)數(shù)據(jù)statusName如何通過枚舉解析。
故定義枚舉@AutowiredAttribute如下
/** * 自動裝配屬性 */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) @Documented public @interface AutowiredAttribute { /** * 當(dāng)為默認值時,表明該屬性為javaBean,且該javaBean需要自動注入屬性 * 否則為指向的某一個屬性 * * @return */ String param() default ""; * 默認為BaseEnum.class, * 當(dāng)為默認時注入數(shù)據(jù)的來源時redis緩存, * 否則為枚舉類型 Class<? extends BaseEnum> enumClass() default BaseEnum.class; * 數(shù)據(jù)源 DataSourceEnum dataSource() default DataSourceEnum.EMPTY; }
定義公共枚舉繼承繼承接口BaseEnum
public interface BaseEnum { String getCode(); String getMsg(); }
定義數(shù)據(jù)源枚舉如下dataSource
public enum DataSourceEnum implements BaseEnum { SYSTEM_DICT("sys:dict:", "系統(tǒng)字典值", "sys_dict_value", "name"), USER_NAME("user:name:", "用戶的id與姓名的映射", "sys_user", "user_name"), USER_ROLE("user:role:", "角色id于角色名稱映射", "sys_role", "name"), DEPT_NAME("dept:name:", "部門的id與部門名稱的映射", "sys_dept", "name"), EMPTY("00", "默認", "", ""); DataSourceEnum(String code, String msg, String tableName, String tableColumn) { this.code = code; this.msg = msg; this.tableName = tableName; this.tableColumn = tableColumn; } private String code; private String msg; /** * 表明 */ private String tableName; * 表的列 private String tableColumn; @Override public String getCode() { return code; public String getMsg() { return msg; public String getTableName() { return tableName; public String getTableColumn() { return tableColumn; }
對比原對象:通過新增注解,就避免的關(guān)聯(lián)查詢和數(shù)據(jù)解析
public class BusinessEntity { /** * 創(chuàng)建者id */ private Long createUserId; * 創(chuàng)建者名稱 (需要關(guān)聯(lián)用戶表) @AutowiredAttribute(param = "createUserId", dataSource = DataSourceEnum.USER_NAME) private String userName; * 數(shù)據(jù)狀態(tài)(0:有效,1失效) private String status; * 數(shù)據(jù)狀態(tài)含義(需要解析0或1的含義給前端) @AutowiredAttribute(param = "status", enumClass = StatusEnum.class) private String statusName; * 數(shù)據(jù)集合 @AutowiredAttribute private List<BusinessEntity> list; }
/** * 填充相應(yīng)體 */ @Component @ControllerAdvice() public class FillResponseBodyAdvice implements ResponseBodyAdvice { @Autowired RedissonClient redissonClient; JdbcTemplate jdbcTemplate; private static String GET_CODE_METHOD_NAME = "getCode"; private static String GET_MSG_METHOD_NAME = "getMsg"; @Override public boolean supports(MethodParameter returnType, Class converterType) { if (ResponseResult.class.getName().equals(returnType.getMethod().getReturnType().getName())) { return true; } return false; } public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (((ResponseResult<?>) body).getCode() == 200) {//僅僅對相應(yīng)為200結(jié)果處理 Object data = ((ResponseResult<?>) body).getData(); Class<?> aClass = data.getClass(); if (data instanceof List) { //集合對象設(shè)置屬性 setForListBeanArr((List) data); } else { //判斷是否為自定義java對象 if (aClass.getSuperclass() instanceof Object) { setForJavaBeanArr(data, aClass); } } return body; /** * 為集合對象設(shè)置屬性 * * @param list */ void setForListBeanArr(List<Object> list) { for (Object object : list) { Class<?> aClass = object.getClass(); setForJavaBeanArr(object, aClass); * 為自定義javaBean對象設(shè)置值 private void setForJavaBeanArr(Object data, Class<?> aClass) { Field[] declaredFields = aClass.getDeclaredFields(); for (Field field : declaredFields) { AutowiredAttribute annotation = field.getAnnotation(AutowiredAttribute.class); if (annotation == null) { continue; //通過枚舉注入 String param = annotation.param(); try { field.setAccessible(true); if (param.equals("")) {//注解表明該對象時javaBean對象 //獲取該javaBean對象 Object data2 = field.get(data); if (data2 == null) { continue; } //屬性是list對象 if (data2 instanceof List) { setForListBeanArr((List) data2); } else if (data2.getClass().getSuperclass() instanceof Object) { setForJavaBeanArr(data2, data2.getClass()); } else { //反射獲取值 Field field1 = aClass.getDeclaredField(param); field1.setAccessible(true); Object o = field1.get(data); if (annotation.enumClass().getName().equals(BaseEnum.class.getName())) { //通過redis注入 injectByEnum(o, field, data); } else { //通過枚舉注入 injectByRedis(o, field, data); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { private void injectByEnum(Object param, Field field, Object data) throws IllegalAccessException { AutowiredAttribute annotationAutowiredAttribute = field.getAnnotation(AutowiredAttribute.class); DataSourceEnum dataSourceEnum = annotationAutowiredAttribute.dataSource(); if (dataSourceEnum.equals(DataSourceEnum.EMPTY)) { //不規(guī)范的 } else if (dataSourceEnum.equals(DataSourceEnum.SYSTEM_DICT)) { Object o = redissonClient.getMap(DataSourceEnum.SYSTEM_DICT.getCode()).get(param); if (o == null) { o = getDictAndSetRedis(DataSourceEnum.SYSTEM_DICT, param); field.set(data, o); private void injectByRedis(Object param, Field field, Object data) throws IllegalAccessException { AutowiredAttribute annotation = field.getAnnotation(AutowiredAttribute.class); Class<? extends BaseEnum> aClass = annotation.enumClass(); try { // 獲取所有常量 Object[] objects = aClass.getEnumConstants(); //獲取指定方法 Method getMsg = aClass.getMethod(GET_MSG_METHOD_NAME); Method getCode = aClass.getMethod(GET_CODE_METHOD_NAME); for (Object obj : objects) { if (getCode.invoke(obj).equals(param.toString())) { field.set(data, getMsg.invoke(obj)); System.out.println(getMsg.invoke(obj)); } catch (Exception e) { System.out.println(e.getMessage()); // Object getDictAndSetRedis(DataSourceEnum dataSourceEnum, Object value) { String sql = "select name from " + dataSourceEnum.getTableName() + " where id = " + value; String s = jdbcTemplate.queryForObject(sql, String.class); RMap<Object, Object> map = redissonClient.getMap(dataSourceEnum.getCode()); map.put(value, s); return s; }
實現(xiàn)了從數(shù)據(jù)庫(mysql)自動查詢,并把結(jié)果緩沖到數(shù)據(jù)庫。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“如何基于SpringBoot實現(xiàn)自動裝配返回屬性”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。