struts2学习之旅三 权限管理和导航设计
1,权限管理的db设计和dao实现,尽量简单快速有效;
db的设计如下:权限按照角色来赋给用户;
权限对应每一个具体的功能,有菜单级别的,有导航级别的,还有页面级别的功能;
涉及到权限的敏感操作一般都要记录日志,不仅要记录到log里还要记录到远程的db里,以备审计。学习的时候暂时不用,但是为了全面考
虑设计,这里还是加上;
表名 | 建表的sql文,这里使用mysql数据库,因为是学习用的,后面会尝试用jpa去替换现在的dao,做到对db支持的灵活性 |
dt_role |
DROP TABLE IF EXISTS `dt_role`; |
dt_permission |
DROP TABLE IF EXISTS `dt_permission`; |
dt_log |
DROP TABLE IF EXISTS `dt_log`; |
数据持久层,采用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; } }
|
这么枯燥重复的代码我硬是耐着性子花了一个半小时码完,真的服了自己,必须尽快找个简单易用的jpa框架来解放一下自己。
2,界面设计和导航
做出来的界面先照个面;
主要是在跳转到主页的时候,给出右侧导航栏的数据,然后使用tiles布局,实现页面的导航,基本完成了任务;下面贴出要点;
要点 | 说明 |
导航数据提取,初始化导航栏的时候先初始化菜单级别的权限,然后是导航级别的;到页面的时候设置一个拦截器,如果用户有权限,显示并导航,没有则拦截并隐藏; |
private List<PermissionTreeNode> handlePermission(ImmutableList<PermissionEntity> permissions) @Override @Override |
导航数据的构造,这里使用的是方法取得属性,使用成员变量名取不到,不知道是为什么,下次搞清楚了再贴出来; |
<div style="background-color:gray;text-align: center;"> <hr> </s:iterator> |
tiles组件配置,这里搞了一个title,算是人性化一点; |
<?xml version="1.0" encoding="UTF-8"?> |
优化了一下布局,作为后台开发人员,前端的布局和样式实在是有待加强,见谅; |
<style type="text/css"> .head { .bottom { .leftBox { .content { |
3,struts2的流程原理跟踪
要开发高效耐用的站点,并在站点出现问题的时候及时的补救,了解站点的启动和运行过程是很有必要的,现在手上的这个小demo规模很小,
我忍不住想要知道它到底是怎么启动和运行的,struts2这个万能代理到底起到一个神马作用;结合开始自学的那个图,来跟踪站点的启动和
运行过程;
站点的启动过程,tomcat启动之后,开始部署站,比如说要部署我的小站,首先它会找到WEB-INF,把下面的jar包先加载完,之后是一般的java代码,
Jsp转换之后的java代码,静态资源等(这是个猜想,之后我会去看看tomcat的核心代码,看看它的运行机制到底是不是这样的?)
看tomcat的启动日志可见一斑;
站点启动过程:个人通过源码分析;
tiles的启动细节分析:
要点 | 代码分析 |
tiles的启动过程 |
1,首先,得到ServletContext对象;通过tomcat的启动事件得到; 2,得到tiler容器,通过ServletContext构造; 装饰过程如下: 一切准备工作做好之后会打出一个log:Initializing Tiles2 container. . . 然后会初始化定义的配置文件,一个一个的加载到内存; BUG - Popping body text '' 最后把tiles容器发不到服务器的上下文; |
struts2的过滤器的启动过程 |
struts2的初始化过程: prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher); postInit(dispatcher, filterConfig); 首先得到过滤器的配置文件,接着初始化日志, 快下班了明天再分析红色的那部分代码; 最后是把控制权交还给tomcat的线程,完成tomcat的启动; |
站点的运行过程放到下一节来说,晚上还有篮球赛,血战研发1,加油·············
4,小结
按照一般的后台的需求,模拟完成了两个功能,导航设计和权限管理,然后跟踪了一遍站点的启动和运行过程,加深了对struts2的理解;最后
奉上一个搞笑的图片,希望天天开心,保持好的心态;