第四章:角色和菜单管理功能【基于Servlet+JSP的图书管理系统】

角色和菜单功能

在这里插入图片描述

一、角色功能

34-图书管理系统-角色管理-DAO处理

  接下来我们可以完成角色管理的增删改查操作

1. Bean对象

  创建sys_role对应的实体对象SysRole

@Data
public class SysRole {

    private Integer id;

    private String name;

    private String notes;

    private Date createTime;
}

2. Dao层

  现在我们就可以在Dao层创建涉及相关的数据库操作的方法。

public interface IRoleDao {
    /**
     * 查询所有的用户信息
     * @return
     */
    public List<SysRole> list(SysRole entity);

    /**
     * 分页查询的方法
     * @param pageUtils 分页数据
     * @return
     */
    public List<SysRole> listPage(PageUtils pageUtils);

    public int save(SysRole entity);

    public SysRole findById(int id);

    public int updateById(SysRole entity);

    int deleteById(int id);

    int count(PageUtils pageUtils);
}

然后是具体的实现

public class RoleDaoImpl implements IRoleDao {
    @Override
    public List<SysRole> list(SysRole entity) {
        QueryRunner queryRunner = MyDbUtils.getQueryRunner();
        String sql = "select * from sys_role ";
        try {
            List<SysRole> list = queryRunner.query(sql, new ResultSetHandler<List<SysRole>>() {
                @Override
                public List<SysRole> handle(ResultSet resultSet) throws SQLException {
                    // 存储返回结果的容器
                    List<SysRole> list = new ArrayList<>();
                    while(resultSet.next()){
                        // 每次循环一次 user 存储一条数据
                        SysRole entity = new SysRole();
                        entity.setId(resultSet.getInt("id"));
                        entity.setName(resultSet.getString("name"));
                        entity.setNotes(resultSet.getString("notes"));
                        entity.setCreateTime(resultSet.getDate("create_time"));
                        list.add(entity); // 把查询的记录封装到了集合容器中
                    }
                    return list; // 返回查询的结果
                }
            });
            return list;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    @Override
    public List<SysRole> listPage(PageUtils pageUtils) {
        QueryRunner queryRunner = MyDbUtils.getQueryRunner();
        String sql = "select * from sys_role limit ?,?";
        if(StringUtils.isNotEmpty(pageUtils.getKey())){
            // 需要带条件查询
            sql = "select * from sys_role where name like '%"+pageUtils.getKey()+"%' or notes like '%"+pageUtils.getKey()+"%'  limit ?,?";
        }

        // 计算 分页开始的位置
        int startNo = pageUtils.getStart();
        try {
            // BeanListHandler 会自动的帮助我们完成字段和属性的映射。前提是属性和字段完全一直
            // 此处不会通过驼峰命名法 装换
            // List<SysUser> list = queryRunner.query(sql, new BeanListHandler<SysUser>(SysUser.class));
            List<SysRole> list = queryRunner.query(sql, new ResultSetHandler<List<SysRole>>() {
                @Override
                public List<SysRole> handle(ResultSet resultSet) throws SQLException {
                    // 存储返回结果的容器
                    List<SysRole> list = new ArrayList<>();
                    while(resultSet.next()){
                        // 每次循环一次 user 存储一条数据
                        SysRole entity = new SysRole();
                        entity.setId(resultSet.getInt("id"));
                        entity.setName(resultSet.getString("name"));
                        entity.setNotes(resultSet.getString("notes"));
                        entity.setCreateTime(resultSet.getDate("create_time"));
                        list.add(entity); // 把查询的记录封装到了集合容器中
                    }
                    return list; // 返回查询的结果
                }
            },startNo,pageUtils.getPageSize());
            return list;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    @Override
    public int save(SysRole entity) {
        QueryRunner queryRunner = MyDbUtils.getQueryRunner();
        String sql = "insert into sys_role(name,notes) values(?,?)";
        try {
            return queryRunner.update(sql,entity.getName(),entity.getNotes());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }

    @Override
    public SysRole findById(int id) {
        QueryRunner queryRunner = MyDbUtils.getQueryRunner();
        String sql = "select * from sys_role where id = ? ";
        try {
            return queryRunner.query(sql, new ResultSetHandler<SysRole>() {
                @Override
                public SysRole handle(ResultSet resultSet) throws SQLException {
                    // 存储返回结果的容器
                    if(resultSet.next()){
                        // 每次循环一次 user 存储一条数据
                        SysRole entity = new SysRole();
                        entity.setId(resultSet.getInt("id"));
                        entity.setName(resultSet.getString("name"));
                        entity.setNotes(resultSet.getString("notes"));
                        entity.setCreateTime(resultSet.getDate("create_time"));
                        return entity;
                    }
                    return null; // 返回查询的结果
                }
            },id);

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    @Override
    public int updateById(SysRole entity) {
        QueryRunner queryRunner = MyDbUtils.getQueryRunner();
        String sql = "update sys_role set name = ? ,notes=? where id = ?";
        try {
            return queryRunner.update(sql,entity.getName(),entity.getNotes(),entity.getId());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }

    @Override
    public int deleteById(int id) {
        QueryRunner queryRunner = MyDbUtils.getQueryRunner();
        String sql = "delete from sys_role  where id = ?";
        try {
            return queryRunner.update(sql,id);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }

    @Override
    public int count(PageUtils pageUtils) {
        QueryRunner queryRunner = MyDbUtils.getQueryRunner();
        String sql = "select count(1) from sys_role ";
        if(StringUtils.isNotEmpty(pageUtils.getKey())){
            sql = "select count(1) from sys_role where username like '%"+pageUtils.getKey()+"%' or nickname like '%"+pageUtils.getKey()+"%' ";
        }
        try {
            return queryRunner.query(sql, new ResultSetHandler<Integer>() {
                @Override
                public Integer handle(ResultSet resultSet) throws SQLException {
                    resultSet.next();
                    return resultSet.getInt(1);
                }
            });
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }
}

3. Service层

  添加角色管理的Service相关的代码

public interface IRoleService {

    public List<SysRole> list(SysRole entity);

    public int save(SysRole entity);

    public SysRole findById(int id);

    public int updateById(SysRole entity);

    int deleteById(int id);

    void listPage(PageUtils pageUtils);

    int count(PageUtils pageUtils);
}

  具体接口对应的实现类

public class RoleServiceImpl implements IRoleService {

    private IRoleDao dao = new RoleDaoImpl();

    @Override
    public List<SysRole> list(SysRole entity) {
        return dao.list(entity);
    }

    @Override
    public int save(SysRole entity) {
        return dao.save(entity);
    }

    @Override
    public SysRole findById(int id) {
        return dao.findById(id);
    }

    @Override
    public int updateById(SysRole entity) {
        return dao.updateById(entity);
    }

    @Override
    public int deleteById(int id) {
        return dao.deleteById(id);
    }

    @Override
    public void listPage(PageUtils pageUtils) {
        // 查询分页的数据
        List<SysRole> list = dao.listPage(pageUtils);
        // 查询 满足查询条件的记录数
        int count = dao.count(pageUtils);
        // 封装分页的数据
        pageUtils.setList(list);
        pageUtils.setTotalCount(count);
    }

    @Override
    public int count(PageUtils pageUtils) {
        return dao.count(pageUtils);
    }
}

4. Servlet层

  RoleServlet需要继承前面定义的BaseServlet,然后重写定义的抽象方法。同时要重写list方法。具体如下:

@WebServlet(name = "roleServlet",urlPatterns = {"/sys/roleServlet"})
public class RoleServlet extends BaseServlet{

    private IRoleService service = new RoleServiceImpl();

    @Override
    public void list(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        super.list(req, resp); // 封装了分页的相关的操作
        // TODO 写我们自己的查询处理
        service.listPage(pageUtils);
        req.setAttribute(Constant.LIST_PAGE_UTILS,pageUtils);
        // 页面跳转
        req.getRequestDispatcher("/sys/role/list.jsp").forward(req,resp);
    }

    @Override
    public void saveOrUpdatePage(HttpServletRequest req, HttpServletResponse resp) throws Exception {

    }

    @Override
    public void saveOrUpdate(HttpServletRequest req, HttpServletResponse resp) throws Exception {

    }

    @Override
    public void remove(HttpServletRequest req, HttpServletResponse resp) throws Exception {

    }

    @Override
    public void findById(HttpServletRequest req, HttpServletResponse resp) throws Exception {

    }


}

5. 角色查询

  展示角色数据,那么我们需要做的操作:

  • 修改main.jsp中的跳转地址
  • 修改/sys/role/list.jsp中的访问地址和table数据

在这里插入图片描述

在这里插入图片描述

6. 添加和更新

  添加和删除功能是类似的。我们一块来实现,在Servlet中完善进入添加更新页面的方法和保存和更新的方法的逻辑

@Override
public void saveOrUpdatePage(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    // 如果是更新。需要查询出当前的信息
    String id = req.getParameter("id");
    if(StringUtils.isNotEmpty(id)){
        // 说明是更新
        SysRole entity = service.findById(Integer.parseInt(id));
        req.setAttribute("entity",entity);
    }
    req.getRequestDispatcher("/sys/role/addOrUpdate.jsp").forward(req,resp);
}

@Override
public void saveOrUpdate(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    // 获取提交的数据
    String id = req.getParameter("id");
    String name = req.getParameter("name");
    String notes = req.getParameter("notes");
    SysRole entity = new SysRole();
    entity.setNotes(notes);
    entity.setName(name);
    if(StringUtils.isNotEmpty(id)){
        // 更新
        entity.setId(Integer.parseInt(id));
        service.updateById(entity);
    }else {
        // 保存数据
        service.save(entity);
    }
    // 做重定向查询
    resp.sendRedirect("/sys/roleServlet?action=list");

}

然后就是对应的页面处理

<form class="form-horizontal m-t" id="signupForm" action="/sys/roleServlet?action=saveOrUpdate" method="post">
    <input type="hidden" name="id" value="${entity.id}">
    <div class="form-group">
        <label class="col-sm-3 control-label">名称:</label>
        <div class="col-sm-8">
            <input id="name" name="name" class="form-control" value="${entity.name}"
                   type="text" aria-required="true" aria-invalid="true" class="error">
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-3 control-label">描述:</label>
        <div class="col-sm-8">
            <input id="notes" name="notes" class="form-control" value="${entity.notes}"
                   type="textarea" aria-required="true" aria-invalid="false" class="valid">
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-8 col-sm-offset-3">
            <button class="btn btn-default" οnclick="resetPage()" type="button">取消</button>
            <button class="btn btn-primary" type="submit">提交</button>
        </div>
    </div>
</form>

这样就OK了
在这里插入图片描述

7.删除角色

  删除角色我们需要做一个判断。也就是已经分配给用户的角色是不能被删除的。所以删除操作的时候我们需要添加这样一个判断

@Override
public void remove(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    // 删除角色信息
    String id = req.getParameter("id");
    // 删除角色信息 我们需要做校验  如果该角色已经分配给了用户。那么这个角色就不能被删除
    boolean flag = service.checkRoleDispatch(Integer.parseInt(id));
    PrintWriter writer = resp.getWriter();
    if(flag){
        // 表示没有被分配,可以删除
        service.deleteById(Integer.parseInt(id));
        writer.write("ok");
    }else{
        // 表示不能被删除
        writer.write("error");
    }
    writer.flush();
    writer.close();
}

service中的处理

@Override
public boolean checkRoleDispatch(int roleId) {
    SysUser entity = new SysUser();
    entity.setRoleId(roleId);
    return userService.list(entity).size() == 0 ?true:false;
}

这个是在UserService的基础上做的扩展,实现了方法的复用。
在这里插入图片描述

在前端页面的处理上。加了条件判断。

function removeData(id) {
    swal({
        title: "您确定要删除这条信息吗",
        text: "删除后将无法恢复,请谨慎操作!",
        type: "warning",
        showCancelButton: true,
        confirmButtonColor: "#DD6B55",
        confirmButtonText: "删除",
        closeOnConfirm: false
    }, function () {

        $.get("/sys/roleServlet?action=remove&id=" + id, function (msg) {
            if(msg === 'ok'){
                // 表示删除成功
                // 再发起一个查询的操作
                window.location.href = "/sys/roleServlet?action=list"
            }else{
                // 表示不能被删除
                swal("删除失败!", "该角色已经被分配, 不能删除!!!。", "warning");
            }

        })
    });
}

在这里插入图片描述

二、菜单功能

1.查询功能

  系统左侧菜单栏我们需要做成动态的。那么就需要维护相关的菜单数据。所以设计了sys_menu这张表。具体的实现。如下,先定义SysMenu这个实体

@Data
public class SysMenu {

    private Integer id;
    private String name;
    private String url;
    private Integer parentId;
    private int seq;
    private Date createTime;
}

然后维护DAO,ServiceServlet的逻辑。

@WebServlet(name = "menuServlet",urlPatterns = {"/sys/menuServlet"})
public class MenuServlet extends BaseServlet{

    private IMenuService service = new MenuServiceImpl();

    /**
     * 菜单功能不做分页
     * @param req
     * @param resp
     * @throws Exception
     */
    @Override
    public void list(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        List<SysMenu> list = service.list(null);
        req.setAttribute("list",list);
        req.getRequestDispatcher("/sys/menu/list.jsp").forward(req,resp);
    }

    @Override
    public void saveOrUpdatePage(HttpServletRequest req, HttpServletResponse resp) throws Exception {

    }

    @Override
    public void saveOrUpdate(HttpServletRequest req, HttpServletResponse resp) throws Exception {

    }

    @Override
    public void remove(HttpServletRequest req, HttpServletResponse resp) throws Exception {

    }

    @Override
    public void findById(HttpServletRequest req, HttpServletResponse resp) throws Exception {

    }
}

然后页面的展示处理。注意main.jsp的菜单地址和/sys/menu/list.jsp页面的调整,我们在此处没有做分页的处理操作。

在这里插入图片描述

2.添加和更新

  添加和更新处理很类似。我们一并的实现。添加和更新我们已经在用户管理角色管理中已经实现了。所以在此处的难度就降低了很多。步骤一样

  1. 进入登录页面:需要准备相关的数据(根据Id查询信息和查询所有的父菜单信息)
  2. 提交表单数据:后端服务获取数据后做添加和更新的操作

在此处需要注意的是:父菜单分配功能,需要使用到下拉菜单
在这里插入图片描述

对应的代码

<div class="form-group">
    <label class="col-sm-3 control-label">父菜单:</label>
    <div class="col-sm-8">
        <select class="form-control m-b" name="parentId">
            <option value="-1">---本身就是父菜单---</option>
            <c:forEach items="${parents}" var="parent">
                <option value="${parent.id}" ${parent.id == entity.parentId?'selected':''}>${parent.name}</option>
            </c:forEach>
        </select>
    </div>
</div>

表单的提交功能。后端处理数据

@Override
public void saveOrUpdate(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    // 获取表单提交的数据
    String id = req.getParameter("id");
    String name = req.getParameter("name");
    String url = req.getParameter("url");
    String seq = req.getParameter("seq");
    String parentId = req.getParameter("parentId");
    SysMenu menu = new SysMenu();
    menu.setName(name);
    menu.setUrl(url);
    if(StringUtils.isNotEmpty(seq)){
        menu.setSeq(Integer.parseInt(seq));
    }
    if(StringUtils.isNotEmpty(parentId)){
        menu.setParentId(Integer.parseInt(parentId));
    }
    if(StringUtils.isNotEmpty(id)){
        // 更新
        menu.setId(Integer.parseInt(id));
        service.updateById(menu);
    }else{
        // 添加
        service.save(menu);
    }
    resp.sendRedirect("/sys/menuServlet?action=list");
}

功能搞定

3.菜单数据展示

  菜单数据有父子菜单的关系。所以在展示数据的时候需要体现这种关系。我们可以通过双重循环的方式来实现。效果如下:
在这里插入图片描述

同时我们可以通过序号来控制菜单的显示的顺序。关键是在查询的时候通过seq升序查询

在这里插入图片描述

4.删除菜单

  删除菜单本身很简单。但是我们要考虑父子菜单的关系和菜单被分配给角色的情况。那么有些情况是不能被删除的。所以我们在Servlet中需要做相关的判断校验

@Override
public void remove(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    int id = Integer.parseInt(req.getParameter("id"));
    // 删除菜单的判断
    // 1.菜单如果分配给了角色就不能被删除
    boolean flag = service.isDispatcher(id);
    String msg = "ok";
    if(flag){
        // 表示已经被分配了
        msg = "error";
    }else{
        SysMenu entity = service.findById(id);
        // 2.需要删除的菜单是父菜单
        if(entity.getParentId() == -1){
            // 有子菜单的父菜单不能被删除 -- 判断是否有子菜单
            flag = service.haveSubMenu(id);
            if(flag){
                // 有子菜单
                msg = "error";
            }else{
                // 父菜单没有子菜单 可以删除
                service.deleteById(id);
            }
        }else{
            // 3.子菜单 可以被删除
            service.deleteById(id);
        }
    }
    PrintWriter writer = resp.getWriter();
    writer.write(msg);
    writer.flush();
}

三、动态绑定

  实现用户和角色的绑定以及角色和菜单的绑定。实现整个系统动态功能分配管理的效果。

1.角色和菜单

  角色和菜单是多对多的关联关系。所以我们通过sys_role_menu来维护他们之间的关联关系。我们在更新角色信息的时候来维护菜单信息。

在这里插入图片描述

需要注意的地方,在jsp页面中展示数据注意样式

在这里插入图片描述

在展示数据的时候我们在进入更新页面前需要对菜单数据做处理

  1. 查询所以的菜单信息
  2. 对当前角色具有的菜单需要标识

在这里插入图片描述

保存更新数据的逻辑。针对菜单我们的步骤是:

  1. 先删除该角色的所有菜单
  2. 新增分配的菜单信息

在这里插入图片描述

2.用户和角色

  用户和角色是一对一的关联关系,那么这块我们就可以在添加和更新用户的时候直接分配角色信息,这块我们操作的内容:

  1. 进入更新/添加界面前需要查询所有的角色信息
  2. 在更新/添加界面中我们需要添加一个下拉菜单来处理分配功能
  3. 表单数据提交到后台Servlet中我们需要处理角色相关的数据。同时调整前面写的JDBC的方法

在这里插入图片描述

然后对应的表单代码

<div class="form-group">
    <label class="col-sm-3 control-label">分配角色:</label>
    <div class="col-sm-8">
        <select class="form-control m-b" name="roleId">
            <c:forEach items="${requestScope.roles}" var="role">
                <option value="${role.id}" ${role.id == entity.roleId?'selected':''}>${role.name}</option>
            </c:forEach>
        </select>
    </div>
</div>

后端的处理代码

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

波波烤鸭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值