文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何基于SpringBoot实现自动装配返回属性

2023-06-29 16:13

关注

这篇文章主要介绍了如何基于SpringBoot实现自动装配返回属性,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

一:需求背景

在业务开发中经常会有这个一个场景,A(业务表)表中会记录数据的创建人,通常我们会用userId字段记录该数据的创建者,但数据的使用方会要求展示该数据的创建者姓名,故我们会关联用户表拿该用户的姓名。还有一些枚举值的含义也要展示给前端。导致原本一个单表的sql就要写成多表的关联sql,以及枚举含义的转换很是恶心。

例如:业务对象BusinessEntity.java

public class BusinessEntity {        private Long createUserId;     * 创建者名称 (需要关联用户表)    private String userName;     * 数据状态(0:有效,1失效)    private String status;     * 数据状态含义(需要解析0或1的含义给前端)    private String statusName;     * 数据集合    private List<BusinessEntity> list;}

二:设计思路

就像@JsonFormat注解,可以指定返回日期格式。我们是不是可以也自定义一个注解,通过这个注解,我们可以自动的把需要联表的数据userName自动填充,需要解析的数据数据statusName如何通过枚举解析。

故定义枚举@AutowiredAttribute如下

@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})@Retention(RUNTIME)@Documentedpublic @interface AutowiredAttribute {        String param() default "";     * 默认为BaseEnum.class,     * 当为默认时注入数据的来源时redis缓存,     * 否则为枚举类型    Class<? extends BaseEnum> enumClass() default BaseEnum.class;     * 数据源    DataSourceEnum dataSource() default DataSourceEnum.EMPTY;}

定义公共枚举继承继承接口BaseEnum

public interface BaseEnum {    String getCode();    String getMsg();}

定义数据源枚举如下dataSource

public enum DataSourceEnum implements BaseEnum {    SYSTEM_DICT("sys:dict:", "系统字典值", "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;}

三:使用方法

对比原对象:通过新增注解,就避免的关联查询和数据解析

public class BusinessEntity {        private Long createUserId;     * 创建者名称 (需要关联用户表)    @AutowiredAttribute(param = "createUserId", dataSource = DataSourceEnum.USER_NAME)    private String userName;     * 数据状态(0:有效,1失效)    private String status;     * 数据状态含义(需要解析0或1的含义给前端)    @AutowiredAttribute(param = "status", enumClass = StatusEnum.class)    private String statusName;     * 数据集合    @AutowiredAttribute    private List<BusinessEntity> list;}

四:注解解析器(核心代码)

@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) {//仅仅对相应为200结果处理            Object data = ((ResponseResult<?>) body).getData();            Class<?> aClass = data.getClass();            if (data instanceof List) {                //集合对象设置属性                setForListBeanArr((List) data);            } else {                //判断是否为自定义java对象                if (aClass.getSuperclass() instanceof Object) {                    setForJavaBeanArr(data, aClass);                }            }        return body;        void setForListBeanArr(List<Object> list) {        for (Object object : list) {            Class<?> aClass = object.getClass();            setForJavaBeanArr(object, aClass);     * 为自定义javaBean对象设置值    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)) {            //不规范的        } 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;}

实现了从数据库(mysql)自动查询,并把结果缓冲到数据库。

感谢你能够认真阅读完这篇文章,希望小编分享的“如何基于SpringBoot实现自动装配返回属性”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