最近工作上做了较多登陆模块的东西,一个较完善的登陆模块会涉及到不少知识点,如SSO、用户权限管理,Redis,今天给大家详细介绍用户权限管理这一功能模块中的动态菜单处理。
先展示需求的效果图:
一、实现过程简介:
用户进行登陆操作,请求进入后台时,数据库根据用户的职能去查询该用户可操作的菜单项目,数据库中存放单条菜单项,通过parent_id是否为0和child_id来实现父子层级关系,如 parent_id = 1 的菜单项(人员管理、角色管理、菜单管理)均为 menu_id = 1菜单项(权限管理)的子菜单,顺序由他们的 child_id 大小排序。简单的菜单设计显示为如下效果:
由于菜单存在级联关系,在返回值上我选用了HashMap。
二、代码实现部分:
Ajax请求菜单(个人认为前端解析难度大于后台获取)
(1)index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
Hello World!
(1)Getmenu.java(接收请求并构造动态菜单):
@WebServlet(urlPatterns="/Getmenu")
public class Getmenu extends HttpServlet {
MenuDao menuDao = new MenuDao();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// response.setContentType("text/xml;charset=UTF-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/plain;charset=utf-8");
PrintWriter out = response.getWriter();
List
public class MenuDao extends BaseDao {
public List getParentMenu(){
List menus = new ArrayList();
Menu menu = null;
try{
String sql = "select * from menu_table where parent_id = 0";
Object[] params = {};
ResultSet rs = this.executeSQL(sql,params);
while(rs.next()){
menu = new Menu();
menu.setMenu_id(rs.getInt(1));
menu.setMenu_name(rs.getString(2));
menu.setParent_id(rs.getInt(3));
menu.setChild_id(rs.getInt(4));
menus.add(menu);
}
}catch (SQLException e){
e.printStackTrace();
}
return menus;
}
public List getChildMenu(){
List menus = new ArrayList();
Menu menu = null;
try{
String sql = "select * from menu_table where parent_id > 0";
Object[] params = {};
ResultSet rs = this.executeSQL(sql,params);
while(rs.next()){
menu = new Menu();
menu.setMenu_id(rs.getInt(1));
menu.setMenu_name(rs.getString(2));
menu.setParent_id(rs.getInt(3));
menu.setChild_id(rs.getInt(4));
menus.add(menu);
}
}catch (SQLException e){
e.printStackTrace();
}
return menus;
}
}
public class BaseDao {
protected Connection conn;
protected PreparedStatement ps;
protected Statement stmt;
protected ResultSet rs;
//获取数据库连接
public boolean getConnection(){
//读取配置信息
PropertiesUtils.loadFile("config.properties");
String url = PropertiesUtils.getPropertyValue("url");
String username = PropertiesUtils.getPropertyValue("username");
String password = PropertiesUtils.getPropertyValue("password");
String driver = PropertiesUtils.getPropertyValue("driver");
//加载jdbc驱动
try{
Class.forName(driver);
//与数据库建立连接
conn = DriverManager.getConnection(url,username,password);
}catch(ClassNotFoundException e){
e.printStackTrace();
return false;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
//增删改
public int executeUpdate(String sql,Object[] params){
int updateRows = 0;
getConnection();
try{
ps = conn.prepareStatement(sql);
for(int i= 0;i
##jdbc config
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8
username = root
password = 123456
(5)PropertiesUtils.java(数据库连接通过配置文件实现的工具类):
public class PropertiesUtils {
static Properties prop = new Properties();
/**
* @param fileName 需要加载的properties文件,文件需要放在src根目录下
* 是否加载成功
*/
public static boolean loadFile(String fileName){
try {
prop.load(PropertiesUtils.class.getClassLoader().getResourceAsStream(fileName));
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 根据KEY取回相应的value
*/
public static String getPropertyValue(String key){
return prop.getProperty(key);
}
}
(6)pom.xml
mysql
mysql-connector-java
5.1.32
com.google.code.gson
gson
2.3.1
四、注意
在加载动态菜单时值得注意的是,ajax的解析类型与后台java的响应类型,个人在success回调函数解析返回data的时候花了较多时间调试,如json对象与object对象取值问题。若需更多的扩展功能,通常的做法建议是前端创建menu.js作为解析生成菜单的专有方法,实现可动画菜单的菜单与操作事件。该类方法在前端框架中并不少见,在此就不一一列举了。