zoukankan      html  css  js  c++  java
  • sshe源码分析——权限管理的后台部分

     

    数据库结构:

    wpsEACA.tmp 

    用户跟组织:多对对

     

    用户跟角色:多对多

     

    组织:有上级组织

     

    wpsEACB.tmp 

    资源跟组织:多对多

     

    资源跟角色:多对多

     

    资源:有上级资源

     

    资源:有资源类型

     

     

     

    BaseDaoImpl中用了Hibernate原生的session

     

     

    @Repository

    public class BaseDaoImpl<T> implements BaseDaoI<T> {

     

        @Autowired

        private SessionFactory sessionFactory;

     

        /**

         * 获得当前事物的session

         *

         * @return org.hibernate.Session

         */

        public Session getCurrentSession() {

    return sessionFactory.getCurrentSession();

    }

        @Override

        public T getByHql(String hql) {

    Query q = getCurrentSession().createQuery(hql);

    List<T> l = q.list();

    if (l != null && l.size() > 0) {

        return l.get(0);

    }

    return null;

        }

        @Override

        public T getByHql(String hql, Map<String, Object> params) {

    Query q = getCurrentSession().createQuery(hql);

    if (params != null && !params.isEmpty()) {

        for (String key : params.keySet()) {

    q.setParameter(key, params.get(key));

        }

    }

    List<T> l = q.list();

    if (l != null && l.size() > 0) {

        return l.get(0);

    }

    return null;

        }

     @Override

        public Long count(String hql) {

    Query q = getCurrentSession().createQuery(hql);

    return (Long) q.uniqueResult();

        }

       @Override

        public List<Map> findBySql(String sql) {

    SQLQuery q = getCurrentSession().createSQLQuery(sql);

    return q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();

        }

     

     

     

     

     

    BaseServiceImpl中有对泛型的处理:

    @Service

    public class BaseServiceImpl<T> implements BaseServiceI<T> {

     

        @Autowired

    private BaseDaoI<T> baseDao;

       @Override

        public T getById(Serializable id) {

    Class<T> c = (Class<T>) ((ParameterizedType) getClass()

    .getGenericSuperclass()).getActualTypeArguments()[0];

    return baseDao.getById(c, id);

        }

        @Override

        public T getByFilter(HqlFilter hqlFilter) {

    String className = ((Class<T>) ((ParameterizedType) getClass()

    .getGenericSuperclass()).getActualTypeArguments()[0]).getName();

    String hql = "select distinct t from " + className + " t";

    return getByHql(hql + hqlFilter.getWhereAndOrderHql(),

    hqlFilter.getParams());

        }

     @Override

        public Long countByFilter(HqlFilter hqlFilter) {

    String className = ((Class<T>) ((ParameterizedType) getClass()

    .getGenericSuperclass()).getActualTypeArguments()[0]).getName();

    String hql = "select count(distinct t) from " + className + " t";

    return count(hql + hqlFilter.getWhereHql(), hqlFilter.getParams());

        }

     

     

     

     

    这里有个自定义的HqlFilter用于添加where条件和排序,过滤结果集

     /**

         * 带参构造

         *

         * @param request

         */

        public HqlFilter(HttpServletRequest request) {

    this.request = request;

    addFilter(request);

    }

        /**

         * 添加过滤

         *

         * @param request

         */

        public void addFilter(HttpServletRequest request) {

    Enumeration<String> names = request.getParameterNames();

    while (names.hasMoreElements()) {

        String name = names.nextElement();

        String value = request.getParameter(name);

        addFilter(name, value);

    }

        }

     

        /**

         * 添加过滤

         *

         * 举例,name传递:QUERY_t#id_S_EQ

         *

         * 举例,value传递:0

         *

         * @param params

         */

        public void addFilter(String name, String value) {

    if (name != null && value != null) {

        if (name.startsWith("QUERY_")) {// 如果有需要过滤的字段

    String[] filterParams = StringUtils.split(name, "_");

    if (filterParams.length == 4) {

        String columnName = filterParams[1].replaceAll("#", ".");// 要过滤的字段名称=t.id

        String columnType = filterParams[2];// 字段类型=S

        String operator = filterParams[3];// SQL操作符=EQ

        String placeholder = UUID.randomUUID().toString().replace("-", "");// 生成一个随机的参数名称

     

        if (hql.toString().indexOf(" where 1=1") < 0) {

    hql.append("  where 1=1 ");

        }

     

        hql.append(" and " + columnName + " " + getSqlOperator(operator) + " :param"

        + placeholder + " ");// 拼HQL

        params.put("param" + placeholder, getObjValue(columnType, operator, value));// 添加参数

    }

        }

    }

        }

    上面这个方法把 request里的参数全部映射,并且把 QUERY_t#id_S_EQ 拼成HQL

    Where 1=1 and t.id =:paramXXX

    然后准备好paramXXX的参数替换

     

    其中操作符operator 是自定义的,包括EQ,NE,LK等,表示=,!=,like

     

    参数替换时的columnType也是自定义的,包括S,I,D等,表示String,Integer,Date

    String的时候如果是like,还要动态组合两边的 %

     

     /**

         * 获得添加过滤字段后加上排序字段的HQL

         *

         * @return

         */

        public String getWhereAndOrderHql() {

    if (!StringUtils.isBlank(sort) && !StringUtils.isBlank(order)) {

        if (sort.indexOf(".") < 1) {

    sort = "t." + sort;

        }

        hql.append(" order by " + sort + " " + order + " ");// 添加排序信息

    } else {

        if (request != null) {

    String s = request.getParameter("sort");

    String o = request.getParameter("order");

    if (!StringUtils.isBlank(s)) {

        sort = s;

    }

    if (!StringUtils.isBlank(o)) {

        order = o;

    }

    if (!StringUtils.isBlank(sort) && !StringUtils.isBlank(order)) {

        if (sort.indexOf(".") < 1) {

    sort = "t." + sort;

        }

        hql.append(" order by " + sort + " " + order + " ");// 添加排序信息

    }

        }

    }

    return hql.toString();

        }

     

    这样就把Action里的参数完全转换成了HQL

     

     

    SyuserServiceImpl中:

     

        @Override

        public void grantRole(String id, String roleIds) {

    Syuser user = getById(id);

    if (user != null) {

        user.setSyroles(new HashSet<Syrole>());

        for (String roleId : roleIds.split(",")) {

    if (!StringUtils.isBlank(roleId)) {

        Syrole role = roleDao.getById(Syrole.class, roleId);

        if (role != null) {

    user.getSyroles().add(role);

        }

    }

        }

    }

        }

     

        @Override

        public void grantOrganization(String id, String organizationIds) {

    Syuser user = getById(id);

    if (user != null) {

        user.setSyorganizations(new HashSet<Syorganization>());

        for (String organizationId : organizationIds.split(",")) {

    if (!StringUtils.isBlank(organizationId)) {

        Syorganization organization = organizationDao.getById(

        Syorganization.class, organizationId);

        if (organization != null) {

    user.getSyorganizations().add(organization);

        }

    }

        }

    }

        }

     

    SyroleServiceImpl中:

      @Override

        public void saveRole(Syrole syrole, String userId) {

    save(syrole);

     

    Syuser user = userDao.getById(Syuser.class, userId);

    user.getSyroles().add(syrole);// 把新添加的角色与当前用户关联

        }

     

    SyorganizationServiceImpl中:

     @Override

        public void saveOrganization(Syorganization syorganization, String userId) {

    save(syorganization);

     

    Syuser user = userDao.getById(Syuser.class, userId);

    user.getSyorganizations().add(syorganization);

        }

     

     

    Model中:

    Syuser

     

        @ManyToMany(fetch = FetchType.LAZY)

        @JoinTable(name = "SYUSER_SYORGANIZATION", schema = "", joinColumns = { @JoinColumn(name = "SYUSER_ID", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "SYORGANIZATION_ID", nullable = false, updatable = false) })

        public Set<Syorganization> getSyorganizations() {

    return this.syorganizations;

        }

     

        public void setSyorganizations(Set<Syorganization> syorganizations) {

    this.syorganizations = syorganizations;

        }

     

        @ManyToMany(fetch = FetchType.LAZY)

        @JoinTable(name = "SYUSER_SYROLE", schema = "", joinColumns = { @JoinColumn(name = "SYUSER_ID", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "SYROLE_ID", nullable = false, updatable = false) })

        public Set<Syrole> getSyroles() {

    return this.syroles;

        }

     

        public void setSyroles(Set<Syrole> syroles) {

    this.syroles = syroles;

        }

     

    Syrole

     

        @ManyToMany(fetch = FetchType.LAZY)

        @JoinTable(name = "SYUSER_SYROLE", schema = "", joinColumns = { @JoinColumn(name = "SYROLE_ID", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "SYUSER_ID", nullable = false, updatable = false) })

        public Set<Syuser> getSyusers() {

    return this.syusers;

        }

     

        public void setSyusers(Set<Syuser> syusers) {

    this.syusers = syusers;

        }

     

    Syorganization

     

        @OneToMany(fetch = FetchType.LAZY, mappedBy = "syorganization", cascade = CascadeType.ALL)

        public Set<Syorganization> getSyorganizations() {

    return this.syorganizations;

        }

     

        public void setSyorganizations(Set<Syorganization> syorganizations) {

    this.syorganizations = syorganizations;

        }

     

        @ManyToMany(fetch = FetchType.LAZY)

        @JoinTable(name = "SYUSER_SYORGANIZATION", schema = "", joinColumns = { @JoinColumn(name = "SYORGANIZATION_ID", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "SYUSER_ID", nullable = false, updatable = false) })

        public Set<Syuser> getSyusers() {

    return this.syusers;

        }

     

        public void setSyusers(Set<Syuser> syusers) {

    this.syusers = syusers;

        }

     

     

     

    这样,权限相关的后台部分就结束了,效果如下:

     

    1.点击登陆,会首先获取菜单((SyresourceServiceI) service).getMainMenu(

    wpsEAEB.tmp 

    先查角色的:

    select distinct t from Syresource t join t.syroles role join role.syusers user  where 1=1  and user.id  =  :param49bd757c16594cbe8657b7d88364d81a  and t.syresourcetype.id  =  :paramf778a1257fa64e9ebca2a52bcc9750fc

    再查组织的:

    select distinct t from Syresource t join t.syorganizations organization join organization.syusers user  where 1=1  and user.id  =  :param49bd757c16594cbe8657b7d88364d81a  and t.syresourcetype.id  =  :paramf778a1257fa64e9ebca2a52bcc9750fc

     

    2.点击用户管理菜单,会通过SecurityUtil查询权限,并动态显示某些功能图标

    因为登陆时已经对该用户所有资源都强制加载了,这时候不再查数据库

    也就是每次更改了权限后需要重新登陆

     

    3.点击某个用户的用户角色:

    wpsEAFC.tmp 

     

    首先调用user.getSyroles()得到当前用户所有角色:当然这里是错的,应该跟用户无关,查询所有角色

    Initializing collection [sy.model.base.Syuser.syroles#0]

    SELECT

    syroles0_.SYUSER_ID AS SYUSER1_7_1_,

    syroles0_.SYROLE_ID AS SYROLE2_9_1_,

    syrole1_.ID AS ID1_5_0_,

    syrole1_.CREATEDATETIME AS CREATEDA2_5_0_,

    syrole1_.DESCRIPTION AS DESCRIPT3_5_0_,

    syrole1_.ICONCLS AS ICONCLS4_5_0_,

    syrole1_. NAME AS NAME5_5_0_,

    syrole1_.SEQ AS SEQ6_5_0_,

    syrole1_.UPDATEDATETIME AS UPDATEDA7_5_0_

    FROM

    SYUSER_SYROLE syroles0_

    INNER JOIN SYROLE syrole1_ ON syroles0_.SYROLE_ID = syrole1_.ID

    WHERE

    syroles0_.SYUSER_ID = '0'

    Collection initialized

     

    这里为什么又查一遍数据库??

    登陆时不是全都初始化过了??

     

    然后得到所选用户的所有角色,并在页面上勾选:

    wpsEAFD.tmp 

    select distinct t from Syrole t join t.syusers user  where 1=1  and user.id  =  :paramdac50de702204cc6a258b8af78905a65

     

    另外虽然数据库中的多对多并没有方向性,但页面上并不提供双向查询

    这里的顺序是:用户->角色/组织->资源

     

    通过后台可以发现,Hibernate总是有不必要的Sql执行,实际项目中肯定要最后优化一遍

     

    http://www.cnblogs.com/gcg0036/p/4393526.html

  • 相关阅读:
    c语言提高学习笔记——02-c提高07day
    c语言提高学习笔记——02-c提高06day
    c语言提高学习笔记——02-c提高05day
    c语言提高学习笔记——02-c提高04day
    c语言提高学习笔记——02-c提高03day
    菜鸡的 分块 刷题记录
    是输入输出的小技巧和细节们
    蒟蒻的 线性基 刷题记录
    曼哈顿距离,欧几里得距离学习笔记
    用 Github.io 和 Hexo 创建你的第一个博客
  • 原文地址:https://www.cnblogs.com/gcg0036/p/4393526.html
Copyright © 2011-2022 走看看