SSH物流开发系统设计:权限认证实现

一、权限认证框架Shiro

系统提供了很多功能,并不是所有的用户登录系统都可以操作这些功能。我们需要对用户的访问进行控制。
认证:系统提供的用于识别用户身份的功能(通常是登录功能)—–让系统知道你是谁??
授权:系统提供的赋予用户访问某个功能的能力—–让系统知道你能做什么??
这里使用Shiro来进行权限认证,关于Shiro的介绍和使用请参考这里。点我

二、将shiro应用到bos项目

第一步:导入shiro-all.jar
第二步:在web.xml中配置一个spring用于整合shiro的过滤器

  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

第三步:在spring配置文件中配置一个bean,id必须和上面的过滤器名称相同

<!-- 配置一个工厂bean,用于创建shiro框架用到过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 注入安全管理器 -->
        <property name="securityManager" ref="securityManager"></property>
        <!-- 注入当前系统的登录页面 -->
        <property name="loginUrl" value="/login.jsp"/>
        <!-- 注入成功页面 -->
        <property name="successUrl" value="/index.jsp"/>
        <!-- 注入权限不足提示页面 -->
        <property name="unauthorizedUrl" value="/unauthorizedUrl.jsp"/>
        <!-- 注入URL拦截规则 -->
        <property name="filterChainDefinitions">
            <value>
                /css/** = anon
                /images/** = anon
                /js/** = anon
                /login.jsp* = anon
                /validatecode.jsp* = anon
                /userAction_login.action = anon
                /page_base_staff.action = perms["staff"]
                /* = authc
            </value>
        </property>
    </bean>

第四步:在spring配置文件中注册安全管理器,为安全管理器注入realm

<!-- 注册自定义realm -->
    <bean id="bosRealm" class="com.crm.bos.shiro.BOSRealm"></bean>

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- 注入上面的realm -->
        <property name="realm" ref="bosRealm"/>
    </bean>

第五步:自定义一个BOSRealm

public class BOSRealm extends AuthorizingRealm {
    @Resource
    private IUserDao userDao;
    /**
     * 认证方法
     */
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        System.out.println("认证方法。。。");
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();// 从令牌中获得用户名

        User user = userDao.findUserByUsername(username);
        if (user == null) {
            // 用户名不存在
            return null;
        } else {
            // 用户名存在
            String password = user.getPassword();// 获得数据库中存储的密码
            // 创建简单认证信息对象
            /***
             * 参数一:签名,程序可以在任意位置获取当前放入的对象
             * 参数二:从数据库中查询出的密码
             * 参数三:当前realm的名称
             */
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,
                    password, this.getClass().getSimpleName());
            return info;//返回给安全管理器,由安全管理器负责比对数据库中查询出的密码和页面提交的密码
        }
    }
    /**
     * 授权方法
     */
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        return null;
    }
}

第六步:完善UserAction的login方法

public String login(){
        //生成的验证码
        String key = (String) ServletActionContext.getRequest().getSession().getAttribute("key");
        //判断用户输入的验证码是否正确
        if(StringUtils.isNotBlank(checkcode) && checkcode.equals(key)){
            //验证码正确
            //获得当前用户对象
            Subject subject = SecurityUtils.getSubject();//状态为“未认证”
            String password = model.getPassword();
            password = MD5Utils.md5(password);
            //构造一个用户名密码令牌
            AuthenticationToken token = new UsernamePasswordToken(model.getUsername(), password);
            try{
                subject.login(token);
            }catch (UnknownAccountException e) {
                e.printStackTrace();
                //设置错误信息
                this.addActionError(this.getText("usernamenotfound"));
                return "login";
            }catch (Exception e) {
                e.printStackTrace();
                //设置错误信息
                this.addActionError(this.getText("loginError"));
                return "login";
            }
            //获取认证信息对象中存储的User对象
            User user = (User) subject.getPrincipal();
            ServletActionContext.getRequest().getSession().setAttribute("loginUser", user);
            return "home";
        }else{
            //验证码错误,设置错误提示信息,跳转到登录页面
            this.addActionError(this.getText("validateCodeError"));
            return "login";
        }
    }

