角色与权限:多对多
一个角色可以有多个权限,一个权限可以被多个角色使用。
那我们下面就来使用我们完成的角色。
我们先来看一下需求,记不记得之前的用户编辑界面:
可以看到,我们注册用户的时候是要给用户安排一个角色的,而我们的角色在角色管理系统里面已经创建好了,可以从创建好的角色中挑选需要的角色(该角色拥有自己特有的权限)。
所以,我们说一下用户与角色的关系设计:
用户:用户1,用户2
角色:管理员,一般用户
用户与角色的关系:多对多
一个用户可以有多个角色;一个角色可以被多个用户使用
用户:user
用户id,名称...
1 用户1
2 用户2
用户角色:user_role
用户id,角色id
1 1
1 2
2 2
角色:role
角色Id,名称
1 管理员
2 一般用户
总体就是:
查询出用户后;需要知道这个用户有哪些角色
我们下面来实现它。实现它就是改造之前的用户管理模块.我们刚刚设计过,“用户”表和“角色”表我们之前都有的,这里不能动,我们需要做的就是设计编写出“用户与角色”这张中间表:
UserRole.java:
联合主键类(需要实现Serializable接口和改写equals和hashCode方法)
UserRoleId.java:
然后写我们的映射文件:
UserRole.hbm.xml
按理来说接下来应该是Dao、Service、Action等,但是这些我们做用户管理的时候已经做好了,我们现在来改造它们。
先改造Action层:
上面我们在进入添加页面之前我们先从数据库将所有角色类型全部取出放入ActionContext域中(需要注入roleService来获得所有角色信息)。
我们之前用户“添加”页面的角色这一块是空的:
我们现在将我们放置在ActionContext域中的角色信息取出,使用struts的<s:checkboxlist>标签来将数据以复选框的形式展示在页面:
效果:
可以看到用户角色一栏已经出现了我们之前添加的角色了。
然后接下来保存用户的时候我们也要将给用户分配的角色保存下来,我们继续完成Action的改造:
我们把userRoleIds引进来,用于获取用户的角色选择,然后我们把原来的save(User user)和update(User user)方法全部改为
保存用户和角色信息saveUserAndRole(User user, String[] userRoleIds)和
修改用户和角色信息updateUserAndRole(User user, String[] userRoleIds);
我们在UserService接口中定义这些方法,然后在UserServiceImpl中实现这两个方法:
其中saveUserRole和deleteUserRoleByUserId没有实现,我们在userDao接口中添加它们,在userDaoImpl中实现它们:
我们做到了新增和编辑的时候保存给注册用户时选择的相应角色。
我们来实验一下:
先来添加一个用户,给他分配一个角色:
保存之后到数据库中查看,发现我们为用户设置了相应的角色:
用户权限id中间表:
妮妮的id
权限id:
然后是编辑界面:
我们的编辑界面还没有设置数据回显,我们先编辑jsp界面,将我们的数据设置在编辑页面上:
然后修改UserAction中editUI()方法,使其也加载用户的角色:
上面新添加了getRoleIdByUserId方法,我们在UserService中添加getRoleIdByUserId方法,然后在其实现类UserServiceImpl中实现这个方法:
上面Dao新添加了getRoleIdByUserId方法,我们在UserDao中添加getRoleIdByUserId方法,然后在其实现类UserDaoImpl中实现这个方法:
测试:
点击编辑界面,将管理员的权限也勾选上:
保存之后可以看到妮妮这个用户又多了一个角色:
一个角色可以有多个权限,一个权限可以被多个角色使用。
那我们下面就来使用我们完成的角色。
我们先来看一下需求,记不记得之前的用户编辑界面:
可以看到,我们注册用户的时候是要给用户安排一个角色的,而我们的角色在角色管理系统里面已经创建好了,可以从创建好的角色中挑选需要的角色(该角色拥有自己特有的权限)。
所以,我们说一下用户与角色的关系设计:
用户:用户1,用户2
角色:管理员,一般用户
用户与角色的关系:多对多
一个用户可以有多个角色;一个角色可以被多个用户使用
用户:user
用户id,名称...
1 用户1
2 用户2
用户角色:user_role
用户id,角色id
1 1
1 2
2 2
角色:role
角色Id,名称
1 管理员
2 一般用户
总体就是:
查询出用户后;需要知道这个用户有哪些角色
我们下面来实现它。实现它就是改造之前的用户管理模块.我们刚刚设计过,“用户”表和“角色”表我们之前都有的,这里不能动,我们需要做的就是设计编写出“用户与角色”这张中间表:
UserRole.java:
- package cn.edu.hpu.tax.user.entity;
- import java.io.Serializable;
- public class UserRole implements Serializable {
- //联合主键
- private UserRoleId id;
- public UserRole() {
- }
- public UserRole(UserRoleId id) {
- this.id = id;
- }
- public UserRoleId getId() {
- return id;
- }
- public void setId(UserRoleId id) {
- this.id = id;
- }
- }
联合主键类(需要实现Serializable接口和改写equals和hashCode方法)
UserRoleId.java:
- package cn.edu.hpu.tax.user.entity;
- import java.io.Serializable;
- import cn.edu.hpu.tax.role.entity.Role;
- public class UserRoleId implements Serializable {
- private String userId;
- private Role role;
- public UserRoleId(){
- }
- public UserRoleId(String userId, Role role) {
- super();
- this.userId = userId;
- this.role = role;
- }
- public String getUserId() {
- return userId;
- }
- public void setUserId(String userId) {
- this.userId = userId;
- }
- public Role getRole() {
- return role;
- }
- public void setRole(Role role) {
- this.role = role;
- }
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((role == null) ? 0 : role.hashCode());
- result = prime * result + ((userId == null) ? 0 : userId.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- UserRoleId other = (UserRoleId) obj;
- if (role == null) {
- if (other.role != null)
- return false;
- } else if (!role.equals(other.role))
- return false;
- if (userId == null) {
- if (other.userId != null)
- return false;
- } else if (!userId.equals(other.userId))
- return false;
- return true;
- }
- }
然后写我们的映射文件:
UserRole.hbm.xml
- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="cn.edu.hpu.tax.user.entity.UserRole" table="user_role">
- <composite-id name="id" class="cn.edu.hpu.tax.user.entity.UserRoleId">
- <key-many-to-one name="role" lazy="false" class="cn.edu.hpu.tax.role.entity.Role">
- <column name="role_id"></column>
- </key-many-to-one>
- <key-property name="userId" type="java.lang.String">
- <column name="user_id" length="32"></column>
- </key-property>
- </composite-id>
- </class>
- </hibernate-mapping>
按理来说接下来应该是Dao、Service、Action等,但是这些我们做用户管理的时候已经做好了,我们现在来改造它们。
先改造Action层:
- package cn.edu.hpu.tax.user.action;
- import java.io.File;
- import java.io.IOException;
- import java.util.List;
- import java.util.UUID;
- import javax.annotation.Resource;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServletResponse;
- import org.apache.commons.io.FileUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionContext;
- import cn.edu.hpu.tax.core.action.BaseAction;
- import cn.edu.hpu.tax.role.service.RoleService;
- import cn.edu.hpu.tax.user.entity.User;
- import cn.edu.hpu.tax.user.service.UserService;
- public class UserAction extends BaseAction{
- @Resource
- private UserService userService;
- //注入RoleService
- @Resource
- private RoleService roleService;
- //其它参数省略
- //跳转到新增页面
- public String addUI(){
- //加载角色列表
- ActionContext.getContext().getContextMap().put("roleList", roleService.findObjects());
- return "addUI";
- }
- //其它方法省略
- }
上面我们在进入添加页面之前我们先从数据库将所有角色类型全部取出放入ActionContext域中(需要注入roleService来获得所有角色信息)。
我们之前用户“添加”页面的角色这一块是空的:
我们现在将我们放置在ActionContext域中的角色信息取出,使用struts的<s:checkboxlist>标签来将数据以复选框的形式展示在页面:
- <tr>
- <td class="tdBg" width="200px">角色:</td>
- <td>
- <s:checkboxlist list="#roleList" name="userRoleIds" listKey="roleId" listValue="name">
- </s:checkboxlist>
- </td>
- </tr>
效果:
可以看到用户角色一栏已经出现了我们之前添加的角色了。
然后接下来保存用户的时候我们也要将给用户分配的角色保存下来,我们继续完成Action的改造:
- package cn.edu.hpu.tax.user.action;
- import java.io.File;
- import java.io.IOException;
- import java.util.List;
- import java.util.UUID;
- import javax.annotation.Resource;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServletResponse;
- import org.apache.commons.io.FileUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionContext;
- import cn.edu.hpu.tax.core.action.BaseAction;
- import cn.edu.hpu.tax.role.service.RoleService;
- import cn.edu.hpu.tax.user.entity.User;
- import cn.edu.hpu.tax.user.service.UserService;
- public class UserAction extends BaseAction{
- //前面的所有参数省略
- //用户角色选择的id们
- private String[] userRoleIds;
- //get和set省略
- //保存新增
- public String add(){
- try {
- if(user!=null){
- //处理头像
- if(headImg!=null){
- //1、保存头像到upload/user
- //获取保存路径的绝对地址
- String filePath=ServletActionContext.getServletContext().getRealPath("upload/user");
- //生成带格式的随机文件名称
- String fileName=UUID.randomUUID().toString()+headImgFileName.substring(headImgFileName.lastIndexOf("."));
- //复制文件
- FileUtils.copyFile(headImg, new File(filePath,fileName));
- //2、设置用户头像路径
- user.setHeadImg("user/"+fileName);
- }
- //saveUserAndRole方法用来同时保存用户和用户的角色
- userService.saveUserAndRole(user,userRoleIds);
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return "list";
- }
- //保存编辑
- public String edit(){
- try {
- if(user!=null){
- //处理头像
- if(headImg!=null){
- //1、保存头像到upload/user
- //获取保存路径的绝对地址
- String filePath=ServletActionContext.getServletContext().getRealPath("upload/user");
- //生成带格式的随机文件名称
- String fileName=UUID.randomUUID().toString()+headImgFileName.substring(headImgFileName.lastIndexOf("."));
- //复制文件
- FileUtils.copyFile(headImg, new File(filePath,fileName));
- //如果旧头像存在,把旧头像删除
- if(user.getHeadImg()!=null){
- String oldfilename=filePath+"\\"+user.getHeadImg().substring(5);
- File file=new File(oldfilename);
- file.delete();
- }
- /**/
- //2、设置用户头像路径
- user.setHeadImg("user/"+fileName);
- }
- userService.updateUserAndRole(user,userRoleIds);
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return "list";
- }
- //其他方法没有改动,省略
- }
我们把userRoleIds引进来,用于获取用户的角色选择,然后我们把原来的save(User user)和update(User user)方法全部改为
保存用户和角色信息saveUserAndRole(User user, String[] userRoleIds)和
修改用户和角色信息updateUserAndRole(User user, String[] userRoleIds);
我们在UserService接口中定义这些方法,然后在UserServiceImpl中实现这两个方法:
- @Override
- public void saveUserAndRole(User user, String[] userRoleIds) {
- //1.保存用户
- save(user);
- //2.保存用户对于的角色
- if(userRoleIds!=null){
- for (String roleId:userRoleIds) {
- userDao.saveUserRole(new UserRole(new UserRoleId(user.getId(),new Role(roleId))));
- }
- }
- }
- @Override
- public void updateUserAndRole(User user, String[] userRoleIds) {
- //1.根据用户删除该用户的所有角色
- userDao.deleteUserRoleByUserId(user.getId());
- //2.更新用户
- update(user);
- //3.保存用户对应的角色
- if(userRoleIds!=null){
- for (String roleId:userRoleIds) {
- userDao.saveUserRole(new UserRole(new UserRoleId(user.getId(),new Role(roleId))));
- }
- }
- }
其中saveUserRole和deleteUserRoleByUserId没有实现,我们在userDao接口中添加它们,在userDaoImpl中实现它们:
- @Override
- public void saveUserRole(UserRole userRole) {
- getHibernateTemplate().save(userRole);
- }
- @Override
- public void deleteUserRoleByUserId(String id) {
- Query query=getSession().createQuery("DELETE FROM UserRole WHERE id.userId=?");
- query.setParameter(0, id);
- query.executeUpdate();
- }
我们做到了新增和编辑的时候保存给注册用户时选择的相应角色。
我们来实验一下:
先来添加一个用户,给他分配一个角色:
保存之后到数据库中查看,发现我们为用户设置了相应的角色:
用户权限id中间表:
妮妮的id
权限id:
然后是编辑界面:
我们的编辑界面还没有设置数据回显,我们先编辑jsp界面,将我们的数据设置在编辑页面上:
- <tr>
- <td class="tdBg" width="200px">角色:</td>
- <td>
- <s:checkboxlist list="#roleList" name="userRoleIds" listKey="roleId" listValue="name">
- </s:checkboxlist>
- </td>
- </tr>
然后修改UserAction中editUI()方法,使其也加载用户的角色:
- //跳转到编辑界面
- public String editUI(){
- //加载角色列表
- ActionContext.getContext().getContextMap().put("roleList", roleService.findObjects());
- if(user!=null && user.getId()!=null){
- user=userService.findObjectById(user.getId());
- //处理角色回显
- String[] ids=userService.getRoleIdByUserId(user.getId());
- if(ids!=null&&ids.length>0){
- userRoleIds=ids;
- }
- }
- return "editUI";
- }
上面新添加了getRoleIdByUserId方法,我们在UserService中添加getRoleIdByUserId方法,然后在其实现类UserServiceImpl中实现这个方法:
- @Override
- public String[] getRoleIdByUserId(String id) {
- return userDao.getRoleIdByUserId(id);
- }
上面Dao新添加了getRoleIdByUserId方法,我们在UserDao中添加getRoleIdByUserId方法,然后在其实现类UserDaoImpl中实现这个方法:
- @Override
- public String[] getRoleIdByUserId(String id) {
- Query query=getSession().createQuery("FROM UserRole WHERE id.userId=?");
- query.setParameter(0, id);
- List<UserRole> list=query.list();
- String[] ids=null;
- if(list!=null&&list.size()>0){
- ids=new String[list.size()];
- for (int i = 0; i < list.size(); i++) {
- ids[i]=list.get(i).getId().getRole().getRoleId();
- }
- }
- return ids;
- }
测试:
点击编辑界面,将管理员的权限也勾选上:
保存之后可以看到妮妮这个用户又多了一个角色:
至此,我们的用户与我们的角色模式正式链接在一块了,下一步我们就要根据用户的角色来调整用户在网站系统中的操作权限了。