aisell(8) 菜单menu结构设计及背后业务思考

在这里插入图片描述
在真实项目中出现假数据是很少的,包括菜单的内容结构都是由数据库查询生成的,我们需要做的就是让前台需要的数据格式与后台发送给前台的数据格式一致就好

    /**
     * 1.方法一:由于easyui的菜单需要"text": "系统管理",
     * 所以这里使用getText来进行匹配
     * 2.方法二:
     *   @Column (name = "name")
     *   private String text;
     * 同样能达到以上的效果
     * @return
     */
    public String getText() {
        return name;
    }

假设现在我业务中的菜单分为子菜单和父菜单,我们如何将其层级使用easyui呈现出来?
在前后端数据类型结构一致、不考虑不同用户权限等问题的情况下,我们直接使用一对多(@OneToMany),在找到父层级之后,能直接找到子菜单

但是我们尽量不要这么做,因为我们必须考虑到每个用户的权限问题,即每个不同的用户能根据他所对应的权限拥有不同的子菜单,没有权限的菜单我们让它不显示是最好的(当然,你如果要显示的话,那就让用户在点开没有权限的菜单时,弹出没有权限提示的窗口让用户知道就好了)

所以

鉴于这种情况,一对多是无法完成的(因为它会将所有子菜单全部显示出来,达不到想要的隐藏某些子菜单的业务效果),我们需要重新设计表与表之间的关系!

思考:
1.如何将权限与菜单绑定起来

2.之前是父菜单找子菜单,现在是子菜单找父菜单,这么找

3.子菜单找到父菜单后,应该把子菜单放到父菜单中

1.通过当前登录用户(employee)找到该用户对应的角色(role),再通过对应的角色(role)找到对应的权限(permission),再通过权限(permission)找到对应的菜单(menu)
一个用户可能有多个角色,最终可能导致有多个重复的菜单,记得要去重
在这里插入图片描述
2.外键关联后,通过当前用户就能直接拿到对应的子菜单
在这里插入图片描述
3.拿到子菜单后是没有层级结构的,我们还需要通过子菜单找到父菜单,然后将子菜单放到父菜单中

    @Override
    public List<Menu> findParentMenus() {
        //1.创建一个装父菜单的容器
        List<Menu> parentMenus = new ArrayList<>();
        //2.拿到这个用户的菜单
        Employee loginUser = UserContent.getEmp();
        List<Menu> menus = menuRepository.findMenusByUser(loginUser.getId());
        //3.遍历子菜单
        menus.forEach(m -> {
            // 3.1 通过子菜单获取父菜单
            Menu parentMenu = m.getParent();
            // 3.2 判断集合中是否有这个父菜单
            if (!parentMenus.contains(parentMenu)) {
                //没有的话,就把它放进去
                parentMenus.add(parentMenu);
            }
            parentMenu.getChildren().add(m);
        });
        return parentMenus;
    }

先前解释过,当前业务需求是不需要通过父菜单找到子菜单的(即配置一对多),但是我的domain里面仍然需要保留一个private List<Menu> children = new ArrayList<>();,因为我需要用父菜单装子菜单啊,所以必须存在这个字段,但是这个字段不需要维护到数据库中,所以我们加个 @Transient 注解让它不被JPA维护!

    @Transient
    private List<Menu> children = new ArrayList<>();

4.注意:
在springmvc将字符串转换成json返回给前台时,是不需要将parent也返回的,所以我们需要加上这个注解:

    @ManyToOne
    @JoinColumn(name = "parent_id")
    @JsonIgnore
    private Menu parent;

5.最后返回的结果:
在这里插入图片描述
注意父菜单没有url,因为我配置了JsonInclude.Include.NON_NULL

<!-- Spring MVC 配置 -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json; charset=UTF-8</value>
                        <value>application/x-www-form-urlencoded; charset=UTF-8</value>
                    </list>
                </property>
                <!-- No serializer:配置 objectMapper 为我们自定义扩展后的 CustomMapper,解决了返回对象有关系对象的报错问题 -->
                <property name="objectMapper">
                    <bean class="cn.itsource.aisell.common.CustomMapper"/>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
public class CustomMapper extends ObjectMapper {
    public CustomMapper() {
    	// 该配置让值为null的属性不成为json数据返回给前台
        this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 设置 SerializationFeature.FAIL_ON_EMPTY_BEANS 为 false
        this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值