A.左侧菜单
[用户登录后只能看到自己对应权限的菜单]
用户登陆成功后通过用户id进行5表联查查询当前用户对应的所有菜单把查询出的结果。转换成json返回前端页面利用前端构建树形菜单工具展示在页面上。
@ResponseBody
@RequestMapping(value = "/list.do")
public List<Baisi_Menu> getMenusByPid(String menu_id, HttpSession session) {
if (menu_id == null || menu_id.equals("")) {
menu_id = 0 + "";
}
// session中取出登录的用户
Baisi_User user = (Baisi_User) session.getAttribute("user");
//通过用户id获取当前用户对应的所有菜单
return service.getMenusByPid(menu_id, user.getUser_id());
}
但是用户仍然可以通过拼接url的方式访问到自己没有权限的页面
所以需要进行权限拦截↓↓↓
B.权限拦截
[基于springmvc拦截器实现权限拦截]
- 用户登陆后通过用户id拿到当前用户所有菜单权限存放到session中
//通过登录用户id获取所有menu_code
List<String> mlist = mservice.getMenusByUid(user.getUser_id());
session.setAttribute("mlist", mlist);
- 声明了一个自定义@PathChange注解
@Target(ElementType.METHOD)//注解作用的地方
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
public @interface PathChange {
String name() default "";
}
3.把自定义的注解放在controller方法上
//注解中需要传入一个请求标识符MENU_CODE
//这样每个菜单对应一个权限
@PathChange(name = "CDGL")
@ResponseBody
@RequestMapping(value = "/getAll.do")
public List<Baisi_Menu> getAll(String menu_id) {
if (menu_id == null || menu_id.equals("")) {
menu_id = 0 + "";
}
return service.getAll(menu_id);
}
4.在拦截器中先从session中取到当前用户的所有菜单权限List<>
List<String> list = (List<String>) request.getSession().getAttribute("mlist");
5.通过文档得知,第三个参数就是即将调用的控制器方法。于是我们可以通过反射得到@PathChange注解:
HandlerMethod h = (HandlerMethod) handler;
String menu_code = h.getMethodAnnotation(PathChange.class).name();
- 但是实际运行中发现很严重的问题,那就是handler的实际类型并不总是HandlerMethod类型,因此第一行代码经常会扔ClassCastException。经过研究发现,只有当GET请求是请求静态文件时(在spring配置文件里会配置静态文件的URI),handler的实际类型会是DefaultServletHttpRequestHandler,此时强制转换就会报错。
- 解决办法
在执行强制转换之前用instanceof检查参数handler的实际类型。
String menu_code = "";
//检查参数handler的实际类型
if (handler instanceof HandlerMethod) {
HandlerMethod h = (HandlerMethod) handler;
if (h.getMethodAnnotation(PathChange.class) != null) {
if (h.getMethodAnnotation(PathChange.class).name() != null
&& !h.getMethodAnnotation(PathChange.class).name().equals("")) {
menu_code = h.getMethodAnnotation(PathChange.class).name();
}
}
}
- 然后拿着取出的MENU_CODE和权限集合List进行对比对比成功则放行,失败则拦截并执行相应操作
if (list.contains(menu_code)) {
return true;
} else {
//拦截后的操作
return false;
}
C.按钮显隐
- 后续…