# 需求

  • 主页菜单列表改为动态呈现方式
    (不同用户登录,看到的菜单是不一样的!)

# 实现

服务端设计

  • step01:设计 VO 对象 ( SysUserMenuVo
    @ 需要的资源:id、name、url


 --- 基于此对象,封装用户菜单信息(用户访问权限的菜单)


public class SysUserMenuVo implements  序列化接口{

	UID....

	private Integer id ; 
	private String name ; 
	private String url ; 
	private List<SysUserMenuVo> childs
}
  • step02:设计 Dao 中的方法( SysMenuDao.Dao.findUserMenus(Integer[] menuIds)

 --- 基于指定菜单id - 查询登录用户的菜单信息

List<SysUserMenuVo> findUserMenus(@Param("menuIds") Integer[] menuIds) //@Param("menuIds")

难点:只查1级菜单、2级菜单

<! 查询用户对应的菜单信息 >


<select id="findUserMenus" resultMap="sysUserMenuVo">
	select p.id  pi, p.name pname , p.url purl , c.id  , c.name  , c.url 
	from sys_menus p join sys_menus c 
	on c.parentId = p.id
	<where> <!-- where 自动把and 去掉 -->
		<foreach collection="array" 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="pid" /> 
	<result property="name" column="pname" />
	<result property="url" column="purl" />
	<collection property="childs" ofType="com.cy.pj.sys.vo.SysUserMenuVo">
		<id property="id" column="id" /> 
		<result property="name" column="name" />
		<result property="url" column="url" />		
	</collection>
</resultMap>



  • step03:设计 Service 的方法( SysMenuService.findUserMenus(userid)

	@Autowired
	private SysUserRoleDao sysUserRoleDao ; 


	public List<SysUserMenuVo> findUserMenus(Integer userId) {
		//1.参数校验
		
		//2.获取用户对应的角色id
		
		List<Integer> roleIds = SysUserRoleDao.findRoleIdsByUserId(userId);
		//3.基于角色id获取对应菜单id并校验
		List<Integer> menuIds = SysRoleMenuDao.findMenuIdsByRoleIds(roleIds.toArray(new Integer[])) ; 
		//4. 基于菜单id获取菜单信息
		List<SysUserMenuVo> list = SysMenuDao.findUserMenus(menuIds.toArray(new Integer[]))
		return list; 


	}
  • step04:设计 Controller 中的方法( PageController.doIndexUI(Model model)
	public String doIndexUI(Model model ){
		...
		用model 传递 返回的信息
		...
	}

客户端设计
基于 thymeleaf 模板引擎中的标签对用户的菜单信息进行呈现


<li class="treeview" th:each="um:${userMenus}">
...
<span>
[[${um.name}]]
</span>
...
	<ul class="treeview-menu">
		<li th:each="c:${um.childs}">
			<a th:onclick="javascript:doLoadUrl([[${c.url}]])">[[${c.name}]]</a>
		</li>
	</ul>

</li>



....


<script> function doLoadUrl(url) { $("#mainContentId").load(url); } </script>


# 2. 需求:限定登录时间(允许的时间范围之内可以登录,其他不可以)

技术分析:方案实现(AOP,Spring MVC 中的***,Filter)
本次方案:基于Spring MVC 中的 HandlerInterceptor 对象实现

# 实现

step01:编写 TimeAccessInterceptor 类(实现 HandlerInterceptor 接口)

我们的 web 包中添加…

public class TimeAccessInterceptor implements HandlerInterceptor {

	Spring MVC中的***定义,基于此对象实现对登录操作的时间访问限制

	DispatcherServlet --> TimeAccessInterceptor -->  XxxController
														(Handler)


	此方***在后端控制方法执行前执行
		↓
	@Override
	public boolean preHandle(  ...   ) throws Exception {

		1.定义允许访问的时间范围
		Calendar c = Calendar.getInstance() ; //日历对象
		c.set(Calendar.HOUR_OF_DAY , 9) ; 
		c.set(Calendar.MINUTE , 0 ) ; 
		c.set(Calendar.SECOND , 0 );
		long start = c.getTimeInMillis() ; // 起始访问时间

		c.set(Calendar.HOUR_OF_DAY , 16) ; 
		long end = c.getTimeInMillis() ; 
		
		2.获取当前进行业务判定
		long currentTime = System.currentTimeMills() ; 
		if(start < currentTime && end > currentTime ) {
			return true ;  //false 表示拒绝对后面的 Handler(Controller)的执行,true表示放行
		}
		throw new ServiceException("请在固定时间登录");

	}
}

step02:配置 TimeAccessInterceptor 对象(定义 SpringWebConfig 配置类,在此类中进行配置)

@Configuration 
public class SpringWebConfig implements WebMvcConfigurer { /* 提供了一些web注册方法 */

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(new TimeAccessInterceptor())
		.addPathPatterns("/user/doLogin"); //设置
	}

}