你的位置:首页 > Java教程

[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