CRM管理系统开发总结:
技术选型:Spring+SpringMVC+easyUI+jQuery+mybatis+layUI+shiro+多模块+Maven
负责模块:部门、权限资源、shiro验证
1.部门模块(easyUI)

  • 1.基础组件的创建
1.使用代码生成器逆向生成domain,mapper及mapper.xml
 	2.然后自己创建service层及controller层
 	3.最后创建JS及jsp
  • 2.高级查询及分页
1.创建查询对象

public class BaseQueryObject { private Integer page = 1; private Integer rows = 10; public Integer getPage() { return page; } public void setPage(Integer page) { this.page = page; } public Integer getRows() { return rows; } public void setRows(Integer rows) { this.rows = rows; } }

public class PageResult {
private long total = 0;
private List rows = new ArrayList();
public PageResult() {
}
public PageResult(long total, List rows) {
this.total = total;
this.rows = rows;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public List getRows() {
return rows;
}
public void setRows(List rows) {
this.rows = rows;
} }

  1. service层中创建高级查询分页的方法

public class DepartmentQueryObject extends BaseQueryObject {
//关键字查询
private String keyword;
public String getKeyword() {
if(StringUtils.hasLength(keyword)){
return keyword.trim();
}
return null;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
} }

@Service @Transactional
public class DepartmentServiceImpl extends
BaseServiceImpl implements IDepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
@Override
public void updateStateToDisable(Long id) {
//1.查询对象 Department department = departmentMapper.selectByPrimaryKey(id);
//判断状态
if(department.getState() == Employee.STATE_NORMAL){
//2.修改状态 department.setState(Department.STATE_DISABLED);
updateByPrimaryKey(department);
}
} }

