共计 5130 个字符,预计需要花费 13 分钟才能阅读完成。
1 首页菜单动态化实现
1.1 背景
用户心愿在登陆当前基于权限的不同,在首页左侧出现不同的菜单,如何实现呢?
1.2 初步剖析
基于登陆用户 id, 查问用户对应的菜单信息而后进行出现
1.3 原理利用剖析
计划实现上能够基于同步或异步查问而后进行菜单数据出现。
1.4 最终解决方案
用户登陆当前,基于用户登陆 id 查问用户对应的一级菜单,二级菜单而后存储到指定作用域,当进入零碎首页后基于 thymeleaf 出现用户菜单。
1.4.1 Pojo 类的定义
基于用户需要将查问到的一级菜单以及一级菜单对应的二级菜单查问进去,并进行封装。
package com.cy.pj.sys.pojo;
@Setter
@Getter
@ToString
public class SysUserMenu implements Serializable{
private static final long serialVersionUID = -8126757329276920059L;
private Integer id;
private String name;
private String url;
private List<SysUserMenu> childs;
}
1.4.2 Dao 接口实现
在 SysMenuDao 中增加办法,基于菜单 id 获取所有菜单相干信息, 代码如下
/**
* 基于菜单获取菜单信息
* **@param** menuIds
* **@return**
*/
List<SysUserMenu> findMenusByIds(List<Integer> menuIds);
1.4.3 Mapper 元素定义
在 SysMenuMapper.xml 文件中增加如下映射元素:
<select id="findMenusByIds" resultMap="sysUserMenu">
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.pojo.SysUserMenu" id="sysUserMenu">
<!-- 一级菜单映射 -->
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="url" column="url"/>
<!-- 二级菜单映射 -->
<collection property="childs" ofType="com.cy.pj.sys.pojo.SysUserMenu">
<id property="id" column="cid"/>
<result property="name" column="cname"/>
<result property="url" column="curl"/>
</collection>
</resultMap>
1.4.4 Service 接口及实现
在 SysMenuService 接口及实现类中定义如下办法,基于用户 id 查问用户对应的菜单信息, 代码如下
@Override
public List<SysUserMenu> findUserMenusByUserId(Integer id) {
//1. 对用户 id 进行判断
//2. 基于用户 id 查找用户对应的角色 id
List<Integer> roleIds=sysUserRoleDao.findRoleIdsByUserId(id);
//3. 基于角色 id 获取角色对应的菜单信息, 并进行封装.
List<Integer> menuIds=sysRoleMenuDao.findMenuIdsByRoleIds(roleIds);
//4. 基于菜单 id 获取用户对应的菜单信息并返回
return sysMenuDao.findMenusByIds(menuIds);
}
1.4.5 Controller 类实现
批改 PageController 中的 doIndexUI 办法
@RequestMapping("doIndexUI")
public String doIndexUI(Model model) {SysUser user=ShiroUtils.getUser();
model.addAttribute("username", user.getUsername());
List<SysUserMenu>userMenus=sysUserService.findUserMenusByUserId(user.getId());
model.addAttribute("userMenus",userMenus);
return "starter";
}
1.4.6 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>
2 管制层拜访拦挡实现
2.1 背景
最近我的项目业务上有新的需要,要求零碎登陆操作要有工夫限度。
2.2 初步剖析
对于相似需要的实现,可采纳过滤器(Filter),SpringMVC 拦截器,AOP 等进行实现。对于过滤器而言个别次要利用在我的项目中共性的过滤,AOP 须要依靠于动静代理以及切面对象, 这样性能方面绝对较差,所以最终抉择应用 Spring MVC 拦截器进行实现。
2.3 原理利用剖析
Spring MVC 中的拦截器基于回调机制,能够在指标办法执行之前,先进行业务检测,满足条件则放行,不满足条件则进行拦挡,拦截器原理剖析如下图所示:
2.4 最终解决方案实现
第一步:拦截器定义,要害代码如下:
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");
}
}
3 我的项目打包策略及实现
3.1 jar 包形式实现(举荐)
如果应用的是 sts,可间接对我的项目进行 maven install 操作,而后在我的项目 target 目录中找到对应的 jar 包,在当前目录下执行 java -jar project-a.jar 即可(如果 project-a.jar 为打包好的 jar 文件)
阐明:能够在打包时跳过测试类,关上 pom.xml, 在 properties 元素中增加跳过测试元素(<skipTests>true</skipTests>),代码如下:
<properties>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
</properties>
3.2 war 包形式实现(理解)
第一步:批改 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
4 我的项目总结
4.1 知识点总结
- Spring Boot (入门,根底,进阶)
- Thymeleaf&ajax
- dbms(动吧零碎中的权限子系统)
- Spring AOP (AspectJ, 事务, 异步, 缓存, 日志)
- Shiro (平安框架 - 认证, 受权, 会话, 记住我, 加密)
4.2 我的项目业务总结
1. 我的项目中各个模块之间的业务关系。
2. 我的项目中各个业务模块的实现过程?(pojo,dao,service,controller)
3. 我的项目中事务的管制,缓存利用,认证和受权外围的业务实现。
4. 倡议: 通读阿里巴巴的开发手册, 相熟其规范。
4.3 我的项目代码实现总结
我的项目外围业务流程,如图所示: