用户希望在登陆以后基于权限的不同,在首页左侧呈现不同的菜单,如何实现呢?
基于登陆用户id,查询用户对应的菜单信息然后进行呈现
方案实现上可以基于或异步查询然后进行菜单数据呈现。
用户登陆以后,基于用户登陆id查询用户对应的一级菜单,二级菜单然后存储到指定作用域,当进入系统首页后基于thymeleaf呈现用户菜单。
基于用户需求将查询到的一级菜单以及一级菜单对应的二级菜单查询出来,并进行封装。
package com.cy.pj.sys.vo;
@Setter
@Getter
@ToString
public class SysUserMenuVo implements Serializable{
private static final long serialVersionUID =
-8126757329276920059L;
private Integer id;
private String name;
private String url;
private List<SysUserMenuVo> childs;
}
在SysMenuDao中添加方法,代码如下
/**
* 基于菜单获取菜单信息
* @param menuIds
* @return
*/
List<SysUserMenuVo> findMenusByIds(
@Param("menuIds")List<Integer> menuIds);
在SysMenuMapper.xml文件中添加如下映射元素:
<select id="findMenusByIds"
resultMap="sysUserMenuVo">
select p.id,p.name,p.url,c.id cid,c.name cname,c.url curl
from sys_menus p join sys_menus c
on c.parentId=p.id
<where>
<foreach collection="menuIds"
open="("
close=")"
separator="or"
item="menuId">
c.id=#{menuId}
</foreach>
and p.parentId is null
</where>
</select>
<resultMap type="com.cy.pj.sys.vo.SysUserMenuVo" id="sysUserMenuVo">
<!-- 一级菜单映射 -->
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="url" column="url"/>
<!-- 二级菜单映射 -->
<collection property="childs" ofType="com.cy.pj.sys.vo.SysUserMenuVo">
<id property="id" column="cid"/>
<result property="name" column="cname"/>
<result property="url" column="curl"/>
</collection>
</resultMap>
在SysMenuService接口及实现类中定义如下方法,代码如下
@Override
public List<SysUserMenuVo> findUserMenusByUserId(Integer id) {
//1.对用户id进行判断
//2.基于用户id查找用户对应的角色id
List<Integer> roleIds=
sysUserRoleDao.findRoleIdsByUserId(id);
//3.基于角色id获取角色对应的菜单信息,并进行封装.
List<Integer> menuIds=
sysRoleMenuDao.findMenuIdsByRoleIds(
roleIds.toArray(new Integer[] {}));
//4.基于菜单id获取用户对应的菜单信息并返回
return sysMenuDao.findMenusByIds(menuIds);
}
修改PageController中的doIndexUI方法
@RequestMapping("doIndexUI")
public String doIndexUI(Model model) {
SysUser user=ShiroUtils.getUser();
model.addAttribute("username", user.getUsername());
List<SysUserMenuVo> userMenus=
sysUserService.findUserMenusByUserId(user.getId());
model.addAttribute("userMenus",userMenus);
return "starter";
}
将如下代码替换starter.html中Sidebar Menu对应的位置。
<ul class="sidebar-menu" data-widget="tree">
<li class="header">HEADER</li>
<li class="treeview" th:each="m:${userMenus}">
<a href="#"><i class="fa fa-link"></i>
<span>[[${m.name}]]</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li th:each="c:${m.childs}">
<a th:onclick="javascript:doLoadRS([[${c.url}]])">[[${c.name}]]</a>
</li>
</ul>
</li>
</ul>
当点击对应的菜单元素时,其事件处理函数如下:
<script type="text/javascript">
function doLoadRS(url){
$("#mainContentId").load(url);
}
</script>
最近项目业务上有新的需求,要求系统登陆操作要有时间限制。
对于类似需求的实现,可采用过滤器,SpringMVC拦截器,AOP等进行实现。对于过滤器而言一般主要应用在项目中共性的过滤,AOP需要依托于动态代理以及切面对象性能方面相对较差,所以最终选择使用Spring MVC拦截器进行实现。
Spring MVC中的拦截器基于回调机制,可以在目标方法执行之前,先进行业务检测,满足条件则放行,不满足条件则进行拦截,拦截器原理分析如下图所示:
第一步:拦截器定义,关键代码如下:
package com.cy.pj.common.web;
/**
* Spring MVC中拦截器
* @author Administrator
*/
public class TimeAccessInterceptor
implements HandlerInterceptor {
/**
* preHandle在控制层目标方法执行之前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("preHandler()");
//获取java中的日历对象
Calendar c=Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 6);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
long start=c.getTimeInMillis();
c.set(Calendar.HOUR_OF_DAY,23);
long end=c.getTimeInMillis();
long cTime=System.currentTimeMillis();
if(cTime<start||cTime>end)
throw new ServiceException("不在访问时间之内");
return true;
}
}
第二步:拦截器配置,关键代码如下
package com.cy.pj.common.config;
@Configuration
public class SpringWebConfig implements WebMvcConfigurer{//web.xml
//配置spring mvc 拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TimeAccessInterceptor())
.addPathPatterns("/user/doLogin");
}
}
假如使用的是sts,可直接对项目进行maven install
操作,然后在项目target目录中找到对应的jar包,在当前目录下执行java -jar project-a.jar
即可(假如project-a.jar为打包好的jar文件)
说明:可以在打包时跳过测试类,打开pom.xml
,在properties元素中添加跳过测试元素(
),代码如下:
<properties>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
</properties>
第一步:修改pom.xml,将打包方式修改为war:
<packaging>war</packaging>
第二步:添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
修改启动类
@SpringBootApplication
public class Application extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
第三步:对项目进行maven install操作
第四步:将项目target目录下生成的war包拷贝到指定tomcat的webapps目录,启动tomcat测试运行,例如:
http://localhost:8080/CGB-DB-SYS-V1.04-0.0.1-SNAPSHOT/doIndexUI