EasyUI前端应用基础续编。
datagrid网格之模糊查询与数据表冻结
模糊查询:
这里以学生姓名stuname作模糊查询,where 1=1 and stuname='%xxx%' 注:1=1表示所有。
以上例为基础:div作为table的一个工具,div里有两个输入框,一个链接按钮,分别用于用户输入学生名,与学号作对学生的模糊查询。
一。jsp
学生ID:
学生姓名:
搜索
二。js 注意:url:''/sshwebtest/getAllPagerStudents'这是链接到后台的控制层'
$(function(){
$("#dg").datagrid({
title:"用户信息表",
//url:"/sshwebtest/getAllStudentsD", //没有分页显示的远程后台数据处理
url:"/sshwebtest/getAllPagerStudents",
pagination:true, //分页显示,有修改每页显示多少条功能,不用写代码
pageSize:5, //初始化每页显示几条记录
pageList:[5,10,25,30,100], //设置分页每页能显示多少条记录选择项,这里是每页有5条,10条,,,多个选项,
// method:"post", //默认为post可以不写这行代码
columns:[[
{field:"ck",checkbox:"true"}, //最左侧有复选框,可供我们选择,
{field:"id",title:"id",width:100},
{field:"stuname",title:"stuname",width:100},
{field:"password",title:"password",width:100},
{field:"state",title:"state",width:100,formatter:function(value,row,index){
if(value == 1){
return "正常";
}else{
return "禁用状态";
}
}},
{field:"regDate",title:"regDate",width:100},
{field:"height",title:"height",width:100}
]], //两个中括号,表示二维表格
striped:true, //把表格网纹化,即奇偶行不同背影 色
toolbar:"#tb",
toolbar:[ //网格上有工具栏,有一个工具(铅笔)
{
text:"编辑",
iconCls:"icon-edit",
handler:function(){
//alert("单击");
var datas = $("#dg").datagrid("getChecked"); //获取选中复选框中记录
if(datas.length > 0 ){
for(var i=0;i
三.后台控制层StuCtroller.java与service,dao的一个代码片段
//带分页显示所有学生信息,学生姓名作模糊查询,不用注入对象,这里我们直接用网页与easyui交互,用到json格式数据,所以用@ResponseBody注解
@Controller
public class StuController {
@Autowired
private StudentService stuService;
@ResponseBody
@RequestMapping(value="/getAllPagerStudents",method=RequestMethod.POST)
public Pager getAllPagerStudents(Integer page,
Integer rows, //page,rows值由easyui 网格自动发送的请求而过来的
@RequestParam(value="id",required=false) Integer id,
@RequestParam(value="stuname",required=false) String stuname) //id,stuname是接收输入框输入的数据
{
System.out.println("StuController.java中由easyui 网格发送的page,rows "+page+","+rows);
if(page != null && page>0) SystemContext.setPageSize(rows); //每一页两条记录
if(rows !=null && rows>0) SystemContext.setPageOffset((page-1)*rows); //从第一条记录开始分
Student stu = new Student();
if(id!=null && id >0 ) stu.setId(id);
if(stuname !=null && !"".equals(stuname) ) stu.setStuname(stuname);
Pager pager = stuService.getAllPagerStus(stu);
SystemContext.removePageOffset();
SystemContext.removePageSize();
return pager;
}
}
-----------------------------------------------------StudentServiceImpl--------------------------------------------
@Service("stuService")
public class StudentServiceImpl extends BaseServiceIpml implements StudentService {
@Override
public Pager getAllPagerStus(Student stu) {
return stuDao.getAllPagerStus(stu);
}
}
------------------------------------------------------StudentService---------------------------------------
public interface StudentService extends BaseService {
/**
* 获取所有学生信息,不支持分页
* @return
*/
public List getAllStus();
/**
* 获取所有学生信息,支持分页
* @param stu
* @return
*/
public Pager getAllPagerStus(Student stu);
}
-----------------------------------------------------------StudentDaoImpl.java------------------------------
@Repository("stuDao")
public class StudentDaoImpl extends BaseDaoImpl implements StudentDao{
//下面写的方法都是本类个性化的方法
@Override
public List getAllStus() {
String hql="from Student";
return super.list(hql, null, null);
}
//分页且模糊查询
@Override
public Pager getAllPagerStus(Student stu) {
String hql="from Student s where 1=1";
if(stu.getId()>0) hql+=" and u.id="+stu.getId();
if(stu.getStuname()!=null &&!"".equals(stu.getStuname()))
hql+=" and s.stuname like'%"+stu.getStuname()+"%'";
return super.find(hql, null, null);
}
}
--------------------StudentDao.java-------------------------------------
public interface StudentDao extends BaseDao{
/**
* 获取所有学生信息,不支持分页
*/
public List getAllStus();
/**
* 获取所有学生信息,支持分页
* @param stu
* @return
*/
public Pager getAllPagerStus(Student stu);
}
---------------------------------------------Pager.java--------------------------------------------------------
public class Pager {
/**
* 分页的大小,每页显示数据的条数
*/
private int size;
// 每页的第一条数据的,条数索引
private int offset;
/**
* 查询出来的总的数据条数,rows--与easyui分页插件里变量名称一致
*/
private long total;
/**
* 每张每页是具体数据(一页所有的记录),rows--easyui与分页插件里变量名称一致
*/
private List rows;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
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;
}
@Override
public String toString() {
return "Pager [size=" + size + ", offset=" + offset + ", total=" + total + ", rows=" + rows + "]";
}
}
-------------------SystemContext.java--------------------------------
/**
* ThreadLocal:数据共享,本地线程变量里的数据,每个线程中创建副本,在多条线程中,给这个变量赋值,
* 每条线程使用不会冲突 进行分页信息通信
* 排序信息通信
*
* @author Administrator
*
*/
public class SystemContext {
// 分页大小,每页显示的数据条数
private static ThreadLocal pageSize = new ThreadLocal<>();
// 每页的起始的条数索引
private static ThreadLocal pageOffset = new ThreadLocal<>();
// 排序的字段
private static ThreadLocal sort = new ThreadLocal<>();
// 排序方式
private static ThreadLocal order = new ThreadLocal<>();
public static Integer getPageSize() {
return pageSize.get();
}
public static void setPageSize(Integer _pageSize) {
pageSize.set(_pageSize);
}
public static Integer getPageOffset() {
return pageOffset.get();
}
public static void setPageOffset(Integer _pageOffset) {
pageOffset.set(_pageOffset);
}
public static String getSort() {
return sort.get();
}
public static void setSort(String _sort) {
sort.set(_sort);
}
public static String getOrder() {
return order.get();
}
public static void setOrder(String _order) {
order.set(_order);
}
public static void removePageSize() {
pageSize.remove();
}
public static void removePageOffset() {
pageOffset.remove();
}
public static void removeSort() {
sort.remove();
}
public static void removeOrder() {
order.remove();
}
}
------------------------------------------------------------------------BaseService.java--------------------
public interface BaseService {
// 添加
public T add(T t);
// 删除
public void delete(int id);
// 修改
public void update(T t);
// 查询
public T load(int id);
}
----------------------------------------------------------BaseServiceImpl.java-------------------------------
public class BaseServiceIpml implements BaseService {
@Autowired
protected BaseDao baseDao;
@Override
public T add(T t) {
return baseDao.add(t);
}
@Override
public void delete(int id) {
baseDao.delete(id);
}
@Override
public void update(T t) {
baseDao.update(t);
}
@Override
public T load(int id) {
return baseDao.load(id);
}
}
------------------------------------------------------------BaseDao.java接口--------------------------------
public interface BaseDao {
// 添加
public T add(T t);
// 删除
public void delete(int id);
// 修改
public void update(T t);
// 查询
public T load(int id);
}
-----------------------------------------------------------BaseDaoImpl.java------------------------------
/**
* BaseDaoImpl:操作数据库的基本方法代码
*
* @author Administrator
* @param
*/
public class BaseDaoImpl implements BaseDao {
@Autowired
private SessionFactory sessionFactory; //spring.xml配置了
private Class clazz;
public Class getClazz() {
/*
Type type= this.getClass().getGenericSuperclass();//this将代表BaseDaoImpl的子类对象如:UserDaoImpl extends BaseDaoImpl
ParameterizedType pt=(ParameterizedType) type;
Type[] types = pt.getActualTypeArguments();
Class clz = (Class) types[0];
return clz;
*/
if (clazz == null) {
clazz = ((Class) ((((ParameterizedType) (this.getClass().getGenericSuperclass()))
.getActualTypeArguments())[0]));
}
return clazz;
}
/**
* 获取数据连接回话的方法
*/
public Session getSession() {
return sessionFactory.getCurrentSession();
}
@Override
public T add(T t) {
getSession().save(t);
return t;
}
@Override
public void delete(int id) {
getSession().delete(load(id));
}
@Override
public void update(T t) {
getSession().update(t);
}
@SuppressWarnings("unchecked")
@Override
public T load(int id) {
return (T) getSession().load(getClazz(), id);//hibernate中有load(xxx.class,xxx)方法加载数据库数据即返回记录
}
/**
* 用hql语句查询多条记录,没有分页,list返回对象.两种spring处理数据库的占位符
* @param hql
* @param objs 替换hql语句中?占位符的实参
* @param alias 替换hql语句中:name占位符的实参
* @return
*/
//其它类如UserDaoImpl,StudentDaoImpl等调用如 :return super.list(hql, null, null);
@SuppressWarnings("unchecked")
public List list(String hql, Object[] objs, Map alias) {
hql = initSort(hql); //初始化排序规则
Query query = getSession().createQuery(hql);
setParameter(query,objs); //将hql里?占位符替换
setAliasParameter(query,alias);
return query.list();
}
/**
* 替换hql语句中:name占位符的实参
* @param query
* @param alias
*/
@SuppressWarnings("rawtypes")
private void setAliasParameter(Query query, Map alias) {
if(alias != null) {
Set keys = alias.keySet();
for(String key:keys) {
Object val = alias.get(key); //取key对应的值
if(val instanceof Collection) { //判断是不是一个集合
query.setParameterList(key, (Collection)val);
}else {
query.setParameter(key, val);
}
}
}
}
/**
* 将hql里?占位符替换
* @param query
* @param objs
*/
private void setParameter(Query query,Object[] objs) {
if(objs != null && objs.length > 0) {
int index = 0;
for(Object obj:objs) {
query.setParameter(index++, obj);
}
}
}
/**
* 给hql语句加排序规则
* @param hql
* @return
*/
private String initSort(String hql) {
String sort = SystemContext.getSort(); // 数据我们可以在Controller放
String order = SystemContext.getOrder();
if (sort != null && !"".equals(sort.trim())) {
hql += " order by " + sort; //例:String hql="select from User order by desc...."
if (!"desc".equals(order)) {
hql += " asc";
} else {
hql += " desc";
}
}
return hql;
}
/**
* 查询多条数据,支持分页
* @param hql
* @param objs
* @param alias
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public Pager find(String hql, Object[] objs, Map alias){
hql = initSort(hql);//初始化排序规则
Query query = getSession().createQuery(hql);
setParameter(query,objs);//将hql里?占位符替换
setAliasParameter(query,alias);
Pager pager = new Pager<>();
setPager(query,pager);
List datas = query.list();
pager.setRows(datas);
//还需要一个查询的中条数 select count(*) from users where id>10
String countHql = getCountHql(hql);
Query countQuery = getSession().createQuery(countHql);
setParameter(countQuery,objs);//将hql里?占位符替换
setAliasParameter(countQuery,alias);
long total = (long) countQuery.uniqueResult();
pager.setTotal(total);
return pager;
}
private String getCountHql(String hql) {
String hhql = hql.substring(hql.indexOf("from")); // 拿到hql语句的form开始后半部分:from users where id>10
String countHql = "select count(*) " + hhql;
//hql语句,fetch
countHql = countHql.replace("fetch", "");
return countHql;
}
private void setPager(Query query, Pager pager) {
Integer pageSize = SystemContext.getPageSize();
Integer pageOffset = SystemContext.getPageOffset();
if(pageOffset == null || pageOffset < 0) {
pageOffset = 0; // pageOffset的默认值
}
if (pageSize == null || pageSize < 0) {
pageSize = 10; // 没有设置每页大小,默认每页显示10条
}
pager.setOffset(pageOffset);
pager.setSize(pageSize);
// data数据,也就是分页的数据 select id,username,pasword from users where id>10; 一张页面上显示的数据
query.setFirstResult(pageOffset).setMaxResults(pageSize);
}
//使用sql语句查询的方法,list,pager
/**
* 针对一些特殊的查询,返回不受泛型的制约,返回object
* @param hql
* @param objs
* @param alias
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public Object queryByHql(String hql, Object[] objs, Map alias) {
Query query = getSession().createQuery(hql);
setParameter(query,objs);//将hql里?占位符替换
setAliasParameter(query,alias);
return query.uniqueResult();
}
/**
* 应对某些特殊情况要用hql语句,来做更新
* @param hql
* @param objs
* @param alias
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void updateByHql(String hql, Object[] objs, Map alias) {
Query query = getSession().createQuery(hql);
setParameter(query,objs);//将hql里?占位符替换
setAliasParameter(query,alias);
query.executeUpdate();
}
}
四,DAO层,service层见代码 'sshwebtest'项目
五,测试
http://localhost/sshwebtest/
数据表冻结
项目中,显示的数据字段数很多,屏幕宽显示不小,这时,就会生成滚动条进行滚动查看:有些列和行,我们不希望它随着滚动而被遮盖,这个时候我们就可以使用冻结功能:
1.冻结列:
frozenColumns array 和列( column )属性一样,但是这些列将被冻结在左边
应用格式:frozenColumns:[[]]
例:冻结第一到第三列:id,password,stuname
$("#dg").datagrid({
width:500, //网格的宽,设置小一点可以看出移动滚动条的效果
height:300,
title:"用户信息表",
//url:"/sshwebtest/getAllStudentsD", //没有分页显示的远程后台数据处理
url:"/sshwebtest/getAllPagerStudents",
pagination:true, //分页显示,有修改每页显示多少条功能,不用写代码
pageSize:5, //初始化每页显示几条记录
pageList:[5,10,25,30,100], //设置分页每页能显示多少条记录选择项,这里是每页有5条,10条,,,多个选项,
frozenColumns:[[
{field:"ck",checkbox:"true"}, //最左侧有复选框,可供我们选择,
{field:"id",title:"id",width:100},
{field:"stuname",title:"stuname",width:100},
{field:"password",title:"password",width:100},
]],
columns:[[ //列数组
{field:"state",title:"state",width:100,formatter:function(value,row,index){
if(value == 1){
return "正常";
}else{
return "禁用状态";
}
}},
{field:"regDate",title:"regDate",width:100},
{field:"height",title:"height",width:100}
]], //两个中括号,表示二维表格
striped:true,
…………………………其它代码与上面一样
2.冻结行:
当数据行很多时,会呈现垂直的滚动条,但是向下滚动,表头却被淹没了,这不符
合人类偷懒的特点(我怎么可能记得住每列的数据代表的意思!),所以需要固定表头。
21.fit: true, // 单独 fit 固定表头,
注:固定了表头,只显示第一页,显分页栏不见了,冻结的列也失效
22.onLoadSuccess: function(){
$(this).datagrid("freezeRow",0); // 额外固定某些行
}
--------
onLoadSuccess: function(){
$(this).datagrid("freezeRow",0); // 额外固定某些行(0表示第一行)
},
frozenColumns:[[
{field:"ck",checkbox:"true"}, //最左侧有复选框,可供我们选择,
{field:"id",title:"id",width:100},
{field:"stuname",title:"stuname",width:100},
{field:"password",title:"password",width:100},
]],
//fit:true,
columns:[[ //列数组
{field:"state",title:"state",width:100,formatter:function(value,row,index){
if(value == 1){
return "正常";
}else{
return "禁用状态";
}
}},
{field:"regDate",title:"regDate",width:100},
{field:"height",title:"height",width:100}
]],
-----------------
网格可编辑保存数据到数据库中。
- 大概功能代码editor:点击一行,显示可编辑框,上一次点的行处于不可编辑状态
------
columns:[[ //列数组
{field:"ck",checkbox:"true"}, //最左侧有复选框,可供我们选择,
{field:"id",title:"id",width:100},
{field:"stuname",title:"stuname",width:100,editor:{type:"textbox"}},
{field:"password",title:"password",width:100},
{field:"state",title:"state",width:100,formatter:function(value,row,index){
if(value == 1){
return "正常";
}else{
return "禁用状态";
}
},editor:{type:"textbox"}},
{field:"regDate",title:"regDate",width:100,editor:{type:"datebox"}},
{field:"height",title:"height",width:100,editor:{type:"numberbox",options:{precision:2}}},//precision 编辑后保留两位小数
{field:"roles",title:"roles",width:100,formatter:function(value,row,index)
{
//这里只是举例讲,只列一个角色权根
var roleNameStr="";
console.log(value); //[{0...}] [{0...}] [{0...}]从浏览器控制台F12中可以看出value是一个二维数组,而记录都存在第二维的0下标上的一维数组中
if(value !=null && value.length >0)
roleNameStr = value[0].roleName;
return roleNameStr;
},editor:{type:"combobox",options:{url:"/sshwebtest/getRoles",method:"post",valueField:"id",textField:"roleName",required:true,panelHeight:160}
}}
]], //两个中括号,表示二维表格
onClickRow:function(index){ //可编辑行单击事件,此处用于打开可编辑网格功能.index为点击的行索引
if(editIndex !=index){ //默认情况下,点击某一行,它可编辑,但是我们再点一行时,上一点击行仍处于可编辑,这可不好,
$("#dg").datagrid("rejectChanges")
}
$("#dg").datagrid("beginEdit",index);
$("#dg").datagrid("selectRow",index); //选中某一行后,左则的复选框打上勾
editIndex = index;
},
});
var editIndex;
- 编辑后保存到数据库,取消编辑。
1.jsp中添加两个链接按钮
保存
取消
。。。。。。。
2.js中添加两个链接按钮的单击事件
//保存修改的记录
$("#save_stu").click(function(){
//添加到数据库之前,数据有效性检验
//根据editIndex拿到这个row对象
var row = $("#dg").datagrid("getRows")[editIndex];
//根据editIndex,拿到行的编辑器,简单类型的字段,直接获取值,roles是Role对象类型,单独处理
var editor = $("#dg").datagrid("getEditor",{index:editIndex,field:"roles"});
var roleid = $(editor.target).combobox("getValue"); //获取角色的编号
var roletext = $(editor.target).combobox("getText"); //获取角色的描述文本
//让datagrid接受修改,并通ajax发出修改请求
$("#dg").datagrid("acceptChanges");
$.ajax({
url:"/sshwebtest/updateStudent",
method:"post",
//如果说Student对象简单,属性没有复杂的关联性,但我们Student中有set集合role对象,springmvc不能解析,所以必须声明请求的数据类型为json数据格式
contentType:"application/json;charset=utf-8",
//传过去的数据格式,从js的对象格式转化为json格式,stringif()可以将java对象转化为json
data:JSON.stringify({ //以下字段名要与Student对象的成员变量名相同
id:row.id,
stuname:row.stuname,
password:row.password,
state:row.state,
regDate:row.regDate,
height:row.height,
roles:[{id:roleid,roleName:roletext}] //[]表示集合
}),
success:function(rs){ //如呆请求成功,会发回来一个对象rs(rs随便起名,但一定要写在小括号中)
if(rs == "success"){
editIndex = undefined;
$("#dg").datagrid("reload");
}else{
alert("修改失败!");
}
}
})
});
//取消编辑,很简单,只要上的面拒绝修改代码即可
$("#undo_stu").click(function(){
$("#dg").datagrid("rejectChanges");
editIndex = undefined;
})
3.后台响应前台的$.ajx()请求 StuController.java
基Role.java,RoleDao.java RoleDaoImpl.java,RoleService.java,RoleServiceImpl.java见项目 'sshwebtest'
@ResponseBody //返回json格式到网页中
@RequestMapping(value="/updateStudent", method=RequestMethod.POST)
public String updateStudent(@RequestBody Student stu) { //把接收的参数转为json格式数据
stuService.update(stu);
return "success";
}
4.测试:
首先:给表sb_roles写入几个记录,如1-超级管理员 2-一般管理员……。
sb_student_role写入几个记录 1 1,2 1, 即每个学生对应自已的权限
其次:http://localhost/sshwebtest 回车,
image.png
基于权限控制模型实现学生/用户角色与权设置
1权限控制模型
----我们在做任何一款产品的时候,或多或少都会涉及到用户和权限的问题。譬如,做企业类软件,不同部门、不同职位的人的权限是不同的;做论坛类产品的时候,版主和访客权限也是不一样的;再例如一款产品的收费用户和免费用户权限也是迥然不同的。
----我们去参照已有的比较成熟的权限模型:RBAC(Role-Based Access Control)——基于角色的访问控制。以产品经理的角度去解析RBAC模型,并分别举例如何运用这套已得到验证的成熟模型。
-
RBAC模型是什么?
RBAC是一套成熟的权限模型。在传统权限模型中,我们直接把权限赋予用户。而在RBAC中,增加了“角色”的概念,我们首先把权限赋予角色,再把角色赋予用户。这样,由于增加了角色,授权会更加灵活方便。在RBAC中,根据权限的复杂程度,又可分为RBAC0、RBAC1、RBAC2、RBAC3。其中,RBAC0是基础,RBAC1、RBAC2、RBAC3都是以RBAC0为基础的升级。我们可以根据自家产品权限的复杂程度,选取适合的权限模型。
image.png
- 基本模型RBAC0
解析:
RBAC0是基础,很多产品只需基于RBAC0就可以搭建权限模型了。在这个模型中,我们把权限赋予角色,再把角色赋予用户。用户和角色,角色和权限都是多对多的关系。用户拥有的权限等于他所有的角色持有权限之和。
image.png
举例:
譬如我们做一款企业管理产品,如果按传统权限模型,给每一个用户赋予权限则会非常麻烦,并且做不到批量修改用户权限。这时候,可以抽象出几个角色,譬如销售经理、财务经理、市场经理等,然后把权限分配给这些角色,再把角色赋予用户。这样无论是分配权限还是以后的修改权限,只需要修改用户和角色的关系,或角色和权限的关系即可,更加灵活方便。此外,如果一个用户有多个角色,譬如王先生既负责销售部也负责市场部,那么可以给王先生赋予两个角色,即销售经理+市场经理,这样他就拥有这两个角色的所有权限
- 角色分层模型RBAC1
解析:
RBAC1建立在RBAC0基础之上,在角色中引入了继承的概念。简单理解就是,给角色可以分成几个等级,每个等级权限不同,从而实现更细粒度的权限管理。
image.png
举例:
基于之前RBAC0的例子,我们又发现一个公司的销售经理可能是分几个等级的,譬如除了销售经理,还有销售副经理,而销售副经理只有销售经理的部分权限。这时候,我们就可以采用RBAC1的分级模型,把销售经理这个角色分成多个等级,给销售副经理赋予较低的等级即可。
- 角色限制模型RBAC2
解析:
RBAC2同样建立在RBAC0基础之上,仅是对用户、角色和权限三者之间增加了一些限制。这些限制可以分成两类,即静态职责分离SSD(Static Separation of Duty)和动态职责分离DSD(Dynamic Separation of Duty)。具体限制如下图:
image.png
举例:
还是基于之前RBAC0的例子,我们又发现有些角色之间是需要互斥的,譬如给一个用户分配了销售经理的角色,就不能给他再赋予财务经理的角色了,否则他即可以录入合同又能自己审核合同;再譬如,有些公司对角色的升级十分看重,一个销售员要想升级到销售经理,必须先升级到销售主管,这时候就要采用先决条件限制了。
- 基于RBAC的延展——用户组
解析:
基于RBAC模型,还可以适当延展,使其更适合我们的产品。譬如增加用户组概念,直接给用户组分配角色,再把用户加入用户组。这样用户除了拥有自身的权限外,还拥有了所属用户组的所有权限。
举例:
譬如,我们可以把一个部门看成一个用户组,如销售部,财务部,再给这个部门直接赋予角色,使部门拥有部门权限,这样这个部门的所有用户都有了部门权限。用户组概念可以更方便的给群体用户授权,且不影响用户本来就拥有的角色权限。
2基于角色和资源的用户权限控制(用SpringMVC实现)
1.准备工作
新建数据库sshwebe:
image.png
建立数据表(由hibernate 对应模型类的映射文件自动建立各表与关系表)
通常,我们会混合使用上述的几种方式。其中,基于角色和资源是目前较为常见的一种实现,一般会有以下几张表:
用户表/学生表(users/t_students):id、用户名、密码、状态(是否可用,下同)
角色表(sb_roles):id、角色名、角色状态
权限表(sb_permissions):id、权限名、权限状态
除了这三张表外,还要两张表来将三者关联起来:
用户角色关联表(sb_students_roles):用户id、角色id(复合主键)
角色权限关联表(sb_roles_permissions):角色id、权限id(复合主键)
然后,我们在相应的controller中通过 annotation,或者在XML中定义相应的permission即可。
注:如果你不想自己实现,可以直接用Spring Security、Shiro等第三方安全框架,只要参照其规范建立几张表,进行一下配置即可。如果要自己实现也不难,这种权限控制模型,有点久是简单,缺点就是,角色被写死在数据库里,修改角色要修改数据库和源码,麻烦,所以使用与角色固定的中小系统,下面我们就通
过过滤器来实现。
初始化表记录:让程序一发布有一个超级管理员
1.学生:stuname:admin,password:admin123,state:1,regDate:2021-10-19
2.角色:roleName:超级管理员,state:1
3.学生-角色表:stu_id:1,roleId:1
建立各模型类
Student,Role,Permission类,Student类前面已有,只是改下:Student中把height字段删除,重新生成get,set和toString方法。
---再生成各自的dao,service层的接口与接口实现类,接口继承BaseDao,BaseService接口。实现类继承(extends)BaseDaoImpl,BaseServiceImpl,执行(implements)各自接口。
Role类:增加关联多对多单向权限类Permission,映射表中Role.hbm.xml,加如下内容。
------------------------------------------------------------------Role.java-----------------------------------------------------------
public class Role {
private int id;
private String roleName;
private Integer state; //0:表示禁 用,1:表示正常
private Set permissions;
get,set,toString()等方法;//右击文件内容处,source---generate....
}
-----------------------------------Role.hbm.xml--------------------------------------------------------------------------------------
Permission类:
public class Permission {
private int id;
private String resources; //这相权限能访问的资源
private Integer state; //状态0:表示禁用,1:表示正常
set,get,toString()方法。。。。
}
步1:”建立login.jsp文件,并实现http://localhost/项目名/login进行登陆页
1.从别处搞来的样式文件,login.css,login.jsp标签
如图所示它们的存放位置。
image.png
2.控制类中,设置返回login.jsp页。
image.png
image.png
步2:建立登录后的主页main.jsp 主要用于-用户管理--角色管理---权限管理
main.js主要作用是点击左侧的菜单,会在中心区面板上(easyui-tabs选项卡面板)添加选项是同菜单一样的选项。
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
熊少文管理后台
------------------------------------------------------------------main.js-----------------------------------------
$(function(){
$(".sshweb_side_tree li a").bind("click",function(){
var title = $(this).text();
var iconCls = $(this).attr("data-icon");
var url = $(this).attr("data-link");
var iframe = $(this).attr("iframe")==1?true:false;
addTab(title,url,iconCls,iframe);
});
});
function addTab(title,url,iconCls,iframe){
var tabPanel = $("#sshweb_tabs");
if(!tabPanel.tabs("exists",title)){
var content = "";
if(iframe){
tabPanel.tabs("add",{
title:title,
content:content, //
其中main.jsp中左侧栏,分对对应,用户管理,角色管理,权限管理 折叠面板--〉树节点
1
步3:建立三张视图 student_manager.jsp,role_manager.jsp,permission_manager.jsp
它们分别用于,操作‘用户管理’,‘角色管理’,‘权限管理’
它们(jsp文件)不是通过浏览器调用(如http://localhost/sshwebtest/student_manager.jsp)之打开的,而是通过 StuController.java,RoleController.java,PermissionController.java中的方法返回视图给main.jsp对应的选项卡面板中的。这里举两个说明返回视图的两种方法,
1.