第七步:在自定义Realm中编写授权方法

    /**
     * 授权方法
     */
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //根据当前登录用户查询其对应的权限,授权
        User user = (User) principals.getPrimaryPrincipal();
        List<Function> list = null;
        if(user.getUsername().equals("admin")){
            //当前用户是超级管理员,查询所有权限,为用户授权
            list = functionDao.findAll();
        }else{
            //普通用户,根据用户id查询对应的权限
            list = functionDao.findListByUserid(user.getId());
        }
        for (Function function : list) {
            info.addStringPermission(function.getCode());
        }
        return info;
    }

三、shiro提供的权限控制方式

1、URL拦截权限控制

<!-- 注入URL拦截规则 -->
        <property name="filterChainDefinitions">
            <value>
                /css/** = anon
                /images/** = anon
                /js/** = anon
                /login.jsp* = anon
                /validatecode.jsp* = anon
                /userAction_login.action = anon
                /page_base_staff.action = perms["staff"]
                /* = authc
            </value>
        </property>

2、方法注解权限控制
第一步:在spring配置文件中开启shiro的注解支持

<!-- 开启shiro注解 -->
    <!-- 自动代理 -->
    <bean id="defaultAdvisorAutoProxyCreator" 
        class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        <!-- 强制使用cglib为Action创建代理对象 -->
        <property name="proxyTargetClass" value="true"></property>
    </bean>
    <!-- 切面类 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>

第二步:在Action的方法上使用shiro的注解描述执行当前方法需要具有的权限。

/**
     * 批量删除功能(逻辑删除)
     * @return
     */
    @RequiresPermissions(value="staff")//执行当前方法需要具有staff权限
    @RequiresRoles(value="abc")
    public String delete(){
        staffService.deleteBatch(ids);
        return "list";
    }

第三步:修改BaseAction的构造方法,判断是否为代理对象。

