最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于SpringBoot實現(xiàn)自動裝配返回屬性的設(shè)計思路

 更新時間:2022年03月25日 08:25:48   作者:愛我-中華  
這篇文章主要介紹了基于SpringBoot實現(xiàn)自動裝配返回屬性,這里涉及到的技術(shù)知識點有注解解析器,為什么用ResponseBodyAdvice這里解析?不在Filter,Interceptors,本文結(jié)合示例代碼給大家介紹的非常詳細,需要的朋友參考下吧

一:需求背景

在業(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;
}

二:設(shè)計思路

?就像@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ù)庫。

五:需要思考的技術(shù)點

1.為什么注解要用到枚舉和泛型class

2.注解解析器,為什么用ResponseBodyAdvice這里解析?不在Filter,Interceptors?

3.對于對象里面嵌套對象,或?qū)ο罄锩媲短准?,怎么解決注入?遞歸

到此這篇關(guān)于基于SpringBoot實現(xiàn)自動裝配返回屬性的文章就介紹到這了,更多相關(guān)SpringBoot自動裝配返回屬性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot集成MQTT示例詳解

    SpringBoot集成MQTT示例詳解

    這篇文章主要為大家介紹了SpringBoot集成MQTT示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Java制作驗證碼的完整實例代碼

    Java制作驗證碼的完整實例代碼

    這篇文章主要給大家介紹了關(guān)于Java制作驗證碼的完整實例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • java實現(xiàn)簡易聊天功能

    java實現(xiàn)簡易聊天功能

    這篇文章主要為大家詳細介紹了java實現(xiàn)簡易聊天功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • 帶你重新認識Java動態(tài)代理

    帶你重新認識Java動態(tài)代理

    這篇文章主要為大家介紹了Java的動態(tài)代理,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • Java實現(xiàn)高效PDF文件傳輸技巧

    Java實現(xiàn)高效PDF文件傳輸技巧

    你是否曾為PDF文件傳輸?shù)牡托识鄲??現(xiàn)在,有了這份Java實現(xiàn)高效PDF文件傳輸技巧指南,你將能夠輕松解決這個問題,我們將分享一些實用的技巧和最佳實踐,幫助你優(yōu)化文件傳輸過程,不要錯過這個提高工作效率的機會,快來閱讀這份指南吧!
    2024-03-03
  • java 日志的數(shù)據(jù)脫敏的實現(xiàn)方法

    java 日志的數(shù)據(jù)脫敏的實現(xiàn)方法

    今日給大家介紹一下java 日志的數(shù)據(jù)脫敏的實現(xiàn)方法,可以更好的保護數(shù)據(jù)的安全,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 淺談java7增強的try語句關(guān)閉資源

    淺談java7增強的try語句關(guān)閉資源

    下面小編就為大家?guī)硪黄獪\談java7增強的try語句關(guān)閉資源。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Maven本地打包war包實現(xiàn)代碼解析

    Maven本地打包war包實現(xiàn)代碼解析

    這篇文章主要介紹了Maven本地打包war包實現(xiàn)代碼解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • Spring如何正確注入集合類型

    Spring如何正確注入集合類型

    這篇文章主要介紹了Spring如何正確注入集合類型,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • Java中對話框的彈出方法

    Java中對話框的彈出方法

    下面小編就為大家?guī)硪黄狫ava中對話框的彈出方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10

最新評論

永登县| 丹阳市| 信宜市| 西乌珠穆沁旗| 长宁县| 安庆市| 澎湖县| 库伦旗| 承德县| 山阳县| 巴马| 同心县| 黔西| 丽江市| 冕宁县| 兖州市| 普兰店市| 盈江县| 县级市| 咸宁市| 灌云县| 泊头市| 宿松县| 永修县| 丰城市| 观塘区| 白山市| 莱阳市| 思茅市| 两当县| 西丰县| 达孜县| 宜川县| 成武县| 正阳县| 班玛县| 日土县| 武安市| 鲁山县| 临安市| 新巴尔虎左旗|