1. Repository持久层
Spring Data 建议定义接口完成SQL语句的操作,该接口可以直接作为Repository组件使用。当使用repository模式时,既能体现业务逻辑组件封装repository组件的门面模式,也可以分离业务逻辑组件和repository组件的功能:业务逻辑组件负责业务逻辑的变化,而repository组件负责持久化的技术变化,这正是桥接模式的应用。
引入repository模式后,每个repository组件包含了数据库的访问逻辑,每个repository组件可对一个数据库表完成基本的CRUD操作。
在spring data 当中,基本的增删改查已经在父类JpaRepository 中完成,自定义接口中只需通过@Query 注解完成个性化查询即可。
1.1 DeptRepository
public interface DeptRepository extends JpaRepository<Dept, Long> {
@Query("select new Map(p.id, p.name) from Dept t")
public List<HashMap<String, Object>> findDepts();
}
1.2 JobRepository
public interface JobRepository extends JpaRepository<Job, Long> {
@Query("select new Map(j.id , j.code, j.name) from Job j")
public List<Map<String, Object>> findJobs();
}
1.3 ModuleRepository
public interface ModuleRepository extends JpaRepository<Module, Long>, JpaSpecificationExecutor<Module> {
@Modifying
@Query("delete Module m where m.code like ?1")
public void setCode(String code) ;
@Query("select m from Module m where m.code like :parentCode and length(m.code) = :sonCodeLen")
public List<Module> findModules(@Param("parentCode")String parentCode, @Param("sonCodeLen")int sonCodeLen);
@Query("select Max(m.code) from Module m where m.code like :parentCode and length(m.code) = :sonCodeLen ")
public String findUniqueEntity(@Param("parentCode")String parentCode, @Param("sonCodeLen")int sonCodeLen);
}
1.4 PopedomRepository
public interface PopedomRepository extends JpaRepository<Popedom, Long> {
@Query("select p.opera.code from Popedom p where p.role.id = :id and p.module.code = :parentCode")
public List<String> findByIdAndParentCode(@Param("id")long id, @Param("parentCode")String parentCode);
@Modifying
@Query("delete Popedom p where p.role.id = :id and p.module.code = :parentCode")
public void setByIdAndParentCode(@Param("id")long id, @Param("parentCode")String parentCode);
@Query("select distinct p.module.code from Popedom p where "
+ "p.role.id in(select r.id from Role r "
+ "inner join r.users u where u.id = ?1 ) "
+ "order by p.module.code asc")
public List<String> getUserPopedomModuleCodes(long id);
@Query("select distinct p.opera.code from Popedom p "
+ "where p.role.id in(select r.id from Role r "
+ "inner join r.users u where u.id = ?1 ) order by p.opera.code asc")
public List<String> getUserPopedomOperasCodes(long id);
}
1.5 RoleRepository
public interface RoleRepository extends JpaRepository<Role, Long>, JpaSpecificationExecutor<Role> {
}
1.6 UserRepository
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
@Query("select u.id from User u where u.id not in(select u.id from User u inner join u.roles r where r.id = ?1)")
List<String> getRolesUsers(long id);
@Query("select u.id from User u inner join u.roles r where r.id = ?1")
List<String> findRoleUsers(long id);
}
2JSP页面分页功能
2.1 分页实体
package org.oa.common.util.page;
public class PageModel {
/** 分页中默认一个5条数据 */
public static final int PAGE_DEFAULT_SIZE = 5;
/** 分页总数据条数 */
private long recordCount;
/** 当前页面 */
private int pageIndex;
/** 每页分多少条数据 */
private int pageSize = PAGE_DEFAULT_SIZE;
/** 总页数 */
private int totalSize;
public long getRecordCount() {
this.recordCount = this.recordCount <= 0 ? 0 : this.recordCount;
return recordCount;
}
public void setRecordCount(long recordCount) {
this.recordCount = recordCount;
}
public int getPageIndex() {
this.pageIndex = this.pageIndex <= 0 ? 1 : this.pageIndex;
/** 判断当前页面是否超过了总页数:如果超过了默认给最后一页作为当前页 */
return pageIndex;
}
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
public int getPageSize() {
this.pageSize = this.pageSize <= PAGE_DEFAULT_SIZE ? PAGE_DEFAULT_SIZE : this.pageSize;
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalSize() {
if (this.getRecordCount() <= 0) {
totalSize = 0;
} else {
totalSize = (int) ((this.getRecordCount() - 1) / this.getPageSize() + 1);
}
return totalSize;
}
public int getFirstLimitParam() {
return (this.getPageIndex() - 1) * this.getPageSize();
}
}
2.2 自定义标签库
package org.oa.common.util.page;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class PagerTag extends SimpleTagSupport {
/** 定义请求URL中的占位符常量 */
private static final String TAG = "{0}";
/** 当前页码 */
private int pageIndex;
/** 每页显示的数量 */
private int pageSize;
/** 总记录条数 */
private int recordCount;
/** 请求URL page.action?pageIndex={0} */
private String submitUrl;
/** 定义总页数 */
private int totalPage = 0;
/** 在页面上引用自定义标签就会触发一个标签处理类 */
@Override
public void doTag() throws JspException, IOException {
/** 定义它拼接是终的结果 */
StringBuilder res = new StringBuilder();
res.append("<center>\n" + "\t\t<p style=\"text-align: center;\">\n" + "\t\t\t<!-- 设计导航-->\n"
+ "\t\t\t<nav class=\"nav form-inline\">\n" + "\t\t\t\t <ul class=\"pagination alin\">");
/** 定义它拼接中间的页码 */
StringBuilder str = new StringBuilder();
/** 判断总记录条数 */
if (recordCount > 0) { // 1499 / 15 = 100
/** 需要显示分页标签,计算出总页数 需要分多少页 */
totalPage = (this.recordCount - 1) / this.pageSize + 1;
/** 判断上一页或下一页需不需要加a标签 */
if (this.pageIndex == 1) { // 首页
str.append("<li class=\"disabled\" ><a href=\"#\">上一页</a></li>");
/** 计算中间的页码 */
this.calcPage(str);
/** 下一页需不需要a标签 */
if (this.pageIndex == totalPage) {
/** 只有一页 */
str.append("<li class=\"disabled\" ><a href=\"#\">下一页</a></li>");
} else {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex + 1));
str.append("<li><a href='" + tempUrl + "'>下一页</a></li>");
}
} else if (this.pageIndex == totalPage) { // 尾页
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex - 1));
str.append("<li><a href='" + tempUrl + "'>上一页</a></li>");
/** 计算中间的页码 */
this.calcPage(str);
str.append("<li class=\"disabled\" ><a href=\"#\">下一页</a></li>");
} else { // 中间
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex - 1));
str.append("<li><a href='" + tempUrl + "'>上一页</a></li>");
/** 计算中间的页码 */
this.calcPage(str);
tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex + 1));
str.append("<li><a href='" + tempUrl + "'>下一页</a></li>");
}
res.append(str);
/** 开始条数 */
int startNum = (this.pageIndex - 1) * this.pageSize + 1;
/** 结束条数 */
int endNum = (this.pageIndex == this.totalPage) ? this.recordCount : this.pageIndex * this.pageSize;
res.append("<li><a style=\"background-color:#D4D4D4;\" href=\"#\">共<font color='red'>" + this.recordCount
+ "</font>条记录,当前显示" + startNum + "-" + endNum + "条记录</a> </li>");
res.append("<div class=\"input-group\">\n"
+ "\t\t\t\t\t\t\t\t\t <input id='pager_jump_page_size' value='" + this.pageIndex
+ "' type=\"text\" style=\"width: 60px;text-align: center;\" class=\"form-control\" placeholder=\""
+ this.pageIndex + "\"\">\n" + "\t\t\t\t\t\t\t\t\t <span class=\"input-group-btn\">\n"
+ "\t\t\t\t\t\t\t\t\t <button class=\"btn btn-info\" id='pager_jump_btn' type=\"button\">GO</button>\n"
+ "\t\t\t\t\t\t\t\t\t </span>\n" + "\t\t\t\t\t \t\t\t\t </div>");
res.append("<script type='text/javascript'>");
res.append(" document.getElementById('pager_jump_btn').onclick = function(){");
res.append(" var page_size = document.getElementById('pager_jump_page_size').value;");
res.append(" if (!/^[1-9]\\d*$/.test(page_size) || page_size < 1 || page_size > " + this.totalPage
+ "){");
res.append(" alert('请输入[1-" + this.totalPage + "]之间的页码!');");
res.append(" }else{");
res.append(" var submit_url = '" + this.submitUrl + "';");
res.append(" window.location = submit_url.replace('" + TAG + "', page_size);");
res.append(" }");
res.append("}");
res.append("</script>");
} else {
res.append(
"<li><a style=\"background-color:#D4D4D4;\" href=\"#\">总共<font color='red'>0</font>条记录,当前显示0-0条记录。</a> </li>");
}
res.append("</ul></nav></p></center>");
this.getJspContext().getOut().print(res.toString());
}
/** 计算中间页码的方法 */
private void calcPage(StringBuilder str) {
/** 判断总页数 */
if (this.totalPage <= 11) {
/** 一次性显示全部的页码 */
for (int i = 1; i <= this.totalPage; i++) {
if (this.pageIndex == i) {
/** 当前页码 */
str.append("<li class=\"active\" ><a href=\"#\">" + i + "</a></li>");
} else {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<li><a href='" + tempUrl + "'>" + i + "</a></li>");
}
}
} else {
/** 靠首页近些 */
if (this.pageIndex <= 8) {
for (int i = 1; i <= 10; i++) {
if (this.pageIndex == i) {
/** 当前页码 */
str.append("<li class=\"active\" ><a href=\"#\">" + i + "</a></li>");
} else {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<li><a href='" + tempUrl + "'>" + i + "</a></li>");
}
}
str.append("<li><a href=\"#\">...</a></li>");
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(this.totalPage));
str.append("<li><a href='" + tempUrl + "'>" + this.totalPage + "</a></li>");
}
/** 靠尾页近些 */
else if (this.pageIndex + 8 >= this.totalPage) {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(1));
str.append("<li><a href='" + tempUrl + "'>1</a></li>");
str.append("<li><a href=\"#\">...</a></li>");
for (int i = this.totalPage - 10; i <= this.totalPage; i++) {
if (this.pageIndex == i) {
/** 当前页码 */
str.append("<li class=\"active\" ><a href=\"#\">" + i + "</a></li>");
} else {
tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<li><a href='" + tempUrl + "'>" + i + "</a></li>");
}
}
}
/** 在中间 */
else {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(1));
str.append("<li><a href='" + tempUrl + "'>1</a></li>");
str.append("<li><a href=\"#\">...</a></li>");
for (int i = this.pageIndex - 4; i <= this.pageIndex + 4; i++) {
if (this.pageIndex == i) {
/** 当前页码 */
str.append("<li class=\"active\" ><a href=\"#\">" + i + "</a></li>");
} else {
tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<li><a href='" + tempUrl + "'>" + i + "</a></li>");
}
}
str.append("<li><a href=\"#\">...</a></li>");
tempUrl = this.submitUrl.replace(TAG, String.valueOf(this.totalPage));
str.append("<li><a href='" + tempUrl + "'>" + this.totalPage + "</a></li>");
}
}
}
/** setter method */
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public void setRecordCount(int recordCount) {
this.recordCount = recordCount;
}
public void setSubmitUrl(String submitUrl) {
this.submitUrl = submitUrl;
}
}
2.3 tld标签文件
<?xml version="1.0" encoding="utf-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<!-- 描述 自定义标签版本的一种描述 -->
<description>Page 1.0 core library</description>
<!-- 显示的名称 导包进行的一个展示 -->
<display-name>Page core</display-name>
<!-- 版本号 -->
<tlib-version>1.0</tlib-version>
<!-- 短名 -->
<short-name>page</short-name>
<!-- uri :导包 -->
<uri>/page-tags</uri>
<!-- 定义一个标签 -->
<tag>
<!-- 标签名 -->
<name>page</name>
<!-- 标签处理类 -->
<tag-class>org.oa.common.util.page.PagerTag</tag-class>
<!-- 设置标签为空 -->
<body-content>empty</body-content>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 表示分页的第几页 -->
<name>pageIndex</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 表示分页标签 ,每页显示多少条数据 -->
<name>pageSize</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 记录分页的总数 -->
<name>recordCount</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 -->
<name>submitUrl</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 -->
<name>style</name>
<!-- 必须的 -->
<required>false</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
3. 业务层接口及其实现类
SysService:
package org.oa.sys.service;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.common.util.page.PageModel;
import org.oa.sys.domain.Dept;
import org.oa.sys.domain.Module;
import org.oa.sys.domain.Role;
import org.oa.sys.domain.User;
import org.oa.sys.dto.UserModule;
import org.oa.sys.vo.TreeData;
public interface SysService {
/**
* @return 查询所有的部门
*/
List<Dept> getAllDepts();
/**
* 异步登录的业务层接口方法
* @param params
* @return
*/
Map<String, Object> login(Map<String, Object> params);
/**
* 根据用户的主键查询用户信息,包含了延迟加载的部门和职位信息
* @param userId
* @return
*/
User getUserById(Long id);
/**
* 修改自己
* @param user
*/
void updateSelf(User user, HttpSession session);
/**
* @return 异步加载部门与职位的json字符串信息写回到页面
*/
Map<String, Object> getAllDeptsAndJobsAjax();
/**
* 分页查询用户信息
*
* @param user
* @param pageModel
* @return
*/
List<User> getUsersByPage(User user, PageModel pageModel);
/**
* 批量删除用户
* @param ids
*/
void deleteUserByUserIds(String ids);
/**
* 校验用户是否已经被注册
* @param userId
* @return
*/
String isUserValidAjax(Long id);
/**
*
* @param user
*/
void addUser(User user);
/**
* 根据userId修改用户信息
* @param user
*/
void updateUser(User user);
/**
* 激活用户
* @param user
*/
void activeUser(User user);
/**
* 加载所有的模块树
* @return
*/
List<TreeData> loadAllModuleTrees();
/**
* 根据父节点查询所有的子模块
* @param parentCode
* @return
*/
List<Module> getModulesByParent(String parentCode, PageModel pageModel);
/**
* 根据父节点查询所有的子模块
* 不分页
* @param parentCode
* @return
*/
List<Module> getModulesByParent(String parentCode);
/**
* 批量删除菜单
* @param ids
*/
void deleteModules(String ids);
/**
* 为当前父节点菜单添加子节点模块
* @param parentCode
* @param module
*/
void addModule(String parentCode, Module module);
/**
* 根据编号查询模块信息
* @param code
* @return
*/
Module getModuleByCode(String code);
/**
* 修改模块
* @param module
*/
void updateModule(Module module);
/**
* 分页查询角色信息
* @param pageModel
* @return
*/
List<Role> getRoleByPage(PageModel pageModel);
/**
* 添加角色
* @param role
*/
void addRole(Role role);
/**
* 批量删除角色
* @param ids
*/
void deleteRole(String ids);
/**
* 根据id查询角色
* @param id
* @return
*/
Role getRoleById(Long id);
/**
* 修改角色
* @param role
*/
void updateRole(Role role);
/**
* 分页查询属于这个角色下的用户信息
* @param role
* @param pageModel
* @return
*/
List<User> selectRoleUser(Role role, PageModel pageModel);
/**
* 查询不属于某个角色下的用户
* @param role
* @param pageModel
* @return
*/
List<User> selectNotRoleUser(Role role, PageModel pageModel);
/**
* 给用户绑定角色
* @param role
* @param ids
*/
void bindUser(Role role, String ids);
/**
* 给用户解绑角色
* @param role
* @param ids
*/
void unBindUser(Role role, String ids);
/**
* 查询当前角色在当前模块下拥有的操作权限编号。
* @param role
* @param parentCode
* @return
*/
List<String> getRoleModuleOperasCodes(Role role, String parentCode);
/**
* 给角色绑定某个模块下的操作权限
* @param codes
* @param role
* @param parentCode
*/
void bindPopedom(String codes, Role role, String parentCode);
/**
* 查询当前用户的权限模块
* @return
*/
List<UserModule> getUserPopedomModules();
}
实现类:
package org.oa.sys.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpSession;
import org.common.service.BaseService;
import org.common.util.CommonContants;
import org.common.util.page.PageModel;
import org.oa.sys.domain.Dept;
import org.oa.sys.domain.Module;
import org.oa.sys.domain.Popedom;
import org.oa.sys.domain.Role;
import org.oa.sys.domain.User;
import org.oa.sys.dto.UserModule;
import org.oa.sys.repository.DeptRepository;
import org.oa.sys.repository.JobRepository;
import org.oa.sys.repository.ModuleRepository;
import org.oa.sys.repository.PopedomRepository;
import org.oa.sys.repository.RoleRepository;
import org.oa.sys.repository.UserRepository;
import org.oa.sys.service.SysService;
import org.oa.sys.vo.TreeData;
import org.oa.util.OaContants;
import org.oa.util.OaException;
import org.oa.util.UserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
@Service
@Transactional
public class SysServiceImpl extends BaseService implements SysService {
@Autowired
private DeptRepository deptRepository;
@Autowired
private JobRepository jobRepository;
@Autowired
private UserRepository userRepository;
@Autowired
private ModuleRepository moduleRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private PopedomRepository popedomRepository;
@Transactional(readOnly = true)
@Override
public List<Dept> getAllDepts() {
try {
List<Dept> depts = deptRepository.findAll();
// 取延迟加载的属性 ,会话此时并没有关闭
for (Dept dept : depts) {
if (dept.getCreater() != null)
dept.getCreater().getName();
if (dept.getModifier() != null)
dept.getModifier().getName();
}
return depts;
} catch (Exception e) {
throw new OaException("查询部门失败了", e);
}
}
@Override
public Map<String, Object> login(Map<String, Object> params) {
Map<String, Object> result = new HashMap<>();
try {
/** 处理登录的业务逻辑 */
/** 1.参数非空校验 */
Long id = (Long) params.get("id");
String passWord = (String) params.get("passWord");
String vcode = (String) params.get("vcode");
HttpSession session = (HttpSession) params.get("session");
// userId!=null&&!userId.equals("")
if (id == null || StringUtils.isEmpty(passWord) || StringUtils.isEmpty(vcode)) {
/** 参数有为空的 */
result.put("status", 0);
result.put("tip", "参数有为空的");
} else {
/** 参数不为空 */
/** 校验验证码是否正确
* 获取session中当前用户对应的验证码
* */
String sysCode = (String) session.getAttribute(CommonContants.VERIFY_SESSION);
if (vcode.equalsIgnoreCase(sysCode)) {
/** 验证码正确了 */
/** 根据登录的用户名去查询用户: 判断登录名是否存在 */
User user = getUserById(id);
if (user != null) {
/** 登录名存在 */
/** 判断密码 */
if (user.getPassword().equals(passWord)) {
/** 判断用户是否已经被激活了 */
if (user.getStatus() == 1) {
/** 登录成功 */
/** 1.把登录成功的用户放入当前用户的session会话中 */
session.setAttribute(OaContants.USER_SESSION, user);
System.out.println("设置用户 ---------------->:" + user);
result.put("status", 1);
result.put("tip", "登录成功");
/** 把登录成功的用户存入到UserHolder*/
UserHolder.addCurrentUser(user);
/** 2.当用户一登录进入系统的时候,就应该立即去查询该用户所拥有
的全部操作权限 --> 存入到当前用户的Session会话中 */
Map<String, List<String>> userAllOperasPopedomUrls = getUserAllOperasPopedomUrls();
session.setAttribute(OaContants.USER_ALL_OPERAS_POPEDOM_URLS, userAllOperasPopedomUrls);
} else {
result.put("status", 5);
result.put("tip", "您的账号未被激活,请联系管理员激活!");
}
} else {
/** 密码错误 */
result.put("status", 2);
result.put("tip", "密码错误了");
}
} else {
/** 登录名不存在 */
result.put("status", 3);
result.put("tip", "没有该账户");
}
} else {
/** 验证码不正确 */
result.put("status", 4);
result.put("tip", "验证码不正确");
}
}
return result;
} catch (Exception e) {
throw new OaException("异步登录业务层抛出异常了", e);
}
}
private Map<String, List<String>> getUserAllOperasPopedomUrls() {
try {
/** 查询用户所拥有的所有操作权限编号
* */
List<String> userAllPopedomOperasCodes = popedomRepository
.getUserPopedomOperasCodes(UserHolder.getCurrentUser().getId());
if (userAllPopedomOperasCodes != null && userAllPopedomOperasCodes.size() > 0) {
Map<String, List<String>> userAllOperasPopedomUrls = new HashMap<>();
String moduleUrl = "";
List<String> moduleOperaUrls = null;
for (String operaCode : userAllPopedomOperasCodes) {
/** 先得到模块的编号 */
String parentModuleCode = operaCode.substring(0, operaCode.length() - OaContants.CODE_LEN);
/** 父模块地址 */
moduleUrl = getModuleByCode(parentModuleCode).getUrl();
/** 判断map集合中是否已经存在该父模块地址 */
if (!userAllOperasPopedomUrls.containsKey(moduleUrl)) {
moduleOperaUrls = new ArrayList<String>();
userAllOperasPopedomUrls.put(moduleUrl, moduleOperaUrls);
}
moduleOperaUrls.add(getModuleByCode(operaCode).getUrl());
}
return userAllOperasPopedomUrls;
}
return null;
} catch (Exception e) {
throw new OaException("登录查询用户的操作权限出现异常", e);
}
}
public User getUserById(Long id) {
try {
User user = userRepository.findById(id).get();
if (user != null) {
// 获取延迟加载的属性
if (user.getDept() != null)
user.getDept().getName();
if (user.getJob() != null)
user.getJob().getName();
if (user.getCreater() != null)
user.getCreater().getName();
if (user.getModifier() != null)
user.getModifier().getName();
if (user.getChecker() != null)
user.getChecker().getName();
return user;
}
return null;
} catch (Exception e) {
throw new OaException("查询用户失败了", e);
}
}
@Transactional
@Override
public void updateSelf(User user, HttpSession session) {
try {
/** 1.持久化修改 */
User sessionUser = userRepository.findById(user.getId()).get();
sessionUser.setModifier(user);
sessionUser.setName(user.getName());
// get一下就可以加载延迟加载的属性
if (sessionUser.getDept() != null)
sessionUser.getDept().getName();
if (sessionUser.getJob() != null)
sessionUser.getJob().getName();
session.setAttribute(OaContants.USER_SESSION, sessionUser);
} catch (Exception e) {
throw new OaException("修改用户失败了", e);
}
}
@Override
public Map<String, Object> getAllDeptsAndJobsAjax() {
try {
/** 1.定义一个Map对象封装最终查询出来的部门信息和职位信息 */
Map<String, Object> deptJobDatas = new HashMap<>();
/** 查询部门 : id name */
List<HashMap<String, Object>> deptsList = deptRepository.findDepts();
/** 查询部门 : id name */
List<Map<String, Object>> jobLists = jobRepository.findJobs();
deptJobDatas.put("depts", deptsList);
deptJobDatas.put("jobs", jobLists);
return deptJobDatas;
} catch (Exception e) {
throw new OaException("查 询部门与职位信息异常了", e);
}
}
@SuppressWarnings("serial")
@Override
public List<User> getUsersByPage(User user, PageModel pageModel) {
try {
Page<User> usersPager = userRepository.findAll(new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// 本集合用于封装查询条件
List<Predicate> predicates = new ArrayList<Predicate>();
if (user != null) {
/** 是否传入了姓名来查询 */
if (!StringUtils.isEmpty(user.getName())) {
predicates.add(cb.like(root.<String> get("name"), "%" + user.getName() + "%"));
}
/** 是否传入手机号码了来查询 */
if (!StringUtils.isEmpty(user.getMobile())) {
predicates.add(cb.like(root.<String> get("mobile"), "%" + user.getMobile() + "%"));
}
/** 是否传入部门来查询 */
if (user.getDept() != null && user.getDept().getId() != null && user.getDept().getId() != 0) {
root.join("dept", JoinType.INNER);
Path<Long> d_id = root.get("dept").get("id");
predicates.add(cb.equal(d_id, user.getDept().getId()));
}
if (user.getJob() != null && !StringUtils.isEmpty(user.getJob().getCode())
&& !user.getJob().getCode().equals("0")) {
root.join("job", JoinType.INNER);
Path<String> j_id = root.get("job").get("code");
predicates.add(cb.equal(j_id, user.getJob().getCode()));
}
}
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
}, PageRequest.of(pageModel.getPageIndex() - 1, pageModel.getPageSize()));
pageModel.setRecordCount(usersPager.getTotalElements());
/** 取每个用户的延迟加载属性 */
List<User> users = usersPager.getContent();
for (User u : users) {
if (u.getDept() != null)
u.getDept().getName();
if (u.getJob() != null)
u.getJob().getName();
if (u.getChecker() != null)
u.getChecker().getName();
}
return users;
} catch (Exception e) {
throw new OaException("查询用户信息异常了", e);
}
}
@Transactional
@Override
public void deleteUserByUserIds(String ids) {
try {
List<User> users = new ArrayList<User>();
for (String id : ids.split(",")) {
User user = new User();
user.setId(Long.parseLong(id));
users.add(user);
}
userRepository.deleteInBatch(users);
} catch (Exception e) {
throw new OaException("删除用户信息异常了", e);
}
}
@Override
public String isUserValidAjax(Long id) {
try {
User user = userRepository.findById(id).get();
return user == null ? "success" : "error";
} catch (Exception e) {
throw new OaException("校验用户登录名是否注册异常了", e);
}
}
@Transactional
@Override
public void addUser(User user) {
try {
user.setCreater(UserHolder.getCurrentUser());
userRepository.save(user);
} catch (Exception e) {
throw new OaException("添加用户信息异常了", e);
}
}
@Transactional
@Override
public void updateUser(User user) {
try {
/** 1.持久化修改 */
User sessionUser = userRepository.findById(user.getId()).get();
sessionUser.setModifyDate(new Date());
sessionUser.setModifier(UserHolder.getCurrentUser());
sessionUser.setPassword(user.getPassword());
sessionUser.setName(user.getName());
sessionUser.setDept(user.getDept());
sessionUser.setJob(user.getJob());
sessionUser.setSex(user.getSex());
} catch (Exception e) {
throw new OaException("修改用户失败了", e);
}
}
@Transactional
@Override
public void activeUser(User user) {
try {
User sessionUser = userRepository.findById(user.getId()).get();
sessionUser.setCheckDate(new Date());
sessionUser.setChecker(UserHolder.getCurrentUser());
sessionUser.setStatus(user.getStatus());
} catch (Exception e) {
throw new OaException("激活用户失败了", e);
}
}
@Override
public List<TreeData> loadAllModuleTrees() {
try {
/** 查询所有的模块信息 */
List<Module> modules = moduleRepository.findAll();
/** 拼装成dtree需要的树节点 */
List<TreeData> treeDatas = new ArrayList<>();
for (Module m : modules) {
TreeData data = new TreeData();
data.setId(m.getCode());
data.setName(m.getName());
// 长度为4的编号的父节点是0
// 其余节点的父节点是从开始位置一直截取到总长度减去步长的位置。 00010001的父节点是0001
String pid = m.getCode().length() == OaContants.CODE_LEN ? "0"
: m.getCode().substring(0, m.getCode().length() - OaContants.CODE_LEN);
data.setPid(pid);
treeDatas.add(data);
}
return treeDatas;
} catch (Exception e) {
throw new OaException("加载模块树异常", e);
}
}
@SuppressWarnings("serial")
@Override
public List<Module> getModulesByParent(String parentCode, PageModel pageModel) {
try {
parentCode = parentCode == null ? "" : parentCode;
List<Object> values = new ArrayList<>();
values.add(parentCode + "%");
values.add(parentCode.length() + OaContants.CODE_LEN);
// // 子节点的编号的长度是父节点编号长度+步长
// // 子节点前几位的编号必须与父节点编码一致
Page<Module> modulesPager = moduleRepository.findAll(new Specification<Module>() {
@Override
public Predicate toPredicate(Root<Module> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// 本集合用于封装查询条件
List<Predicate> predicates = new ArrayList<Predicate>();
predicates.add(cb.like(root.<String> get("code"), values.get(0) + ""));
predicates.add(cb.equal(cb.length(root.<String> get("code")), values.get(1)));
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
}, PageRequest.of(pageModel.getPageIndex() - 1, pageModel.getPageSize()));
pageModel.setRecordCount(modulesPager.getTotalElements());
/** 取每个用户的延迟加载属性 */
List<Module> sonModules = modulesPager.getContent();
for (Module m : sonModules) {
if (m.getCreater() != null)
m.getCreater().getName();
if (m.getModifier() != null)
m.getModifier().getName();
}
return sonModules;
} catch (Exception e) {
throw new OaException("查询子模块异常", e);
}
}
@Override
public List<Module> getModulesByParent(String parentCode) {
try {
parentCode = parentCode == null ? "" : parentCode;
List<Module> sonModules = moduleRepository.findModules(parentCode + "%",
parentCode.length() + OaContants.CODE_LEN);
for (Module m : sonModules) {
if (m.getCreater() != null)
m.getCreater().getName();
if (m.getModifier() != null)
m.getModifier().getName();
}
return sonModules;
} catch (Exception e) {
throw new OaException("查询子模块异常", e);
}
}
@Transactional
@Override
public void deleteModules(String ids) {
try {
for (String id : ids.split(",")) {
moduleRepository.deleteById(Long.valueOf(id));
}
} catch (Exception e) {
throw new OaException("批量删除菜单异常", e);
}
}
@Transactional
@Override
public void addModule(String parentCode, Module module) {
try {
/** 维护编号:通用工具类(给你一个父节点,给你一张表,给你那个字段,
* 找出该字段该父节点下的下一个儿子节点的编号 ) */
module.setCode(getNextSonCode(parentCode, OaContants.CODE_LEN));
module.setCreater(UserHolder.getCurrentUser());
moduleRepository.save(module);
} catch (Exception e) {
throw new OaException("添加子菜单异常", e);
}
}
public String getNextSonCode(String parentCode, int codeLen) throws Exception {
/** 判断父节点是否为null */
parentCode = parentCode == null ? "" : parentCode;
/** 1.查询出当前父节点下的最大儿子节点编号 */
String maxSonCode = moduleRepository.findUniqueEntity(parentCode + "%", parentCode.length() + codeLen);
String nextSonCode = ""; // 保存最终的下一个儿子节点编号
/** 4.判断最大儿子节点编号是否存在 ,因为极有可能父节点此时一个子节点都没有 */
if (StringUtils.isEmpty(maxSonCode)) {
/** 儿子节点编号不存在 */
String preSuffix = ""; // 0 需要拼接多少个0
for (int i = 0; i < codeLen - 1; i++) {
preSuffix += "0";
}
nextSonCode = parentCode + preSuffix + 1;
} else {
/** 儿子节点编号存在 */
/** 截取出当前儿子节点编号的步长出来 */
String currentMaxSonCode = maxSonCode.substring(parentCode.length());
/** 得到儿子节点步长编号的整形形式 */
int maxSonCodeInt = Integer.valueOf(currentMaxSonCode);
maxSonCodeInt++;
/** 判断编号是否越界了 */
if ((maxSonCodeInt + "").length() > codeLen) {
throw new OaException("编号越界了!");
} else {
/** 没有越界 */
String preSuffix = ""; // 0 需要拼接多少个0
for (int i = 0; i < codeLen - (maxSonCodeInt + "").length(); i++) {
preSuffix += "0";
}
nextSonCode = parentCode + preSuffix + maxSonCodeInt;
}
}
return nextSonCode;
}
@Override
public Module getModuleByCode(String code) {
try {
return moduleRepository.findByCode(code);
} catch (Exception e) {
throw new OaException("查询模块异常", e);
}
}
@Transactional
@Override
public void updateModule(Module module) {
try {
Module sessionModule = moduleRepository.findById(module.getId()).get();
sessionModule.setModifier(UserHolder.getCurrentUser());
sessionModule.setName(module.getName());
sessionModule.setRemark(module.getRemark());
sessionModule.setUrl(module.getUrl());
} catch (Exception e) {
throw new OaException("修改模块异常", e);
}
}
@Override
public List<Role> getRoleByPage(PageModel pageModel) {
try {
// 指定排序参数对象:根据id,进行降序查询
Sort sort = new Sort(Sort.Direction.ASC, "id");
/**
* 封装分页实体
* 参数一:pageIndex表示当前查询的第几页(默认从0开始,0表示第一页)
* 参数二:表示每页展示多少数据,现在设置每页展示2条数据
* 参数三:封装排序对象,根据该对象的参数指定根据id降序查询
*/
Pageable page = PageRequest.of(pageModel.getPageIndex() - 1, pageModel.getPageSize(), sort);
Page<Role> rolePager = roleRepository.findAll(page);
pageModel.setRecordCount(rolePager.getTotalElements());
/** 取每个用户的延迟加载属性 */
List<Role> roles = rolePager.getContent();
for (Role r : roles) {
if (r.getModifier() != null)
r.getModifier().getName();
if (r.getCreater() != null)
r.getCreater().getName();
}
return roles;
} catch (Exception e) {
throw new OaException("查询角色异常", e);
}
}
@Transactional
@Override
public void addRole(Role role) {
try {
role.setCreateDate(new Date());
role.setCreater(UserHolder.getCurrentUser());
roleRepository.save(role);
} catch (Exception e) {
throw new OaException("添加角色异常", e);
}
}
@Transactional
@Override
public void deleteRole(String ids) {
try {
List<Role> roles = new ArrayList<Role>();
for (String id : ids.split(",")) {
Role role = new Role();
role.setId(Long.valueOf(id));
}
roleRepository.deleteInBatch(roles);
} catch (Exception e) {
throw new OaException("批量删除角色异常", e);
}
}
@Override
public Role getRoleById(Long id) {
try {
return roleRepository.findById(id).get();
} catch (Exception e) {
throw new OaException("根据id查询角色异常", e);
}
}
@Transactional
@Override
public void updateRole(Role role) {
try {
Role r = roleRepository.findById(role.getId()).get();
r.setName(role.getName());
r.setRemark(role.getRemark());
r.setModifier(UserHolder.getCurrentUser());
} catch (Exception e) {
throw new OaException("根据id修改角色异常", e);
}
}
@SuppressWarnings("serial")
@Override
public List<User> selectRoleUser(Role role, PageModel pageModel) {
try {
Page<User> usersPager = userRepository.findAll(new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// 本集合用于封装查询条件
List<Predicate> predicates = new ArrayList<>();
List<String> userIds = userRepository.findRoleUsers(role.getId());
predicates.add(root.<String> get("userId").in(userIds));
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
}, PageRequest.of(pageModel.getPageIndex() - 1, pageModel.getPageSize()));
pageModel.setRecordCount(usersPager.getTotalElements());
List<User> users = usersPager.getContent();
for (User u : users) {
if (u.getDept() != null)
u.getDept().getName();
if (u.getJob() != null)
u.getJob().getName();
if (u.getChecker() != null)
u.getChecker().getName();
}
return users;
} catch (Exception e) {
throw new OaException("查询属于角色下的用户信息异常", e);
}
}
@SuppressWarnings("serial")
@Override
public List<User> selectNotRoleUser(Role role, PageModel pageModel) {
try {
Page<User> usersPager = userRepository.findAll(new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// 本集合用于封装查询条件
List<Predicate> predicates = new ArrayList<Predicate>();
// 先查询出不属于这个角色下的用户
List<String> userId = userRepository.getRolesUsers(role.getId());
predicates.add(root.<String> get("userId").in(userId));
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
}, PageRequest.of(pageModel.getPageIndex() - 1, pageModel.getPageSize()));
pageModel.setRecordCount(usersPager.getTotalElements());
List<User> users = usersPager.getContent();
for (User u : users) {
if (u.getDept() != null)
u.getDept().getName();
if (u.getJob() != null)
u.getJob().getName();
if (u.getChecker() != null)
u.getChecker().getName();
}
return users;
} catch (Exception e) {
throw new OaException("查询不属于角色下的用户信息异常", e);
}
}
@Transactional
@Override
public void bindUser(Role role, String ids) {
try {
/** 给角色绑定一批用户 */
/** 1.先查询出该角色 */
Role session = roleRepository.findById(role.getId()).get();
/** 2.给角色的users添加需要绑定的用户 */
for (String id : ids.split(",")) {
User user = userRepository.findById(Long.valueOf(id)).get();
session.getUsers().add(user);
}
} catch (Exception e) {
throw new OaException("绑定角色下的用户异常", e);
}
}
@Transactional
@Override
public void unBindUser(Role role, String ids) {
try {
/** 给角色绑定一批用户 */
/** 1.先查询出该角色 */
Role session = roleRepository.findById(role.getId()).get();
/** 2.给角色的users添加需要绑定的用户 */
for (String id : ids.split(",")) {
User user = userRepository.findById(Long.valueOf(id)).get();
session.getUsers().remove(user);
}
} catch (Exception e) {
throw new OaException("绑定角色下的用户异常", e);
}
}
@Override
public List<String> getRoleModuleOperasCodes(Role role, String parentCode) {
try {
List<String> roleModuleOperasCodes = popedomRepository.findByIdAndParentCode(role.getId(), parentCode);
return roleModuleOperasCodes;
} catch (Exception e) {
throw new OaException("查询当前角色在当前模块下拥有的操作权限编号异常", e);
}
}
@Transactional
@Override
public void bindPopedom(String codes, Role role, String parentCode) {
try {
/** 1.先清空此角色在此模块下的所有操作权限 */
popedomRepository.setByIdAndParentCode(role.getId(), parentCode);
/** 2.更新新的角色模块权限 */
if (!StringUtils.isEmpty(codes)) {
Module parent = getModuleByCode(parentCode);
/** 添加一些更新的权限 */
for (String code : codes.split(",")) {
/** 创建一个权限对象 */
Popedom popedom = new Popedom();
popedom.setRole(role);
popedom.setModule(parent);
popedom.setOpera(getModuleByCode(code));
popedom.setCreateDate(new Date());
popedom.setCreater(UserHolder.getCurrentUser());
popedomRepository.save(popedom);
}
}
} catch (Exception e) {
throw new OaException("给角色绑定某个模块的操作权限异常", e);
}
}
@Override
public List<UserModule> getUserPopedomModules() {
try {
/**查询当前用户的权限模块 :先查用户所有的角色,再查这些角色拥有的所有权限模块 */
List<String> popedomModuleCodes = popedomRepository
.getUserPopedomModuleCodes(UserHolder.getCurrentUser().getId());
if (popedomModuleCodes != null && popedomModuleCodes.size() > 0) {
/** 定义一个Map集合用于保存用户的权限模块
* Map<Module,List<Module>>
* {系统管理=[用户管理,角色管理] , 假期模块=[查询信息,用户请假]}
* */
Map<Module, List<Module>> userModulesMap = new LinkedHashMap<>();
Module fistModule = null;
List<Module> secondModules = null;
for (String moduleCode : popedomModuleCodes) {
/** 截取当前模块的一级模块编号 */
String fistCode = moduleCode.substring(0, OaContants.CODE_LEN);
/** 查询出一级模块对象 */
fistModule = getModuleByCode(fistCode);
fistModule.setName(fistModule.getName().replaceAll("-", ""));
/**如果map集合中没有包含当前一级模块的key,说明是第一次添加一级模块 */
if (!userModulesMap.containsKey(fistModule)) {
secondModules = new ArrayList<Module>();
userModulesMap.put(fistModule, secondModules);
}
Module secondModule = getModuleByCode(moduleCode);
secondModule.setName(secondModule.getName().replaceAll("-", ""));
secondModules.add(secondModule);
}
List<UserModule> userModules = new ArrayList<>();
for (Entry<Module, List<Module>> entry : userModulesMap.entrySet()) {
Module key = entry.getKey();
List<Module> value = entry.getValue();
UserModule userModule = new UserModule();
userModule.setFirstModule(key);
userModule.setSecondModules(value);
userModules.add(userModule);
}
return userModules;
}
return null;
} catch (Exception e) {
throw new OaException("查询当前用户的权限模块", e);
}
}
}
4. Web层
4.1 LoginController 登录
package org.my.oa.sys.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.my.oa.sys.service.SysService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class LoginController {
/** 1.定义业务层对象 */
@Autowired
private SysService sysService;
@ResponseBody // 异步请求的响应结果
@RequestMapping(value = "/loginAjax", produces = "application/json; charset=UTF-8")
public Map<String, Object> login(@RequestParam("mobile") String mobile, @RequestParam("password") String password,
@RequestParam("vcode") String vcode, HttpSession session) {
try {
Map<String, Object> params = new HashMap<>();
params.put("mobile", mobile);
params.put("password", password);
params.put("vcode", vcode);
params.put("session", session);
// 响应数据啊,写回去数据
Map<String, Object> result = sysService.login(params);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
4.2 RequestController 登录跳转
package org.my.oa.sys.controller;
import java.util.List;
import org.my.oa.sys.dto.UserModule;
import org.my.oa.sys.service.SysService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/oa")
public class RequestController {
/** 1.定义业务层对象 */
@Autowired
private SysService sysService;
@RequestMapping(value="/login")
public String requestLogin(){
return "login";
}
@RequestMapping(value="/main")
public String requestMain(Model model){
try {
//查询出当前用户拥有的所有模块权限
List<UserModule> userModules = sysService.getUserPopedomModules();
model.addAttribute("userPopedomModules", userModules);
} catch (Exception e) {
e.printStackTrace();
}
return "main";
}
@RequestMapping(value="/home")
public String requestHome(){
return "home";
}
}
简单列举这两个控制层,业务逻辑层里面的实现已经很详细了,JSP页面不再展示。
附上目前完成的部分:
https://github.com/gavinL93/oa
本工程参考《Spring Boot2 企业应用实战》一书