public BaseAction() {
        ParameterizedType genericSuperclass = null;

        if(this.getClass().getGenericSuperclass() instanceof ParameterizedType){
            genericSuperclass = (ParameterizedType) this
            .getClass().getGenericSuperclass();
        }else{//当前为Action创建了代理
            genericSuperclass = (ParameterizedType) this.getClass().getSuperclass().getGenericSuperclass();
        }

第四步:在struts.xml中配置全局异常捕获,统一跳转到权限不足的页面

<!-- 全局异常捕获 -->
        <global-exception-mappings>
            <exception-mapping result="unauthorizedUrl"
                exception="org.apache.shiro.authz.AuthorizationException"></exception-mapping>
        </global-exception-mappings>

四、实现权限认证

初始化权限数据

执行sql脚本文件初始化权限数据:

INSERT INTO `auth_function` VALUES ('11', '基础档案', 'jichudangan', null, null, '1', '0', null);
INSERT INTO `auth_function` VALUES ('112', '收派标准', 'standard', null, 'page_base_standard.action', '1', '1', '11');
INSERT INTO `auth_function` VALUES ('113', '取派员设置', 'staff', null, 'page_base_staff.action', '1', '2', '11');
INSERT INTO `auth_function` VALUES ('114', '区域设置', 'region', null, 'page_base_region.action', '1', '3', '11');
INSERT INTO `auth_function` VALUES ('115', '管理分区', 'subarea', null, 'page_base_subarea.action', '1', '4', '11');
INSERT INTO `auth_function` VALUES ('116', '管理定区/调度排班', 'decidedzone', null, 'page_base_decidedzone.action', '1', '5', '11');
INSERT INTO `auth_function` VALUES ('12', '受理', 'shouli', null, null, '1', '1', null);
INSERT INTO `auth_function` VALUES ('121', '业务受理', 'noticebill', null, 'page_qupai_noticebill_add.action', '1', '0', '12');
INSERT INTO `auth_function` VALUES ('122', '工作单快速录入', 'quickworkordermanage', null, 'page_qupai_quickworkorder.action', '1', '1', '12');
INSERT INTO `auth_function` VALUES ('124', '工作单导入', 'workordermanageimport', null, 'page_qupai_workorderimport.action', '1', '3', '12');
INSERT INTO `auth_function` VALUES ('13', '调度', 'diaodu', null, null, '1', '2', null);
INSERT INTO `auth_function` VALUES ('131', '查台转单', 'changestaff', null, null, '1', '0', '13');
INSERT INTO `auth_function` VALUES ('132', '人工调度', 'personalassign', null, 'page_qupai_diaodu.action', '1', '1', '13');
INSERT INTO `auth_function` VALUES ('14', '物流配送流程管理', 'zhongzhuan', null, null, '1', '3', null);
INSERT INTO `auth_function` VALUES ('141', '启动配送流程', 'start', null, 'workOrderManageAction_list.action', '1', '0', '14');
INSERT INTO `auth_function` VALUES ('142', '查看个人任务', 'personaltask', null, 'taskAction_findPersonalTask.action', '1', '1', '14');
INSERT INTO `auth_function` VALUES ('143', '查看我的组任务', 'grouptask', null, 'taskAction_findGroupTask.action', '1', '2', '14');

权限分页查询

第一步:修改页面中datagrid的URL地址,访问FunctionAction的pageQuery的分页查询方法。

pageList: [10,20,30],
            pagination : true,
            url : '${pageContext.request.contextPath}/functionAction_pageQuery.action',
            columns : [[
              {
                  field : 'id',
                  title : '编号',
                  width : 200
              },
              {
                  field : 'name',
                  title : '名称',
                  width : 200
              },  
              {
                  field : 'description',
                  title : '描述',
                  width : 50
              },  
              {
                  field : 'generatemenu',
                  title : '是否生成菜单',
                  width : 200,
                  formatter:function(data){
                      if(data == '1'){
                          return "是";
                      }else{
                          return "否";
                      }
                  }
              },  
              {
                  field : 'zindex',
                  title : '优先级',
                  width : 200
              },  
              {
                  field : 'page',
                  title : '路径',
                  width : 200
              }
            ]]

第二步:创建FunctionAction

@Controller
@Scope("prototype")
public class FunctionAction extends BaseAction<Function> {

    public String pageQuery() {
        pageBean.setCurrentPage(Integer.parseInt(model.getPage()));//赋给分页数据,否则这个page参数会赋给Function中的page属性
        functionService.pageQuery(pageBean);
        String[] excludes = new String[] { "function", "functions", "roles", "detachedCriteria"};
        this.writePageBean2Json(pageBean, excludes);
        return NONE;
    }

第三步:配置struts.xml

<!-- 权限管理Action -->
        <action name="functionAction_*" class="functionAction" method="{1}">
            <result name="list">/WEB-INF/pages/admin/function.jsp</result>
        </action>

权限添加功能

第一步:修改添加页面中的combobox的URL地址,查询所有的权限,展示到下拉框中

<form id="functionForm" method="post" action="${pageContext.request.contextPath }/functionAction_add.action">
                <table class="table-edit" width="80%" align="center">
                    <tr class="title">
                        <td colspan="2">功能权限信息</td>
                    </tr>
                    <tr>
                        <td width="200">权限关键字</td>
                        <td>
                            <input type="text" name="code" class="easyui-validatebox" data-options="required:true" />                       
                        </td>
                    </tr>
                    <tr>
                        <td>名称</td>
                        <td><input type="text" name="name" class="easyui-validatebox" data-options="required:true" /></td>
                    </tr>
                    <tr>
                        <td>访问路径</td>
                        <td><input type="text" name="page"  /></td>
                    </tr>
                    <tr>
                        <td>是否生成菜单</td>
                        <td>
                            <select name="generatemenu" class="easyui-combobox">
                                <option value="0">不生成</option>
                                <option value="1">生成</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>优先级</td>
                        <td>
                            <input type="text" name="zindex" class="easyui-numberbox" data-options="required:true" />
                        </td>
                    </tr>
                    <tr>
                        <td>父功能点</td>
                        <td>
                            <input name="function.id" class="easyui-combobox" data-options="valueField:'id',textField:'name',
                            url:'${pageContext.request.contextPath }/functionAction_listajax.action'"/>
                        </td>
                    </tr>
                    <tr>
                        <td>描述</td>
                        <td>
                            <textarea name="description" rows="4" cols="60"></textarea>
                        </td>
                    </tr>
                    </table>
            </form>

第二步:在FunctionAction中提供listajax方法

public String listajax() throws IOException{
        List<Function> list=functionService.findAll();
        String[] excludes=new String[]{"function", "functions", "roles"};
        this.writeList2Json(list, excludes);
        return NONE;
    }

第三步:为保存按钮绑定事件提交表单

<script type="text/javascript">
    $(function(){
        // 点击保存
        $('#save').click(function(){
            var v = $("#functionForm").form("validate");
            if(v){
                $("#functionForm").submit();
            }
        });
    });

第四步:在Action中提供add方法,保存一个权限数据

 public String add(){
        functionService.save(model);
        return "list";
    }

Service代码:

public void save(Function model) {
        //需要判断传过来的pid是否是空串,若为空串则将其赋值为null,否则无法插入mysql中
        Function parent = model.getFunction();
        if(parent!=null && parent.getId()!=null&&parent.getId().equals("")){
            model.setFunction(null);
        }
        functionDao.save(model);
    }

角色管理(关联权限)

1、 添加角色(为角色授权)

1.1. 授权树的编写
显示授权树,根据auth_function 表查询,返回json数据

<script type="text/javascript">
    $(function(){
        // 授权树初始化
        var setting = {
            data : {
                key : {
                    title : "t"
                },
                simpleData : {
                    enable : true
                }
            },
            check : {
                enable : true, //选中效果
            }
        };

        $.ajax({
            url : '${pageContext.request.contextPath}/functionAction_listajax.action',
            type : 'POST',
            dataType : 'json',
            success : function(data) {
                $.fn.zTree.init($("#functionTree"), setting, data);
            },
            error : function(msg) {
                alert('树加载异常!');
            }
        });

服务器返回 ztree节点数据,应该包含 id、name、parentId !
在FunctionAction 添加treedata的方法

public String listajax() throws IOException{
        List<Function> list=functionService.findAll();
        String[] excludes=new String[]{"function", "functions", "roles"};
        this.writeList2Json(list, excludes);
        return NONE;
    }

在Function 实体类 添加getParentId 方法

public String getpId() {//注意getpId中的“p”是小写,因为“I”是大写
        if(function != null){
            return function.getId();
        }else{
            return "0";
        }
    }

1.2. 提交添加角色表单

// 点击保存
        $('#save').click(function(){
            var v = $("#roleForm").form("validate");
            if(v){
                var treeObj = $.fn.zTree.getZTreeObj("functionTree");//获得页面中的ztree对象
                var nodes = treeObj.getCheckedNodes(true);//在提交表单之前将选中的checkbox收集
                var array = new Array();
                for(var i=0;i<nodes.length;i++){
                    var id = nodes[i].id;//权限id
                    array.push(id);
                }
                var ids = array.join(",");//1,2,3,4,5
                $("input[name=ids]").val(ids);
                //alert();
                $("#roleForm").submit();
            }
        });

编写服务器 RoleAction

@Controller
@Scope("prototype")
public class RoleAction extends BaseAction<Role>{

    private String ids;//用来接受权限的id值
    public String add(){
        roleService.save(model,ids);
        return "list";
    }
    public void setIds(String ids) {
        this.ids = ids;
    }

将DAO 注入 BaseService
将Service 注入BaseAction
添加角色业务代码service层:

public void save(Role model, String ids) {
        roleDao.save(model);//变为持久对象

        Group group=new GroupEntity(model.getName());
        identityService.saveGroup(group);//将角色数据同步到actitviti的数据表中

        String[] functionIds = ids.split(",");
        for (String fid : functionIds) {
            Function function=new Function();
            function.setId(fid);//托管状态,建立关联时必须是持久类关联托管类
            model.getFunctions().add(function);//角色和权限建立关联
        }
    }

配置跳转

<!-- 角色管理 -->
        <action name="roleAction_*" class="roleAction" method="{1}">
            <result name="list">/WEB-INF/pages/admin/role.jsp</result>
        </action>

4.2. 角色列表查询
/WEB-INF/pages/admin/role.jsp 修改 datagrid 的url

pageList: [10,20,30],
            pagination : true,
            url : '${pageContext.request.contextPath}/roleAction_pageQuery.action',
            columns : [[
                {
                    field : 'id',
                    title : '编号',
                    width : 230
                },
                {
                    field : 'name',
                    title : '名称',
                    width : 200
                }, 
                {
                    field : 'description',
                    title : '描述',
                    width : 200
                } 
            ]]

在服务器 RoleAction 添加方法

public String pageQuery(){
        roleService.pageQuery(pageBean);
        String[] excludes=new String[]{"functions","users"};
        this.writePageBean2Json(pageBean, excludes);
        return NONE;
    }

用户管理(关联角色)

1、 添加用户
pojo类

package com.crm.bos.domain;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * User entity. @author MyEclipse Persistence Tools
 */

public class User implements java.io.Serializable {

    // Fields

    private String id;
    private String username;
    private String password;
    private Double salary;
    private Date birthday;
    private String gender;// 1表示男,2表示女
    private String station;
    private String telephone;
    private String remark;
    private Set<Noticebill> noticebills = new HashSet<Noticebill>();
    private Set<Role> roles = new HashSet<Role>();

    public String getFormateBirthday() {
        if (birthday != null) {
            return new SimpleDateFormat("yyyy-MM-dd").format(birthday);
        } else {
            return "未提交生日";
        }
    }

    public String getRoleNames() {
        String names = "";
        if (roles != null && roles.size() > 0) {
            for (Role role : roles) {
                names += role.getName() + " ";
            }
        }
        return names;
    }

    // Constructors

    /** default constructor */
    public User() {
    }

    /** minimal constructor */
    public User(String id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    /** full constructor */
    public User(String id, String username, String password, Double salary,
            Date birthday, String gender, String station, String telephone,
            String remark) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.salary = salary;
        this.birthday = birthday;
        this.gender = gender;
        this.station = station;
        this.telephone = telephone;
        this.remark = remark;
    }

    // Property accessors

    public String getId() {
        return this.id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Double getSalary() {
        return this.salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public Date getBirthday() {
        return this.birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getGender() {
        return this.gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getStation() {
        return this.station;
    }

    public void setStation(String station) {
        this.station = station;
    }

    public String getTelephone() {
        return this.telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getRemark() {
        return this.remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public Set<Noticebill> getNoticebills() {
        return noticebills;
    }

    public void setNoticebills(Set<Noticebill> noticebills) {
        this.noticebills = noticebills;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

}

修改 /WEB-INF/pages/admin/userinfo.jsp

 <form id="form" method="post" action="${pageContext.request.contextPath}/userAction_add.action">
           <table class="table-edit"  width="95%" align="center">
                <tr class="title"><td colspan="4">基本信息</td></tr>
                <tr><td>用户名:</td><td><input type="text" name="username" id="username" class="easyui-validatebox" required="true" /></td>
                    <td>口令:</td><td><input type="password" name="password" id="password" class="easyui-validatebox" required="true" validType="minLength[5]" /></td></tr>
                <tr class="title"><td colspan="4">其他信息</td></tr>
                <tr><td>工资:</td><td><input type="text" name="salary" id="salary" class="easyui-numberbox" /></td>
                    <td>生日:</td><td><input type="text" name="birthday" id="birthday" class="easyui-datebox" /></td></tr>
                <tr><td>性别:</td><td>
                    <select name="gender" id="gender" class="easyui-combobox" style="width: 150px;">
                        <option value="1"></option>
                        <option value="2"></option>
                    </select>
                </td>
                    <td>单位:</td><td>
                    <select name="station" id="station" class="easyui-combobox" style="width: 150px;">
                        <option value="">请选择</option>
                        <option value="总公司">总公司</option>
                        <option value="分公司">分公司</option>
                        <option value="厅点">厅点</option>
                        <option value="基地运转中心">基地运转中心</option>
                        <option value="营业所">营业所</option>
                    </select>
                </td></tr>
                <tr>
                    <td>联系电话</td>
                    <td colspan="3">
                        <input type="text" name="telephone" id="telephone" class="easyui-validatebox" required="true" />
                    </td>
                </tr>
                <tr><td>备注:</td><td colspan="3"><textarea style="width:80%"></textarea></td></tr>
                <tr><td>选择角色:</td>
                    <td colspan="3" id="roleTD">
                        <script type="text/javascript">
                            $(function(){
                                //发送ajax请求,获取所有的角色数据,返回json,在页面中动态构造到checkbox中
                                var url = "${pageContext.request.contextPath}/roleAction_listajax.action";
                                $.post(url,{},function(data){
                                    //解析json数据,构造checkbox
                                    for(var i=0;i<data.length;i++){
                                        var id = data[i].id;
                                        var name = data[i].name;
                                        $("#roleTD").append('<input type="checkbox" value="'+id+'" name="roleIds">'+name);
                                    }
                                });
                            });
                        </script>

                    </td>
               </tr>
           </table>
       </form>

在RoleAction 添加 listajax 方法

public String listajax() throws IOException{
        List<Role> list=roleService.findAll();
        String[] excludes=new String[]{"functions","users"};
        this.writeList2Json(list, excludes);
        return NONE;
    }

点击 保存按钮提交form表单

<script type="text/javascript">
    $(function(){
        $("body").css({visibility:"visible"});
        $('#save').click(function(){
            if($('#form').form("validate")){
                $('#form').submit();
            }
        });
    });
</script>   

在 UserAction 添加 save 方法

private String[] roleIds;//接受页面提交过来的参数

    public String add(){
        userService.save(model,roleIds);
        return "list";
    }

service层代码:

public void save(User model, String[] roleIds) {
        String password = model.getPassword();
        password= MD5Utils.md5(password);//md5加密
        model.setPassword(password);//设置加密后的密码
        userDao.save(model);

        for (String roleId : roleIds) {
            Role role=roleDao.findById(roleId);
            model.getRoles().add(role);
            identityService.createMembership(actUser.getId(), role.getName());//关联角色信息
        }

    }

2、 用户列表查询

/WEB-INF/pages/admin/userlist.jsp
修改 datagrid 的 url

$(function(){
        // 初始化 datagrid
        // 创建grid
        $('#grid').datagrid( {
            iconCls : 'icon-forward',
            fit : true,
            border : false,
            rownumbers : true,
            striped : true,
            toolbar : toolbar,
            url : "${pageContext.request.contextPath}/userAction_pageQuery.action",
            pageList: [3,5,10],
            pagination : true,
            idField : 'id', 
            frozenColumns : frozenColumns,
            columns : columns,
            onClickRow : onClickRow,
            onDblClickRow : doDblClickRow
        });

        $("body").css({visibility:"visible"});

    });

在服务器 UserAction 提供查询方法

public String pageQuery() throws IOException{
        userService.pageQuery(pageBean);
        String[] excludes=new String[]{"noticebills","roles"};
        this.writePageBean2Json(pageBean, excludes);
        return NONE;
    }

五、源码点我

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值