struts2学习之旅三 权限管理和导航设计

1,权限管理的db设计和dao实现,尽量简单快速有效;

db的设计如下:权限按照角色来赋给用户;

struts2学习之旅三 权限管理和导航设计

权限对应每一个具体的功能,有菜单级别的,有导航级别的,还有页面级别的功能;

struts2学习之旅三 权限管理和导航设计

涉及到权限的敏感操作一般都要记录日志,不仅要记录到log里还要记录到远程的db里,以备审计。学习的时候暂时不用,但是为了全面考

虑设计,这里还是加上;

struts2学习之旅三 权限管理和导航设计

表名 建表的sql文,这里使用mysql数据库,因为是学习用的,后面会尝试用jpa去替换现在的dao,做到对db支持的灵活性
dt_role

DROP TABLE IF EXISTS `dt_role`;
CREATE TABLE `dt_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `roleName` varchar(20)   NOT NULL,
  `roleDesc` varchar(100)   DEFAULT NULL,
  `createDate` datetime DEFAULT NULL,
  `flag` tinyint(4) DEFAULT NULL,
  `pid` int(11) DEFAULT NULL,
  `order` int(11) DEFAULT NULL,
  `ext` varchar(120)   DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

dt_permission

DROP TABLE IF EXISTS `dt_permission`;
CREATE TABLE `dt_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `pName` varchar(30) NOT NULL DEFAULT '' COMMENT '权限名称',
  `pDesc` varchar(200) DEFAULT NULL COMMENT '权限描述',
  `pFunctionName` varchar(30) NOT NULL,
  `pid` int(11) DEFAULT NULL COMMENT '父id',
  `pUrl` varchar(200) DEFAULT NULL COMMENT '功能的链接',
  `pLevel` tinyint(4) DEFAULT NULL COMMENT '功能的层级',
  `order` int(11) DEFAULT NULL COMMENT '排序号',
  `ext` varchar(120) DEFAULT NULL,
  `createDate` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

dt_log