3.编写高级查询分页的sql
<sql id="base_where">
  <where>
    <if test="keyword != null">
      and name like concat("%",#{keyword},"%")
    </if>
  </where>
</sql>

<select id="selectForList" resultMap="BaseResultMap" >
  select id, sn, `name`, manager, parent, children, dirPath, state, tenant
  from department
  <include refid="base_where" />
</select>
		4.创建controller层方法(CRUD)

@Controller @RequestMapping("/department") public class
DepartmentController {
@Autowired
private IDepartmentService departmentService;
//根据id查询部门
@RequestMapping("/getById")
@ResponseBody
public Department getById(Long id){
return departmentService.selectByPrimaryKey(id);
}
//部门主页面
@RequestMapping("/index")
public String index(Model model){
return “department”;
}
//部门列表数据
@RequestMapping("/list")
@ResponseBody
public PageResult list(DepartmentQueryObject qo){
return departmentService.selectForList(qo);
}
@RequestMapping("/findAll")
@ResponseBody
public List findAll(){
return departmentService.selectAll();
}
//部门添加/修改
@RequestMapping("/saveOrUpdate")
@ResponseBody
public AjaxResult saveOrUpdate(Department department){
try {
if(department.getId() == null){
departmentService.insert(department);
}else{
departmentService.updateByPrimaryKey(department);
}
return AjaxResult.success();
}catch (Exception e){
e.printStackTrace();
return AjaxResult.error(“啊,系统异常啦,我们正在殴打程序员O(∩_∩)O~”);
}
}
//部门删除
@RequestMapping("/delete")
@ResponseBody
public AjaxResult remove(Long id){
try {
departmentService.deleteByPrimaryKey(id);
return AjaxResult.success();
}catch (Exception e){
e.printStackTrace();
return AjaxResult.error(“啊,系统异常啦,我们正在殴打程序员O(∩_∩)O~”);
}
} }

3.前台页面对功能的实现(jsp,js)及其sql
		1.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>部门管理</title>
    <jsp:include page="/static/common/common_header.jsp" />
    <script src="/static/js/model/department.js"></script>
</head>
<body>
<%--工具条--%>
<div id="departmentDataGridToolbar">
    <a href="javascript:void(0)" data-method="add" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true">添加</a>
    <a href="javascript:void(0)" data-method="edit"  class="easyui-linkbutton" data-options="iconCls:'icon-edit',plain:true">修改</a>
    <a href="javascript:void(0)" data-method="remove"  class="easyui-linkbutton" data-options="iconCls:'icon-remove',plain:true">删除</a>
    <a href="javascript:void(0)" data-method="reload"  class="easyui-linkbutton" data-options="iconCls:'icon-reload',plain:true">刷新</a>
     关键字:<input type="text" id="keyword">
    <a href="javascript:void(0)" class="easyui-linkbutton"  data-method="search"  data-options="iconCls:'icon-search',plain:true">查询</a>
</div>
<%--员工管理表格--%>
<table id="departmentDataGrid"></table>
<%--添加/编辑 的弹出窗口--%>
<div id="departmentAddDialog" class="easyui-dialog" title="添加/编辑"
     data-options="iconCls:'icon-save',resizable:true,modal:true">
    <form id="departmentAddDialogForm">
        <input type="hidden" name="id" />
        <table>
            <tr>
                <td>部门编号</td>
                <td><input type="text" name="sn"/> </td>
            </tr>
            <tr>
                <td>部门名称</td>
                <td><input type="text" name="name"/> </td>
            </tr>
            <tr>
                <td>部门经理</td>
                <td><input type="text" name="manager"/> </td>
            </tr>
            <tr>
                <td>上级部门</td>
                <td><input type="text" name="parent"/> </td>
            </tr>
            <tr>
                <td>子 部门</td>
                <td><input type="text" name="children"/> </td>
            </tr>
            <tr>
                <td>路  径</td>
                <td><input type="text" name="dirpath"/> </td>
            </tr>
            <tr>
                <td>状  态</td>
                <td><input type="text" name="state"/> </td>
            </tr>
            <tr>
                <td>所属租户</td>
                <td><input type="text" name="tenant"/> </td>
            </tr>
        </table>
    </form>
</div>
<%--添加/编辑 的弹出窗口的按钮组--%>
<div id="departmentAddDialogButtons">
    <a href="javascript:void(0)" class="easyui-linkbutton" data-method="save" data-options="iconCls:'icon-ok',plain:true">保存</a>
    <a href="javascript:void(0)" class="easyui-linkbutton" data-method="close" data-options="iconCls:'icon-cancel',plain:true">关闭</a>
</div>
</body>
</html>

		2.js
function stateFormatter(value,row,index){
    return value == 1 ? "<span style='color:red'>禁用</span>" : "<span style='color:green'>正常</span>";
}
$(function () {
    var  departmentDataGrid = $('#departmentDataGrid');
    var departmentAddDialog = $("#departmentAddDialog");
    var departmentAddDialogForm = $("#departmentAddDialogForm");
    //统一绑定方法
    var methodObj = {
        search:function () {
            //获取关键字
            var keyword = $("#keyword").val();
            //查询
            departmentDataGrid.datagrid("load",{"keyword":keyword});
        },
        add:function () {
            //弹出添加的dialog
            departmentAddDialogForm.form("clear");
            departmentAddDialog.dialog("open");
        },
        edit:function () {
            //获取选中行
            var row = departmentDataGrid.datagrid("getSelected");
            if(row){
                //表单数据回显
                departmentAddDialogForm.form("clear");
                departmentAddDialogForm.form('load',row);

                //弹出编辑框
                departmentAddDialog.dialog("open");
            }else{
                //给出提示
                $.messager.alert("提示","你不选择数据我怎么给你修改?","error");
            }
        },
        remove:function () {
            //获取选中行
            var row = departmentDataGrid.datagrid("getSelected");
            if(row){
                var id = row.id;
                var state = row.state;
                if(state == 1){
                    $.messager.alert("提示","状态已经是删除","error");
                }else{
                    //删除请求ajax
                    $.post("department/remove",{"id":id},function (data) {
                        if(data.success){
                            //列表刷新
                            $.messager.alert("提示","恭喜您,提交成功,列表已经刷新","info");
                            methodObj.reload();
                        }else{
                            $.messager.alert("提示","恭喜您,提交失败,错误原因:"+data.msg,"error");
                        }
                    });
                }
            }else{
                //给出提示
                $.messager.alert("提示","你不选择数据我怎么给你删除?","error");
            }
        },
        reload:function () {
            departmentDataGrid.datagrid("reload");
        },
        save:function () {
            //获取表单
            //提交表单
            departmentAddDialogForm.form('submit', {
                url:"department/saveOrUpdate",
                success:function(data){
                    data = $.parseJSON(data);
                    if(data.success){
                        //列表刷新
                        $.messager.alert("提示","恭喜您,提交成功,列表已经刷新","info");
                        methodObj.close();
                        methodObj.reload();
                    }else{
                        $.messager.alert("提示","恭喜您,提交失败,错误原因:"+data.msg,"error");
                    }
                }
            });
        },
        close:function () {
            departmentAddDialog.dialog("close");
        }
    };
    //统一绑定事件
    $("a[data-method]").click(function () {
        var method = $(this).data("method");
        methodObj[method]();
    });
    //渲染表格
    departmentDataGrid.datagrid({
        url:'department/list',
        fit:true,
        fitColumns:true,
        singleSelect:true,
        pagination:true,
        toolbar:"#departmentDataGridToolbar",
        columns:[[
            {field:'id',title:'ID',width:100},
            {field:'sn',title:'部门编号',width:100},
            {field:'name',title:'部门名称',width:100},
            {field:'manager',title:'部门经理',width:100},
            {field:'parent',title:'上级部门',width:100},
            {field:'children',title:'子部门',width:100},
            {field:'dirpath',title:'路径',width:100},
            {field:'state',title:'状态',width:100,formatter:stateFormatter},
            {field:'tenant',title:'所属租户',width:100}
        ]]
    });
    //添加的dialog
    departmentAddDialog.dialog({
        closed: true,
        modal: true,
        buttons:"#departmentAddDialogButtons"
    });
    departmentAddDialog.dialog({
        left:650,
        top:50
    })
});

		3.sql











delete from department
where id = #{id,jdbcType=BIGINT}
insert into department (sn, name, manager,
parent, children, dirPath,
state, tenant)
values (#{sn,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{manager,jdbcType=VARCHAR},
#{parent,jdbcType=VARCHAR}, #{children,jdbcType=VARCHAR}, #{dirpath,jdbcType=VARCHAR},
#{state,jdbcType=INTEGER}, #{tenant,jdbcType=VARCHAR})
update department
set sn = #{sn,jdbcType=VARCHAR},
name = #{name,jdbcType=VARCHAR},
manager = #{manager,jdbcType=VARCHAR},
parent = #{parent,jdbcType=VARCHAR},
children = #{children,jdbcType=VARCHAR},
dirPath = #{dirpath,jdbcType=VARCHAR},
state = #{state,jdbcType=INTEGER},
tenant = #{tenant,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
select id, sn, name, manager, parent, children, dirPath, state, tenant
from department
where id = #{id,jdbcType=BIGINT}

2.权限模块-资源模块等同(layUI)

  • 1.基础组件的创建
  • 2.高级查询及分页
1.查询对象(这是属于layUI的,所以跟前面的不一样)

public class BaseQuery { private int page = 1;//当前页数 private int limit = 10;//每页显示条数 pageSize public int getPage() { return page; } public void setPage(int page) { this.page = page; } public int getLimit() { return limit; } public void setLimit(int limit) { this.limit = limit; } }

public class PageResult {
private long total = 0;
private List rows = new ArrayList();
public PageResult() {
}
public PageResult(long total, List rows) {
this.total = total;
this.rows = rows;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public List getRows() {
return rows;
}
public void setRows(List rows) {
this.rows = rows;
} }

2.service层

public class RoleQuery extends BaseQuery { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } @Service @Transactional public class RoleServiceImpl extends BaseServiceImpl<Role> implements IRoleService { @Autowired private RoleMapper roleMapper; //根据名字查询角色 @Override public Role selectByName(String name) { return roleMapper.selectByName(name); } @Override public PageList<Role> selectByQuery(BaseQuery baseQuery) { PageList<Role> pageList = new PageList<>(); //maBatis 分页 PageHelper.startPage(baseQuery.getPage(),baseQuery.getLimit()); Page page = (roleMapper.selectByQuery(baseQuery)); //设置总数量 pageList.setCount(page.getTotal()); //设置总数据 pageList.setData(page.getResult()); return pageList; } }

3.sql的编写


  <!--分页-->
    <select id="selectByQuery" parameterType="cn.itsource.ssme.query.RoleQuery" resultMap="BaseResultMap"
            resultType="cn.itsource.ssme.domain.RolePermission">
      SELECT
      r.id,r.name,p.name
      FROM role r
      JOIN role_permission rp
      ON  r.id=rp.role_id
      JOIN permission p
      ON  p.id=rp.permission_id
      <where>
        <if test="name!=null and name !='' ">
          role.name LIKE concat('%',#{name},'%')
        </if>
      </where>
    </select>
		4.控制层controller功能CRUD
@Controller
@RequestMapping("/role")
public class RoleController {
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IPermissionService permissionService;
    @Autowired
    private IRolePermissionService rolePermissionService;
    @Autowired
    private IRoleMenuService roleMenuService;
    @Autowired
    private ISystemMenuService systemMenuService;
    @RequestMapping("/index")
    public String index() {
        return "role";
    }
    @RequestMapping("/list")
    @ResponseBody//json
    public PageList<Role> list(RoleQuery roleQuery) {
        return roleService.selectByQuery(roleQuery);
    }
    // role/delete?id
    @RequestMapping("/delete")
    @ResponseBody//json
    public AjaxResult delete(Long[] ids) {
        try {
            //删除先把中间表删除
            for (Long id : ids) {
                rolePermissionService.deleteByRoleId(id);
            }
            for (Long id : ids){
                roleMenuService.deleteByRoleId(id);
            }
            for (Long id : ids) {
                roleService.deleteByPrimaryKey(id);
            }
            return AjaxResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("删除失败!!!");
        }
    }
    @RequestMapping("/saveOrUpdate")
    @ResponseBody//json
    public AjaxResult saveOrUpdate(Role role) {
        //将获取到的权限封装到角色对象里面
        List<Permission> permissions = new ArrayList<>();
        for (Permission permission : role.getSn()) {
            Permission permission1 = permissionService.selectByPrimaryKey(permission.getId());
            permissions.add(permission1);
        }
        role.setSn(permissions);
        //获取到菜单,封装的角色对象里面
        List<SystemMenu> systemMenus = new ArrayList<>();
        for (SystemMenu menu : role.getSystemMenus()) {
            systemMenuService.selectByPrimaryKey(menu.getId());
            systemMenus.add(systemMenuService.selectByPrimaryKey(menu.getId()));
        }
        if (role != null) {
            try {
                //判断是否有id,有就是修改,没有就是添加
                if (role.getId() != null) {
                    //这个是当前角色未被修改的权限
                    List<RolePermission> list = rolePermissionService.selectByRoleId(role.getId());
                    //这是当前角色未被修改的菜单
                    List<RoleMenu> roleMenus = roleMenuService.selectByRoleId(role.getId());
                    for (SystemMenu systemMenu : systemMenus) {
                        roleMenuService.deleteByRoleId(role.getId());
                    }
                    for (int i = 0; i < systemMenus.size(); i++) {
                        RoleMenu roleMenu = new RoleMenu();
                        roleMenu.setRoleId(role.getId());
                        roleMenu.setMenuId(systemMenus.get(i).getId());
                        roleMenuService.insert(roleMenu);
                    }
                    for (RolePermission permission : list) {
                       /* System.out.println("这个是当前角色未被修改的权限------------"+permission);*/
                        //删除所有的
                        rolePermissionService.deleteByRoleId(role.getId());
                    }
                    //这是修改我们选中的权限
                    for (int i = 0; i < permissions.size(); i++) {
                        RolePermission rolePermission = new RolePermission();
                        rolePermission.setRoleId(role.getId());
                        rolePermission.setPermissionId(permissions.get(i).getId());
                       /* System.out.println("这是修改我们选中的权限"+rolePermission);*/
                        //在添加
                        rolePermissionService.insert(rolePermission);
                    }
                    //修改 清空
                    role.setSn(null);
                    role.setSystemMenus(null);
                    roleService.updateByPrimaryKey(role);
                } else {
                    //添加
                    Role role1 = new Role();
                    role1.setName(role.getName());
                    //在角色表里添加
                    roleService.insert(role1);
                    //在搜索出我们刚才添加对象
                    Role roleId = roleService.selectByName(role1.getName());
                    //id是空的啊  因为我在添加啊   所以先添加角色表内容在搜索出刚才添加的对象id
                    //向角色id里面添加所有的权限id
                    for (int i = 0; i < permissions.size(); i++) {
                        RolePermission rolePermission = new RolePermission();
                        rolePermission.setRoleId(roleId.getId());
                        rolePermission.setPermissionId(permissions.get(i).getId());
                        rolePermissionService.insert(rolePermission);
                    }
                    for (int i = 0; i <systemMenus.size() ; i++) {
                        RoleMenu roleMenu = new RoleMenu();
                        roleMenu.setRoleId(roleId.getId());
                        roleMenu.setMenuId(systemMenus.get(i).getId());
                        roleMenuService.insert(roleMenu);
                    }
                }
                return AjaxResult.success();
            } catch (Exception e) {
                e.printStackTrace();
                return AjaxResult.error("操作失败!!!");
            }
        }
        return null;
    }
    //动态的获取所有的权限
    @RequestMapping("/findPermissionAll")
    @ResponseBody
    public List<Permission> findPermissionAll() {
        return permissionService.selectAll();
    }
    //动态的获取所有的菜单
    @RequestMapping("findMenuAll")
    @ResponseBody
    public List<SystemMenu> findMenuAll(){
        return systemMenuService.selectAll();
    }
}
3.前台页面对功能的实现及其sql
		1.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>角色管理</title>
    <%--引入自己封装的公共代码,依赖于layui和jquery--%>
    <%@include file="/static/common/head.jsp" %>
    <script type="application/javascript" src="/static/js/model/role.js"></script>

</head>
<body>
<%--头部工具栏--%>
<script type="text/html" id="toolbarDemo">
    <div class="layui-btn-container">
<shiro:hasPermission name="dept:save">
        <button class="layui-btn layui-btn-sm" lay-event="add"><i class="layui-icon">添加</i></button>
</shiro:hasPermission>
<shiro:hasPermission name="dept:delete">
        <button class="layui-btn layui-btn-sm" lay-event="delete"><i class="layui-icon">删除</i></button>
</shiro:hasPermission>
<shiro:hasPermission name="dept:update">
        <button class="layui-btn layui-btn-sm" lay-event="update"><i class="layui-icon">编辑</i></button>
</shiro:hasPermission>
    </div>
</script>
<%--头部高级查询的form表单--%>
<div class="layui-form">
    <div class="layui-form-item">
        <div class="layui-inline">
            <label class="layui-form-label">角色名</label>
            <div class="layui-input-inline">
                <input type="text" name="roleName" class="layui-input" placeholder="请输入角色名">
            </div>
        </div>
        <div class="layui-inline">
            <div class="layui-input-inline">
                <div class="layui-btn" lay-submit id="serch" lay-filter="serch">立即提交</div>
            </div>
        </div>
    </div>
</div>
<%--数据表单--%>
<table class="layui-hide" id="roleTable" lay-filter="roleTable"></table>
<%--弹出框的form--%>
<form class="layui-form" id="roleFormDlog" lay-filter="roleFormDlog" style="display:none;">
    <input type="hidden" name="id">
    <div class="layui-form-item">
        <label class="layui-form-label">角色名:</label>
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="name" placeholder="请输入" autocomplete="off">
        </div>
    </div>
    <%--权限下拉框--%>
    <div class="layui-form-item">
        <label class="layui-form-label">权限选择</label>
            <div class="layui-input-block" id="allPermission"> </div>
    </div>
    <%--菜单下拉框--%>
    <div class="layui-form-item">
        <label class="layui-form-label">菜单选择</label>
        <div class="layui-input-block" id="allMenu"> </div>
    </div>
    <div class="layui-form-item">
        <div class="layui-form-item">
            <div class="layui-input-block">
                <button class="layui-btn" lay-submit lay-filter="save">立即提交</button>
                <a class="layui-btn layui-btn-sm" data-cmd="reset"> <i class="layui-icon">重置</i></a>
            </div>
        </div>
    </div>
</form>
</body>
</html>
		2.js
layui.config({
    base: '/static/js/'
}).extend({
    selectN: './layui_extends/selectN',
    selectM: './layui_extends/selectM',
}).use(['jquery', 'table', 'form', 'layer', 'selectN', 'selectM'], function () {
    var selectN = layui.selectN
    var selectM = layui.selectM;
    var table = layui.table; //数据表格对象
    var form = layui.form;//头部form表单对象
    var layer = layui.layer;//弹出层对象
    var $ = layui.jquery;//加载jquery对象
    var emp = {};
    // 创建数据表格
    table.render({
        elem: '#roleTable'
        ,id: '#roleTable'
        , url: '/role/list'
        , title: '员工信息'
        , even: true //开启隔行背景
        , toolbar: '#toolbarDemo'
        , cols: [[
            {type: 'checkbox', fixed: 'left'},
            {field: 'id', title: '编号', align: 'center'},
            {field: 'name', title: '角色名', align: 'center'},
            {
                field: 'sn', title: '权限', align: 'center', templet: function (d) {
                    var permissions = [];
                    if (d.sn.length) {
                        $.each(d.sn, function (index, obj) {
                            permissions.push(obj.name);
                        })
                    }
                    return permissions;
                }
            },{
                field:'systemMenus',title:'菜单',align:'center',templet:function (d) {
                    var systemMenus = [];
                    if (d.systemMenus.length) {
                        $.each(d.systemMenus, function (index, obj) {
                            systemMenus.push(obj.name);
                        })
                    }
                    return systemMenus;
                }
            }
        ]]
        , page: true
    });
    var p = []
    var r=[]
    //多选标签-基本配置权限下拉框
    var permissions = selectM({
        //元素容器【必填】
        elem: '#allPermission'
        //候选数据【必填】
        , data: "/role/findPermissionAll"
        , max: 100
        , width: 400
        //添加验证
        , verify: 'required'
        ,selected:p
    });
    //多选标签-基本配置菜单下拉框
    var allMenu = selectM({
        //元素容器【必填】
        elem: '#allMenu'
        //候选数据【必填】
        , data: "/role/findMenuAll"
        , max: 100
        , width: 400
        //添加验证
        , verify: 'required'
        ,selected:r
    });
    //高级查询提交
    form.on("submit(serch)", function (data) {
        var serchdate = data.field;
        console.debug(serchdate.roleName);
        table.reload('#roleTable', {
            url:"/role/list"
            ,where: { //设定异步数据接口的额外参数,任意设
                name:serchdate.roleName
            }
            ,page: {
                curr: 1 //重新从第 1 页开始
            }
        });
    });
    //监听事件
    table.on('toolbar(roleTable)', function(obj){
        var checkStatus = table.checkStatus(obj.config.id);
        switch(obj.event){
            case 'add':
                // 弹出添加框
                layer.open({
                    type: 1,
                    title: "添加",
                    closeBtn: false,
                    shift: 2,
                    area: ['600px', '500px'],
                    shadeClose: true,
                    btn: ['取消'],
                    offset: '100px',
                    // btnAlign: 'c',
                    content: $("#roleFormDlog"),
                    //弹出成功后的回调
                    success: function (layero, index) {
                        form.val("roleFormDlog", {"id": ""});
                        form.val("roleFormDlog", {"name": ""});
                    }
                });
                break;
            case 'delete':
                var id = table.checkStatus("#roleTable");
                var ids = [];
                $.each(id.data, function (index, obj) {
                    ids.push(obj.id);
                });
                if (ids.length) {
                    $.get("/role/delete", {"ids": ids.toString()}, function (res) {
                        if (res.success) {
                            //数据表格刷新
                            $(".layui-laypage-btn")[0].click();
                            layer.msg("删除成功", {
                                time: 2000, //20s后自动关闭
                            });
                            //当前页数据条数   table.cache.test
                            var count = (table.cache.length) - (ids.length);
                            //删除后如果当前页没有数据了就跳到上一页
                            if (count == 0) {
                                //当前页码值
                                var current = $(".layui-laypage-em").next().html();
                                $(".layui-laypage-skip").find("input").val(current - 1);
                                $(".layui-laypage-btn").click();
                            }
                        } else {
                            layer.msg("删除失败" + res.mag, {
                                time: 2000 //20s后自动关闭
                            });
                        }
                    });
                } else {
                    layer.msg("请选择后删除", {
                        icon: 0,
                        time: 2000
                    });
                }
                break;
            case 'update':
                var id = table.checkStatus("#roleTable");
                var p = []
                var r=[]
                var ids = [];
                $.each(id.data, function (index, obj) {
                    ids.push(obj.id);
                    if((obj.sn).length){
                        $.each(obj.sn,function (i,o) {
                            //将选中的放入数组。后面默认选中
                            p.push(o.id)
                        })
                    }
                    if((obj.systemMenus).length){
                        $.each(obj.systemMenus,function (i,o) {
                            r.push(o.id)
                        })
                    }
                });
                //多选标签-基本配置  回显下拉框
                var p1 = selectM({
                    //元素容器【必填】
                    elem: '#allPermission'
                    //候选数据【必填】
                    , data: "/role/findPermissionAll"
                    , max: 100
                    , width: 400
                    //添加验证
                    , verify: 'required'
                    ,selected:p
                });
                var p2 = selectM({
                    //元素容器【必填】
                    elem: '#allMenu'
                    //候选数据【必填】
                    , data: "/role/findMenuAll"
                    , max: 100
                    , width: 400
                    //添加验证
                    , verify: 'required'
                    ,selected:r
                });
                if (ids.length) {
                    layer.open({
                        type: 1,
                        title: "修改",
                        closeBtn: false,
                        shift: 2,
                        area: ['600px', '500px'],
                        shadeClose: true,
                        btn: ['取消'],
                        //form表单回显
                        offset: '100px',
                        // btnAlign: 'c',
                        content: $("#roleFormDlog"),
                        //弹出成功后的回调
                        success: function (layero, index) {
                            var obj = table.checkStatus("#roleTable");
                            $.each(obj.data, function (i, o) {
                                form.val("roleFormDlog", {"id": o.id});
                                form.val("roleFormDlog", {"name": o.name});
                            })
                        }
                    })
                }
                else {
                    layer.msg("请选择后修改", {
                        icon: 0,
                        time: 2000
                    });
                }
                break;
        };
    });
    //添加与删除事件
    $("a").on("click", function () {
        var cmd = $(this).data("cmd");
        if (cmd) {
            itsource[cmd]();
        }
    });
    var itsource = {
        //重置搜索框
        "reset": function () {
            document.getElementById("roleFormDlog").reset();
            //多选标签-基本配置  回显下拉框
            var p1 = selectM({
                //元素容器【必填】
                elem: '#allPermission'
                //候选数据【必填】
                , data: "/role/findPermissionAll"
                , max: 100
                , width: 400
                //添加验证
                , verify: 'required',
                selected:[]
            });
        }
    };
    //弹出框提交
    form.on("submit(save)", function (data) {
        var setted = data.field;
        //sn[0].id=1
        for (var i = 0; i < (permissions.values).length; i++) {
            // (permissions.values)[i];
            //动态的拼接传参 权限
            setted["sn[" + i + "].id"] = (permissions.values)[i]
        }
        for (var i = 0; i < (allMenu.values).length; i++) {
            //动态的拼接传参 菜单
            setted["systemMenus[" + i + "].id"] = (allMenu.values)[i]
        }
        console.debug(56465);
        var url = "/role/saveOrUpdate";
        $.ajax({
            url: url,
            type: 'post',
            data: setted,
            success: function (res) {
                if (res.success) {
                    //关闭弹出框
                    layer.closeAll();
                    //数据表格刷新
                    $(".layui-laypage-btn")[0].click();
                    layer.msg("操作成功", {
                        time: 2000, //20s后自动关闭
                    });
                } else {
                    layer.closeAll();
                    layer.msg("操作失败" + res.mag, {
                        time: 2000 //20s后自动关闭
                    });
                }
            }
        });
        return false;//防止页面跳转,进行局部刷新
    });
});

		3.sql
<mapper namespace="cn.itsource.mapper.RoleMapper" >
  <resultMap id="BaseResultMap" type="cn.itsource.ssme.domain.Role" >
    <id column="id" property="id" jdbcType="BIGINT" />
    <result column="name" property="name" jdbcType="VARCHAR" />
    <result column="tenant" property="tenant" jdbcType="INTEGER" />
    <collection property="sn" column="id" select="cn.itsource.mapper.RoleMapper.selectSn">
    </collection>
    <collection property="systemMenus" column="id"
                select="cn.itsource.mapper.RoleMapper.selectMenu"></collection>
  </resultMap>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long" >
    delete from role
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="cn.itsource.ssme.domain.Role" useGeneratedKeys="true" keyProperty="id" >
    insert into role (`name`, tenant
      )
    values ( #{name,jdbcType=VARCHAR}, #{tenant,jdbcType=INTEGER}
      )
  </insert>
  <update id="updateByPrimaryKey" parameterType="cn.itsource.ssme.domain.Role" >
    update role
    set
     `name` = #{name,jdbcType=VARCHAR},
      tenant = #{tenant,jdbcType=INTEGER}
    where id = #{id,jdbcType=BIGINT}
  </update>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" >
    select id,`name`, tenant
    from role
    where id = #{id,jdbcType=BIGINT}
  </select>
  <select id="selectAll" resultMap="BaseResultMap" >
    select id, `name`, tenant
    from role
  </select>
  <select id="selectByName" resultMap="BaseResultMap" parameterType="string">
    SELECT * FROM role WHERE `name` = #{name}
  </select>
  <select id="selectSn" resultType="cn.itsource.ssme.domain.Permission">
    SELECT DISTINCT p.* FROM role_permission rrpp
    JOIN permission p ON rrpp.permission_id=p.id
    JOIN role r on rrpp.role_id=r.id
    WHERE r.id=#{id}
  </select>
  <select id="selectMenu" resultType="cn.itsource.ssme.domain.SystemMenu">
    SELECT DISTINCT s.* FROM role_menu rm
    JOIN systemmenu s ON rm.menu_id=s.id
    JOIN role r ON rm.role_id = r.id
    WHERE r.id=#{id}
  </select>
</mapper>

3.shiro模块

  • 1.首先导入shiro及与Spring的依赖
  • 2.创建一个myrealm去继承AuthorizingRealm,然后覆写它的两个方法

public class ItsourceRealm extends AuthorizingRealm {
@Autowired
private IEmployeeService employeeService;
@Autowired
private IPermissionService permissionService;
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
Employee employee = UserContext.getUser();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set permissions = permissionService.findPermissionSnByEmployee(employee);
info.setStringPermissions(permissions);
return info;
}
//身份认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws
AuthenticationException {
String username = (String)token.getPrincipal();
Employee employee = employeeService.selectByUserName(username);
if(employee == null){
return null;
}
ByteSource salt = ByteSource.Util.bytes(MD5Util.SALT);
return new SimpleAuthenticationInfo(employee,employee.getPassword(),salt,getName());
} }

3.创建applicationContext-shiro.xml配置文件
 <!--shiro的核心对象已经交给spring管理-->
 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
     <property name="realm" ref="itsourceRealm"/>
 </bean>
 <bean id="itsourceRealm" class="cn.itsource.realm.ItsourceRealm">
     <property name="credentialsMatcher">
         <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
             <!--加密方式-->
             <property name="hashAlgorithmName" value="MD5"/>
             <!--加密次数-->
             <property name="hashIterations" value="10"/>
         </bean>
     </property>
 </bean>
 <!--
     shiro最核心的配置       处理请求的具体方式
     注意:该bean的id对应的值必须要和代理过滤器的名字一致,否则报错
 -->
 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
     <property name="securityManager" ref="securityManager"/>
     <!--如果没有认证,都跳到loginUrl对应的路径-->
     <property name="loginUrl" value="/login"/>
     <!--如果认证通过之后,就跳到successUrl对应的路径-->
     <property name="successUrl" value="/main"/>
     <!--如果你访问某个资源,没有权限,就跳到unauthorizedUrl对应的路径中-->
     <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
     <!--动态调用过滤链-->
     <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"/>
     <!--自定义过滤器-->
     <property name="filters">
         <map>
             <entry key="itsourcePerms" >
                 <bean class="cn.itsource.realm.ItsourcePermissionsAuthorizationFilter"/>
             </entry>
         </map>
     </property>
 </bean>
 <bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapFactory" factory-method="createMap"/>
 <bean id="filterChainDefinitionMapFactory" class="cn.itsource.realm.FilterChainDefinitionMapFactory"/>

public class MD5Util {//公共对密码加密的类
//加密方式
public static final String ALGORITHMNAME = “MD5”;
//盐值
public static final String SALT = “kaley”;
//加密次数
public static final int HASHITERATIONS = 10;
//MD5加密
public static String createMd5(String source){//加密的方法
SimpleHash hash = new SimpleHash(ALGORITHMNAME,source,SALT,HASHITERATIONS);
return hash.toString();
} }

5.创建一个权限监听类

public class FilterChainDefinitionMapFactory {
@Autowired
private IPermissionService permissionService;
public Map<String,String> createMap(){
List permissions = permissionService.selectAll();
Map<String, String> map = new LinkedHashMap<>();
map.put("/static/", “anon”);
map.put("/login", “anon”);
map.put("/logout", “logout”);
map.put(".css", “anon”);
map.put("
.js", “anon”);
map.put("/logout", “logout”);
for (Permission permission : permissions) {
map.put(permission.getUrl(), “itsourcePerms[”+permission.getSn()+"]");
}
map.put("/
", “authc”);
return map;
} }

6.web读取配置文件及shiro过滤器
<!--读取Spring的核心配置文件-->
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
    classpath:applicationContext.xml
    classpath:applicationContext-shiro.xml
  </param-value>
</context-param>
<!-- Spring与shiro集成:需要定义一个shiro过滤器(这是一个代理过滤器,它会到spring的配置中找一个名称相同的真实过滤器) -->
<filter>
  <filter-name>shiroFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  <init-param>
    <param-name>targetFilterLifecycle</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>shiroFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
	7.最后前台页面实现功能