有些功能模块都已经做过了,可是老师实现要比我们一起的实现好经典.要更加面向对象.更加通过.充分的感觉到了功力的不同啊.哈哈...这就是差距啊.也 有一些模块看上去很简单,但在代码实现的过程中就会碰到这样或那样的问题.一时很难解决,让我们的练习速度非常慢.所有,我们要学会看异常信息和积累并总 结异常的处理,并能快速的判断异常发生的位置.
今天我们主要实现 Role 的增, 删, 改, 查.并用面向对象的思想对实现过程进行优化.让经常使用的代码抽取出来.
1.添加新角色:
①. 修改 ems_authority_table 表, 录入权限模块对应的记录. 详见 roles.doc
②. 页面 UI:
a. 对字段的 jQuery validation 验证
b. struts validator 验证 **
c. Action的复杂验证: 角色名不能重复 **.
d. 角色名的 ajax 验证.
③. 若验证都通过, 在 Action 中受理请求, 录入角色
2.查询所有角色
3.查看角色的详细信息
不能直接使用 19 -- 23 代码, 这样会把所有的子权限都显示出来, 而不只是当前用户所具备的权限, 因为采取了 OpenSessionInView 模式,所以此时${auth.authoritySet} 会获取到当前父权限的所有子权限:
<c:forEach items="${CN_ITCAST_EMS_ROLE_REQUEST.authoritySet}" var="auth">
<c:if test="${empty auth.parentAuthority}">
<p>
<label for="message"><b>${auth.displayName }</b></label>
</p>
*<c:forEach items="${auth.authoritySet}" var="subAuth">
*<p>
*<label for=""> </label>${subAuth.displayName }
*</p>
*</c:forEach>
</c:if>
</c:forEach>
则几行代码可以替换为:
<c:forEach items="${CN_ITCAST_EMS_ROLE_REQUEST.authoritySet}" var="subAuth">
<c:if test="${subAuth.parentAuthority == auth}">
<p>
<label for=""> </label>${subAuth.displayName }
</p>
</c:if>
</c:forEach>
总结:
SpringSecuity 拦截的URL 模式后总是要带上一个匹配符(*), 否则这个 URL 模式无法匹配带有参数的 URL,但此时需要修改 EMSNavigationMenuAction 中的实现
为了使 web 应用出错时, 有更好的相应页面, 需要在 web.xml 中加入错误处理页面的配置.
4.修改角色的详细信息
和录入使用同一个页面
①. 使用 struts 的 html 标签进行表单回显
②. 在 role-input.jsp 页面需要加入 <html:hidden property="id"/> 隐藏域, 以能保证被修改的 Role 的 id 的传递.
③. 但此时角色录入会发生异常 org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1,
其原因是: <html:hidden property="id"/> 被翻译为: <input type="hidden" name="id" value="">. 即此时传递的是一个含有 id 的 Role 对象, 当对该对象使用 saveOrUpdate() 方法时,
会执行 update 语句, 但在数据库中并没有对应的记录, 所以会发生上述异常. 解决方案为: 在 roleInput 中过滤一下.
if(StringUtils.isEmpty(role.getId())){
role.setId(null);
}
5.删除角色
需要级联删除和员工, 权限的级联关系:
①. 因为在 Role 中没有和 Employee 对应的集合, 所以当删除 Role 时, 需要手工删除其和 Employee 关联的 role_employee 关联表中的信息
②. 使用
String hql = "SELECT e FROM Employee e JOIN e.roleSet r WHERE r.id = ?";
emps = find(hql, role.getId());
查询得到和当前 Role 对象对应的 Employee 的集合信息.
在使用
for(Employee employee: emps){
employee.getRoleSet().remove(role);
}
解除和当前 Role 关联的 Employee 的中间表的信息