DROP TABLE IF EXISTS `dt_log`;
CREATE TABLE `dt_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `userName` varchar(30) DEFAULT NULL COMMENT '用户名',
  `ip` varchar(30) DEFAULT NULL COMMENT 'ip地址',
  `type` tinyint(4) DEFAULT NULL COMMENT '日志类型',
  `content` varchar(200) DEFAULT NULL COMMENT '日志内容',
  `ext1` varchar(120) DEFAULT NULL COMMENT '扩展字段1',
  `ext2` varchar(120) DEFAULT NULL COMMENT '扩展字段2',
  `createDate` datetime DEFAULT NULL COMMENT '创建日期',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

struts2学习之旅三 权限管理和导航设计数据持久层,采用easydb的方式,先写基本的dao;

package com.cutter.web.account.dao.achieve;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List; import org.apache.log4j.Logger;
import org.pureart.persistement.database.easydb.DB;
import org.pureart.persistement.database.easydb.IUStH;
import org.pureart.persistement.database.easydb.ParamReadStH;
import org.pureart.persistement.database.easydb.ReadStH; import com.cutter.web.account.dao.entity.Role;
import com.cutter.web.account.dao.inter.RoleDao;
import com.cutter.web.account.util.StringUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; public class RoleDaoAchieve implements RoleDao { private static final Logger log = Logger.getLogger(RoleDaoAchieve.class); private static final String ROLE_TABLE = " test.dt_role"; private static final String ROLE_SELECT = " SELECT * FROM " + ROLE_TABLE; private static final String ROLE_GET_BY_ID = ROLE_SELECT + " WHERE id=? ;"; private static final String ROLE_DELETE_BY_ID = " DELETE FROM " + ROLE_TABLE + " WHERE id=? ;"; private static final String ROLE_LIST_ALL = ROLE_SELECT + " ORDER BY createDate DESC "; private static final String ROLE_LIST_BY_PAGE = ROLE_LIST_ALL + " limit ?,? ;"; private static final String ROLE_ADD = " INSERT INTO " + ROLE_TABLE
+ " (roleName,roleDesc,flag,pid,order,ext,createDate) VALUES(?,?,?,?,?,?,?);"; private static final String ROLE_UPDATE = " update " + ROLE_TABLE
+ " set roleName=? , roleDesc=? , flag=? , pid=? , order=? , ext=? , createDate=? where id=?"; @Override
public boolean update(final Role entity) { if (null != entity) {
final boolean flag = 0 < entity.getId();
try {
return DB.insertUpdate(flag ? ROLE_UPDATE : ROLE_ADD, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException {
stmt.setString(1, entity.getRoleName());
stmt.setString(2, entity.getRoleDesc());
stmt.setInt(3, entity.getFlag());
stmt.setInt(4, entity.getPid());
stmt.setInt(5, entity.getOrder());
stmt.setString(6, entity.getExt());
stmt.setDate(7, StringUtil.transforFromUtilToSqlDate(entity.getCrateDate()));
if (flag) {
stmt.setInt(8, entity.getId());
}
stmt.executeUpdate();
}
});
} catch (SQLException e) {
log.error("更新角色信息异常!");
e.printStackTrace();
}
}
return false;
} @Override
public Role get(final int id) {
try {
if (0 < id) {
final Role role = new Role(); boolean getResult = DB.select(ROLE_GET_BY_ID, new ParamReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException { if (rs.next()) {
handResult(role, rs); } } @Override
public void setParams(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, id); }
}); if (getResult) {
return role;
}
}
} catch (SQLException e) {
log.error("查询单条角色信息异常!");
e.printStackTrace();
}
return null;
} @Override
public boolean delete(final int id) {
try {
if (0 < id) {
return DB.insertUpdate(ROLE_DELETE_BY_ID, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, id);
stmt.executeUpdate();
}
});
}
} catch (SQLException e) {
log.error("删除单条角色信息异常!");
e.printStackTrace();
}
return false;
} @Override
public boolean batchDelete(final int[] idArray) {
try {
if (null != idArray && 1 < idArray.length) {
return DB.insertUpdate(ROLE_DELETE_BY_ID, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException { for (int i : idArray) {
stmt.setInt(1, i);
stmt.addBatch();
}
stmt.executeBatch();
}
});
}
} catch (SQLException e) {
log.error("批量删除角色信息异常!");
e.printStackTrace();
}
return false;
} @Override
public ImmutableList<Role> listAll() { try {
final List<Role> roleList = Lists.newLinkedList(); boolean listResult = DB.select(ROLE_LIST_ALL, new ReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException { while (rs.next()) {
roleList.add(handResult(new Role(), rs));
}
}
}); if (listResult) {
return ImmutableList.copyOf(roleList);
} } catch (SQLException e) {
log.error("查询全部角色信息异常!");
e.printStackTrace();
} return null;
} @Override
public ImmutableList<Role> list(final int pageSize, final int page) { try { final List<Role> roleLists = Lists.newLinkedList(); boolean listPageResult = DB.select(ROLE_LIST_BY_PAGE, new ParamReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException { while (rs.next()) {
roleLists.add(handResult(new Role(), rs));
} } @Override
public void setParams(PreparedStatement stmt) throws SQLException {
int start = pageSize * (page - 1);
int end = start + pageSize; stmt.setInt(1, start);
stmt.setInt(2, end);
}
}); if (listPageResult) {
return ImmutableList.copyOf(roleLists);
} } catch (SQLException e) {
log.error("分页查询角色信息异常!");
e.printStackTrace();
} return null; } private Role handResult(final Role role, ResultSet rs) throws SQLException { role.setId(rs.getInt("id"));
role.setRoleName(rs.getString("roleName"));
role.setRoleDesc(rs.getString("roleDesc"));
role.setPid(rs.getInt("pid"));
role.setFlag(rs.getInt("flag"));
role.setCrateDate(StringUtil.transforFromSqlToUtilDate(rs.getDate("createDate")));
role.setExt(rs.getString("ext"));
role.setOrder(rs.getInt("order")); return role;
} }
package com.cutter.web.account.dao.achieve;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List; import org.apache.log4j.Logger;
import org.pureart.persistement.database.easydb.DB;
import org.pureart.persistement.database.easydb.IUStH;
import org.pureart.persistement.database.easydb.ParamReadStH;
import org.pureart.persistement.database.easydb.ReadStH; import com.cutter.web.account.dao.entity.Permission;
import com.cutter.web.account.dao.inter.PermissionDao;
import com.cutter.web.account.util.StringUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; public class PermissionDaoAchieve implements PermissionDao { private static final Logger log = Logger.getLogger(PermissionDaoAchieve.class); private static final String PERMISSION_TABLE = " test.dt_permission "; private static final String PERMISSION_SELECT = " SELECT * FROM " + PERMISSION_TABLE; private static final String PERMISSION_GET_BY_ID = PERMISSION_SELECT + " where id=? ;"; private static final String PERMISSION_GET_BY_ROLEID = PERMISSION_SELECT + " where roleId=? ;"; private static final String PERMISSION_DELETE_BY_ID = " DELETE FROM " + PERMISSION_TABLE + " WHERE id=? ;"; private static final String PERMISSION_LIST_ALL = PERMISSION_SELECT + " ORDER BY createDate DESC ;"; private static final String PERMISSION_LIST_BY_PAGE = PERMISSION_LIST_ALL + " LIMIT ?,? ; "; private static final String PERMISSION_ADD = " INSERT INTO " + PERMISSION_TABLE
+ " (pName,pFunctionName,pid,pDesc,pUrl,pLevel,order,ext,createDate) VALUES(?,?,?,?,?,?,?,?,?,?)"; private static final String PERMISSION_UPDATE = " UPDATE "
+ PERMISSION_TABLE
+ " SET pName=? , pFunctionName=? , pid=? , pDesc=? , pUrl=? , pLevel=? , order=? , ext=? , createDate=? where id=? ;"; @Override
public boolean update(final Permission entity) {
if (null != entity) {
try {
final boolean flag = 0 < entity.getId(); DB.insertUpdate(flag ? PERMISSION_UPDATE : PERMISSION_ADD, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException { stmt.setString(1, entity.getpName());
stmt.setString(2, entity.getpFunctionName());
stmt.setInt(3, entity.getPid());
stmt.setString(4, entity.getpDesc());
stmt.setString(5, entity.getpUrl());
stmt.setInt(6, entity.getpLevel());
stmt.setInt(7, entity.getOrder());
stmt.setString(8, entity.getExt());
stmt.setDate(9, StringUtil.transforFromUtilToSqlDate(entity.getCreateDate())); if (flag) {
stmt.setInt(10, entity.getId());
}
stmt.executeUpdate(); }
});
} catch (SQLException e) {
log.error("更新权限信息异常!");
e.printStackTrace();
}
}
return false;
} @Override
public Permission get(final int id) { if (0 < id) {
final Permission permission = new Permission();
try {
boolean getResult = DB.select(PERMISSION_GET_BY_ID, new ParamReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException {
if (rs.next()) {
handResult(permission, rs);
} } @Override
public void setParams(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, id); }
}); if (getResult) {
return permission;
}
} catch (SQLException e) {
log.error("查询单条的权限信息异常!");
e.printStackTrace();
}
} return null;
} @Override
public boolean delete(final int id) {
if (0 < id) {
try {
return DB.insertUpdate(PERMISSION_DELETE_BY_ID, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, id);
stmt.executeUpdate();
}
});
} catch (SQLException e) {
log.error("删除单条的权限信息异常!");
e.printStackTrace();
}
} return false;
} @Override
public boolean batchDelete(final int[] idArray) {
if (null != idArray && 1 < idArray.length) {
try {
return DB.insertUpdate(PERMISSION_DELETE_BY_ID, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException {
for (int i : idArray) {
stmt.setInt(1, i);
stmt.addBatch();
}
stmt.executeBatch();
}
});
} catch (SQLException e) {
log.error("批量删除权限信息异常!");
e.printStackTrace();
}
} return false;
} @Override
public ImmutableList<Permission> listAll() { final List<Permission> permissionList = Lists.newLinkedList(); boolean listResult;
try {
listResult = DB.select(PERMISSION_LIST_ALL, new ReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException {
while (rs.next()) {
permissionList.add(handResult(new Permission(), rs));
} }
});
if (listResult) {
return ImmutableList.copyOf(permissionList);
} } catch (SQLException e) {
log.error("查询所有的权限信息异常!");
e.printStackTrace();
} return null;
} @Override
public ImmutableList<Permission> list(final int pageSize, final int page) {
final List<Permission> permissionList = Lists.newLinkedList(); boolean listResult;
try {
listResult = DB.select(PERMISSION_LIST_ALL, new ParamReadStH() {
@Override
public void handleRead(ResultSet rs) throws SQLException {
while (rs.next()) {
permissionList.add(handResult(new Permission(), rs));
} } @Override
public void setParams(PreparedStatement stmt) throws SQLException {
int start = pageSize * (page - 1);
int end = start + pageSize; stmt.setInt(1, start);
stmt.setInt(2, end); }
});
if (listResult) {
return ImmutableList.copyOf(permissionList);
} } catch (SQLException e) {
log.error("分页查询权限信息异常!");
e.printStackTrace();
} return null;
} private Permission handResult(final Permission permission, ResultSet rs) throws SQLException {
permission.setId(rs.getInt("id"));
permission.setpName(rs.getString("pName"));
permission.setpDesc(rs.getString("pDesc"));
permission.setOrder(rs.getInt("order"));
permission.setCreateDate(StringUtil.transforFromSqlToUtilDate(rs.getDate("createDate")));
permission.setpFunctionName(rs.getString("pFunctionName"));
permission.setExt(rs.getString("ext"));
permission.setPid(rs.getInt("pid"));
permission.setpLevel(rs.getInt("pLevel"));
permission.setpUrl(rs.getString("pUrl")); return permission;
} @Override
public ImmutableList<Permission> getPermissionsByRoleId(final int roleId) {
if (0 < roleId) {
final List<Permission> permissions = Lists.newLinkedList();
try {
boolean getResult = DB.select(PERMISSION_GET_BY_ROLEID, new ParamReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException {
while (rs.next()) {
permissions.add(handResult(new Permission(), rs));
} } @Override
public void setParams(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, roleId); }
}); if (getResult) {
return ImmutableList.copyOf(permissions);
}
} catch (SQLException e) {
log.error("根据角色查询权限信息异常!");
e.printStackTrace();
}
} return null;
} }
package com.cutter.web.account.dao.achieve;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List; import org.apache.log4j.Logger;
import org.apache.tiles.jsp.taglib.InsertAttributeTag;
import org.pureart.persistement.database.easydb.DB;
import org.pureart.persistement.database.easydb.IUStH;
import org.pureart.persistement.database.easydb.ParamReadStH;
import org.pureart.persistement.database.easydb.ReadStH; import com.cutter.web.account.dao.entity.Log;
import com.cutter.web.account.dao.inter.LogDao;
import com.cutter.web.account.util.StringUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; public class LogDaoAchieve implements LogDao { private static final Logger log = Logger.getLogger(LogDaoAchieve.class); private static final String LOG_TABLE = " test.dt_log "; private static final String LOG_SELECT = " SELECT * FROM " + LOG_TABLE; private static final String LOG_GET_BY_ID = LOG_SELECT + " WHERE id=? ;"; private static final String LOG_DELETE_BY_ID = " DELETE FROM " + LOG_TABLE + " WHERE id=? ;"; private static final String LOG_LIST_ALL = LOG_SELECT + " ORDER BY createDate DESC ;"; private static final String LOG_LIST_ALL_BY_PAGE = LOG_SELECT + " ORDER BY createDate DESC limit ?,? ;"; private static final String LOG_LIST_ALL_BY_TYPE = LOG_SELECT + " WHERE type=? ;"; private static final String LOG_ADD = " INSERT INTO " + LOG_TABLE
+ " (userName,ip,type,content,createDate,ext1,ext2) VALUES(?,?,?,?,?,?,?) ;"; private static final String LOG_UPDATE = " UPDATE " + LOG_TABLE
+ " SET userName=? , ip=? , type=? , content=? , createDate=? , ext1=? , ext2=? WHERE id=? ;"; @Override
public boolean update(final Log entity) { if (null != entity) {
try {
final boolean flag = 0 < entity.getId(); return DB.insertUpdate(flag ? LOG_UPDATE : LOG_ADD, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException {
stmt.setString(1, entity.getUserName());
stmt.setString(2, entity.getIp());
stmt.setInt(3, entity.getType());
stmt.setString(4, entity.getContent());
stmt.setDate(5, StringUtil.transforFromUtilToSqlDate(entity.getCreateDate()));
stmt.setString(6, entity.getExt1());
stmt.setString(7, entity.getExt2());
if (flag) {
stmt.setInt(8, entity.getId());
}
stmt.executeUpdate(); }
}); } catch (SQLException e) {
log.error("更新用户日志异常!");
e.printStackTrace();
}
} return false;
} @Override
public Log get(final int id) {
try {
final Log log = new Log();
boolean selectResult = DB.select(LOG_GET_BY_ID, new ParamReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException {
if (rs.next()) {
handleResult(log, rs);
}
} @Override
public void setParams(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, id);
}
}); if (selectResult) {
return log;
} } catch (SQLException e) {
log.error("查询单条的日志信息异常!");
e.printStackTrace();
} return null;
} @Override
public boolean delete(final int id) { try {
if (0 < id) {
return DB.insertUpdate(LOG_DELETE_BY_ID, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, id);
stmt.executeUpdate();
}
});
}
} catch (SQLException e) {
log.error("删除用户日志异常!");
e.printStackTrace();
}
return false;
} @Override
public boolean batchDelete(final int[] idArray) { try {
if (null != idArray && 1 <= idArray.length) {
return DB.insertUpdate(LOG_DELETE_BY_ID, new IUStH() { @Override
public void handleInsertUpdate(PreparedStatement stmt) throws SQLException { for (int i : idArray) {
stmt.setInt(1, i);
stmt.addBatch();
}
stmt.executeBatch(); }
});
}
} catch (SQLException e) {
log.error("批量删除日志异常!");
e.printStackTrace();
} return false;
} @Override
public ImmutableList<Log> listAll() {
final List<Log> logList = Lists.newLinkedList();
try {
final boolean listResult = DB.select(LOG_LIST_ALL, new ReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException {
while (rs.next()) {
logList.add(handleResult(new Log(), rs));
}
}
}); if (listResult) {
return ImmutableList.copyOf(logList);
} } catch (SQLException e) {
log.error("查询所有的日志异常!");
e.printStackTrace();
} return null;
} @Override
public ImmutableList<Log> list(final int pageSize, final int page) {
try {
if (0 < page && 0 < pageSize) {
final List<Log> logList = Lists.newLinkedList();
final boolean listResult = DB.select(LOG_LIST_ALL_BY_PAGE, new ParamReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException {
while (rs.next()) {
logList.add(handleResult(new Log(), rs));
}
} @Override
public void setParams(PreparedStatement stmt) throws SQLException {
int start = pageSize * (page - 1);
int end = start + pageSize;
stmt.setInt(1, start);
stmt.setInt(2, end);
}
}); if (listResult) {
return ImmutableList.copyOf(logList);
} } } catch (SQLException e) {
log.error("分页查询日志异常!");
e.printStackTrace();
} return null;
} @Override
public ImmutableList<Log> getLogByType(final int typeId) {
final List<Log> logList = Lists.newLinkedList();
try {
final boolean listResult = DB.select(LOG_LIST_ALL, new ParamReadStH() { @Override
public void handleRead(ResultSet rs) throws SQLException {
while (rs.next()) {
logList.add(handleResult(new Log(), rs));
}
} @Override
public void setParams(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, typeId); }
}); if (listResult) {
return ImmutableList.copyOf(logList);
} } catch (SQLException e) {
log.error("根据类型id查询日志异常!");
e.printStackTrace();
} return null;
} private Log handleResult(final Log log, ResultSet rs) throws SQLException { log.setId(rs.getInt("id"));
log.setUserName(rs.getString("userName"));
log.setIp(rs.getString("ip"));
log.setContent(rs.getString("content"));
log.setCreateDate(StringUtil.transforFromSqlToUtilDate(rs.getDate("createDate")));
log.setType(rs.getInt("type"));
log.setExt1(rs.getString("ext1"));
log.setExt2(rs.getString("ext2")); return log;
} }

struts2学习之旅三 权限管理和导航设计 这么枯燥重复的代码我硬是耐着性子花了一个半小时码完,真的服了自己,必须尽快找个简单易用的jpa框架来解放一下自己。

2,界面设计和导航

做出来的界面先照个面;

struts2学习之旅三 权限管理和导航设计

主要是在跳转到主页的时候,给出右侧导航栏的数据,然后使用tiles布局,实现页面的导航,基本完成了任务;下面贴出要点;

要点 说明
导航数据提取,初始化导航栏的时候先初始化菜单级别的权限,然后是导航级别的;到页面的时候设置一个拦截器,如果用户有权限,显示并导航,没有则拦截并隐藏;

private  List<PermissionTreeNode>  handlePermission(ImmutableList<PermissionEntity> permissions)
   {
      
       if(null!=permissions&&!permissions.isEmpty())
       {
           List<PermissionTreeNode> tree=Lists.newLinkedList();
           //1,筛选出菜单项
          Collection<PermissionEntity> menuCollection= Collections2.filter(permissions, new Predicate<PermissionEntity>() {

@Override
               public boolean apply(PermissionEntity input) {
                   return input.getpLevel()==1;
               }
           });
         
          if(null!=menuCollection&&!menuCollection.isEmpty())
          {
              //2,组装成树型结构
              for (final PermissionEntity menuItem : menuCollection) {
               PermissionTreeNode node=new PermissionTreeNode();
               node.setPid(menuItem.getId());
               node.setpName(menuItem.getpName());
               node.setChildren(Collections2.filter(permissions, new Predicate<PermissionEntity>() {

@Override
                   public boolean apply(PermissionEntity input) {
                       return input.getPid()==menuItem.getId()&&input.getpLevel()==2;
                   }
               }));
               tree.add(node);
           }
              return tree;
          }
         
       }
      
       return null;
   }

导航数据的构造,这里使用的是方法取得属性,使用成员变量名取不到,不知道是为什么,下次搞清楚了再贴出来;

<div style="background-color:gray;text-align: center;">
    <h1>导航</h1>

<hr>
    <s:iterator id="item" value="#session.permission" var="item">
        <div>
            <span><s:property value="#item.getpName()" /> </span>
            <s:iterator var="navItem" value="#item.getChildren()">
                <br><a href="<%=contextPath%><s:property value="#navItem.getpUrl()" /> ">
                    <s:property value="#navItem.getpName()" /> </a>
            </s:iterator>
        </div>

</s:iterator>
</div>

tiles组件配置,这里搞了一个title,算是人性化一点;

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN" "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
    <definition name="adminHomePage" extends="adminDefaultLayout">
        <put-attribute name="titleKey" value="cutter哥哥后台管理主页"/>   
        <put-attribute name="content" value="/manager/index.jsp" />
    </definition>
    <definition name="listUserPage" extends="adminDefaultLayout">
        <put-attribute name="titleKey" value="查询用户"/>
        <put-attribute name="content" value="/manager/user/userList.jsp" />
    </definition>
    <definition name="addUserPage" extends="adminDefaultLayout">
        <put-attribute name="titleKey" value="增加用户"/>
        <put-attribute name="content" value="/manager/user/addList.jsp" />
    </definition>
    <definition name="editUserPage" extends="adminDefaultLayout">
        <put-attribute name="titleKey" value="编辑用户"/>
        <put-attribute name="content" value="/manager/user/editList.jsp" />
    </definition>
</tiles-definitions>

优化了一下布局,作为后台开发人员,前端的布局和样式实在是有待加强,见谅;

<style type="text/css">
body {
    text-decoration: none;
    width: 100%;
    height: 100%;
    text-align: center;
}

.head {
    width: 100%;
    height: 50px;
    background-color: green;
}

.bottom {
    width: 100%;
    height: 30px;
    background-color: green;
}

.leftBox {
    width: 100px;
    height: 600px;
    background-color: green;
    clear:both;
    float: left;
}

.content {
    width: 90%;
    height: 600px;
    clear: right;
    margin-left: 100px;
    margin-top: 50px;
}
</style>

3,struts2的流程原理跟踪

要开发高效耐用的站点,并在站点出现问题的时候及时的补救,了解站点的启动和运行过程是很有必要的,现在手上的这个小demo规模很小,

我忍不住想要知道它到底是怎么启动和运行的,struts2这个万能代理到底起到一个神马作用;结合开始自学的那个图,来跟踪站点的启动和

运行过程;

站点的启动过程,tomcat启动之后,开始部署站,比如说要部署我的小站,首先它会找到WEB-INF,把下面的jar包先加载完,之后是一般的java代码,

Jsp转换之后的java代码,静态资源等(这是个猜想,之后我会去看看tomcat的核心代码,看看它的运行机制到底是不是这样的?)

看tomcat的启动日志可见一斑;

struts2学习之旅三 权限管理和导航设计

站点启动过程:个人通过源码分析;

struts2学习之旅三 权限管理和导航设计

tiles的启动细节分析:

要点 代码分析
tiles的启动过程

1,首先,得到ServletContext对象;通过tomcat的启动事件得到;

2,得到tiler容器,通过ServletContext构造;
如果ServletContext不含有key为TilesContainerFactory.CONTEXT_FACTORY_INIT_PARAM(
public static final String CONTEXT_FACTORY_INIT_PARAM =
        "org.apache.tiles.context.TilesContextFactory";)的配置,装饰一个;
  if(context.getInitParameter(TilesContainerFactory.CONTEXT_FACTORY_INIT_PARAM) == null) {
            context = decorate(context);
        }
        else {
            if (LOG.isWarnEnabled()) {
            LOG.warn("Tiles container factory is explicitly set.  Not injecting struts configuration.");
            }
        }
        return super.createContainer(context);

装饰过程如下:
protected ServletContext decorate(ServletContext context) {
        return new ConfiguredServletContext(context, INIT);
    }
直接使用现有的ServletContext和一个空的map实例化一个,作为ServletContext;
然后调用父类的工厂,创建一个容器;创建过程如下:
public TilesContainer createTilesContainer(Object context)
        throws TilesException {
        BasicTilesContainer container = new BasicTilesContainer();
        initializeContainer(context, container);
        return container;
    }
先创建一个基本的tiles容器,然后使用ServletContext初始化;

一切准备工作做好之后会打出一个log:Initializing Tiles2 container. . .

然后会初始化定义的配置文件,一个一个的加载到内存;
DEBUG - Adding resource 'jndi:/localhost/sq/WEB-INF/tiles/tiles.xml' to definitions factory.
DEBUG - Adding resource 'jndi:/localhost/sq/WEB-INF/tiles/tiles-adminUser.xml' to definitions factory.
得到一个读取配置文件的对象:
DEBUG - register('-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN', 'jar:file:/E:/evn/tomcat7-32or64/webapps/sq/WEB-INF/lib/tiles-cor
最后读取配置文件,找到tiles属性对应的文件,最后是初始化好定义的tiles组件;

BUG -   Popping body text ''
DEBUG - endDocument()
DEBUG - Resolve definition for child name='addUserPage' extends='adminDefaultLayout'.
DEBUG - Resolve definition for child name='adminHomePage' extends='adminDefaultLayout'.
DEBUG - Resolve definition for child name='editUserPage' extends='adminDefaultLayout'.
DEBUG - Resolve definition for child name='listUserPage' extends='adminDefaultLayout'.

最后把tiles容器发不到服务器的上下文;

struts2的过滤器的启动过程

struts2的初始化过程:
public void init(FilterConfig filterConfig) throws ServletException {
        InitOperations init = new InitOperations();
        try {
            FilterHostConfig config = new FilterHostConfig(filterConfig);
            init.initLogging(config);
           Dispatcher dispatcher = init.initDispatcher(config);
            init.initStaticContentLoader(config, dispatcher);

prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
            execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
            this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);

postInit(dispatcher, filterConfig);
        } finally {
            init.cleanup();
        }
    }

首先得到过滤器的配置文件,接着初始化日志,
然后加载struts的配置文件到内存,完成url和Action的映射(红色部分);

快下班了明天再分析红色的那部分代码;

最后是把控制权交还给tomcat的线程,完成tomcat的启动;

站点的运行过程放到下一节来说,晚上还有篮球赛,血战研发1,加油·············

4,小结

按照一般的后台的需求,模拟完成了两个功能,导航设计和权限管理,然后跟踪了一遍站点的启动和运行过程,加深了对struts2的理解;最后

奉上一个搞笑的图片,希望天天开心,保持好的心态;

struts2学习之旅三 权限管理和导航设计

上一篇:Hadoop 2.x HDFS新特性


下一篇:Django学习-8-模板渲染的一些特性