服务端菜单接口的设计
menu表的各个列的意思: menu表 服务端的菜单项数据
id:唯一标识 url:做权限控制用的 path:请求路径,对应了前端的请求路径 component:组件的名字 name:
iconCls:组件的图标 keepAlice:标记 是否保护 requrieAuth:标记 进入组件要不要登录 parentId:父菜单 enabled:菜单项是否启动
制作服务端返回一个菜单列表
Menu类
该类本来还有KeepAlive和requireAuth两个属性,但是这两个属性不常用,所以就放到新建的Meta类里面去了,Menu新添加了一个private List
@Data
public class Menu {
private Integer id;
private String url;
private String path;
private String component;
private String name;
private String iconcls;
private Meta meta;
private List<Menu> children;
private Integer parentid;
private Boolean enabled;
}
Meta类
@Data
public class Meta {
private Boolean keepalive;
private Boolean requireauth;
}
在MenuMapper.xml中新增
<!--一对一的-->
<association property="meta" javaType="com.xyg.pojo.Meta">
<result column="keepAlive" property="keepalive" jdbcType="BIT"></result>
<result column="requireAuth" property="requireauth" jdbcType="BIT"></result>
</association>
SysConfigController控制类
在controller文件夹里面新建一个SysConfigController类,该类是系统设置类
前端传过来的id是不可信,不安全。
@RestController
@RequestMapping("/system/config")
public class SystemConfigController {
@Autowired
MenuService menuService;
@GetMapping("/menu")
public RespBean getMenusByHrId(){
return menuService.getMenusByHrId();
}
}
MenuService业务类
要传入id了,id从哪里来,我们登录的用户信息保存到security里面
SecurityContextHolder里面有一个getContext()方法.getAuthentication()它里面的getPrincipal(),Principal它是当前登录的用户对象,然后强转成Hr对象再获取它里面的id
@Service
public class MenuService {
@Autowired
MenuMapper menuMapper;
public RespBean getMenusByHrId() {
//Id从哪里来呢,前端传过来的信息是不可信,我们登录的用户信息保存在security,可以从Security里获取登录用户信息
return RespBean.ok("操作成功!",menuMapper.getMenusByHrId( ((Hr) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId()));
//SecurityContextHolder里面有一个getContext()方法.getAuthentication()它里面的getPrincipal(),Principal它是当前登录的用户对象,然后强转成Hr对象再获取它里面的id
}
}
MenuMapper接口
public interface MenuMapper {
List<Menu> getMenusByHrId(Integer hrid);
}
MenuMapper.xml
getMenusByHrId接口的SQL语句
<!--返回查询结果有点复杂有一对一、有一对多-->
<select id="getMenusByHrId" resultMap="Menus2">
SELECT DISTINCT m1.*,m2.id as id2,m2.component as component2,m2.enabled as enabled2,m2.iconCls as iconCls2,m2.keepAlive as keepAlive2,m2.`name` as `name2`,m2.parentId as parentId2,m2.requireAuth as requireAuth2,m2.path as path2
from menu m1,menu m2,hr_role hrr,menu_role mr
where m1.id=m2.parentId and hrr.hrid=#{hrid} and hrr.rid=mr.rid and mr.mid=m2.id AND m2.enabled=TRUE
ORDER BY m1.id,m2.id
</select>
resultMap
<resultMap id="BaseResultMap" type="com.xyg.pojo.Menu" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="url" property="url" jdbcType="VARCHAR" />
<result column="path" property="path" jdbcType="VARCHAR" />
<result column="component" property="component" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="iconCls" property="iconcls" jdbcType="VARCHAR" />
<result column="parentId" property="parentid" jdbcType="INTEGER" />
<result column="enabled" property="enabled" jdbcType="BIT" />
<!--一对一的-->
<association property="meta" javaType="com.xyg.pojo.Meta">
<result column="keepAlive" property="keepalive" jdbcType="BIT"></result>
<result column="requireAuth" property="requireauth" jdbcType="BIT"></result>
</association>
</resultMap>
<!--extends="BaseResultMap" 继承BaseResultMap 拥有父类的-->
<resultMap id="Menus2" type="com.xyg.pojo.Menu" extends="BaseResultMap">
<!--一对多的,里面还有meat一对一-->
<collection property="children" ofType="com.xyg.pojo.Menu">
<id column="id2" property="id" jdbcType="INTEGER" />
<result column="url2" property="url" jdbcType="VARCHAR" />
<result column="path2" property="path" jdbcType="VARCHAR" />
<result column="component2" property="component" jdbcType="VARCHAR" />
<result column="name2" property="name" jdbcType="VARCHAR" />
<result column="iconCls2" property="iconcls" jdbcType="VARCHAR" />
<result column="parentId2" property="parentid" jdbcType="INTEGER" />
<result column="enabled2" property="enabled" jdbcType="BIT" />
<!--一对一的-->
<association property="meta" javaType="com.xyg.pojo.Meta">
<result column="keepAlive2" property="keepalive" jdbcType="BIT"></result>
<result column="requireAuth2" property="requireauth" jdbcType="BIT"></result>
</association>
</collection>
</resultMap>
解析这个接口SQL语句
SELECT DISTINCT m1.*,m2.id as id2,m2.component as component2,m2.enabled as enabled2,m2.iconCls as iconCls2,m2.keepAlive as keepAlive2,m2.`name` as `name2`,m2.parentId as parentId2,m2.requireAuth as requireAuth2,m2.path as path2
from menu m1,menu m2,hr_role hrr,menu_role mr
where m1.id=m2.parentId and hrr.hrid=#{hrid} and hrr.rid=mr.rid and mr.mid=m2.id AND m2.enabled=TRUE
ORDER BY m1.id,m2.id
DISTINCT :查询不重复记录的条数
用到了4个表,其中menu表自己关联自己
3个表之间的关系:
菜单表 menu
用户和角色关联表 hr_role
菜单和角色关联表 menu_role
菜单表 menu : menu 自己和自己关联查询自己的 父菜单下的 子菜单 sql语句条件:当前菜单的id 等于 parentId m1 查询的是父菜单的,m2查询的是子菜单
用户和角色关联表 hr_role :查询当前用户的具备哪些角色 sql语句条件: 当前角色的ID 等于 这个用户角色 的用户id
菜单和角色关联表 menu_role:查询角色具备的菜单 sql语句条件:菜单的ID 等于 这个角色拥有的菜单 ID
就是根据用户的ID 需要查询出