六、模塊實現:登錄控制模塊(4)

    1. 登錄控制模塊
      1. 登錄攔截器

在包“com.example.demo”中新建一個“LoginInterceptor”類,代碼如下:

package com.example.demo;

import java.io.PrintWriter;

 

/**

 * 登錄攔截器

 */

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.web.servlet.HandlerInterceptor;

 

import com.example.demo.vo.Json;

import com.fasterxml.jackson.databind.ObjectMapper;

 

@Component

public class LoginInterceptor implements HandlerInterceptor {

   

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

 

    @Autowired

    private ObjectMapper mapper;//Jackson使用ObjectMapper類將POJO對象序列化成JSON字符串,也能將JSON字符串反序列化成POJO對象。

 

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {       //請求進入這個攔截器

         logger.info("進入攔截器...");

         HttpSession session = request.getSession();

        if(session.getAttribute("user") == null){//判斷session中有沒有user信息

        logger.info("session中沒有user信息");

        //ajax異步請求

            if("XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"))){

              logger.info("ajax異步請求");

              Json j = new Json();

              j.setSuccess(false);

              j.setMsg("session會話超時,請重新登錄!");

              response.setContentType("application/json;charset=UTF-8");

                  PrintWriter writer = response.getWriter();

                  writer.write(mapper.writeValueAsString(j));//將對象轉成字符串

                  logger.info(mapper.writeValueAsString(j));

                  writer.close();

                  response.flushBuffer();

                  return false;

            }else {

              logger.info("頁面請求");

              response.sendRedirect("/login");//沒有user信息的話進行路由重定向到登錄頁面

                return false;

            }

        }

        logger.info("登錄攔截驗證通過。");

        return true;//有的話就繼續操作

    }

}

每一個配置爲攔截的http請求都會執行preHandle方法,可以在這裏檢查用戶的session是否爲空來進行登錄驗證,因爲請求有可能是異步的,所以對於異步的請求不能直接跳轉頁面,而是返回json數據。

修改在包“com.example.demo”中新建一個“WebConfig”類,代碼如下:

package com.example.demo;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

 

@Configuration

public class WebConfig implements WebMvcConfigurer {

   

    @Autowired

    private LoginInterceptor loginInterceptor;//登錄攔截器

 

    //圖片存放根路徑,從application.yml中讀取upload

    @Value("${upload}")

    private String UPLOAD_PATH;

   

    /**

     * 文件上傳

     */

    @Override

    public void addResourceHandlers(ResourceHandlerRegistry registry) {

    //外部靜態資源映射路徑,用來上傳文件

    String filePath = "file:" + UPLOAD_PATH;

        registry.addResourceHandler("/upload/**").addResourceLocations(filePath);

    }

   

    //攔截器

    @Override

    public void addInterceptors(InterceptorRegistry registry) {

        //登錄攔截的管理器

        InterceptorRegistration registration = registry.addInterceptor(loginInterceptor);//攔截的對象會進入這個類中進行判斷

        registration.addPathPatterns("/**");//所有路徑都被攔截

        registration.excludePathPatterns("/","/login","/UserController/login","/kaptcha","/static/**","/UserController/logout","/upload/**");//添加不攔截路徑

    }

}

在WebConfig中增加了攔截器的設置。

      1. 驗證碼接口

修改在包“com.example.demo.controller”中新建一個“HomeController”類,代碼如下:

package com.example.demo.controller;

/**

 * 後臺管理主頁,登錄頁面,驗證碼生成

 */

import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.servlet.ModelAndView;

import com.example.demo.model.User;

import com.example.demo.service.PermissionService;

import com.google.code.kaptcha.Constants;

import com.google.code.kaptcha.Producer;

 

@Controller

public class HomeController {

 

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

   

    @Autowired 

    private Producer captchaProducer;//驗證碼

   

    @Autowired

    private PermissionService permissionService;// 注入業務層的service

   

    // 未加入@ResponseBody用來返回數據給頁面

    @RequestMapping("/index")

    public String index(HttpServletRequest request,Model model) {

         HttpSession session = request.getSession();

         User user = (User)session.getAttribute("user");

         logger.info(user.getUsername());

         logger.info(user.getId());

         model.addAttribute("username", user.getUsername());

         model.addAttribute("userid", user.getId());

         model.addAttribute("menulist", permissionService.getUserMenu(user.getId()));

         return "admin/index";

    }

 

    // 未加入@ResponseBody用來返回數據給頁面

    @RequestMapping("/home")

    public String home(Model model) {

         return "admin/home";

    }

   

    // 未加入@ResponseBody用來返回數據給頁面

    @RequestMapping("/")

    public String login(Model model) {

         return "admin/login";

    }

   

    // 未加入@ResponseBody用來返回數據給頁面

    @RequestMapping("/login")

    public String login2(Model model) {

         return "admin/login";

    }

   

    @RequestMapping("/kaptcha"

    public ModelAndView getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {   

        HttpSession session = request.getSession();   

        String code = (String)session.getAttribute(Constants.KAPTCHA_SESSION_KEY);   

        logger.info("******************驗證碼是: " + code + "******************");   

        response.setDateHeader("Expires", 0);   

        // Set standard HTTP/1.1 no-cache headers.   

        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");   

        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).   

        response.addHeader("Cache-Control", "post-check=0, pre-check=0");   

        // Set standard HTTP/1.0 no-cache header.   

        response.setHeader("Pragma", "no-cache");   

        // return a jpeg   

        response.setContentType("image/jpeg");   

        // create the text for the image   

        String capText = captchaProducer.createText();   

        // store the text in the session   

        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);   

        // create the image with the text   

        BufferedImage bi = captchaProducer.createImage(capText);   

        ServletOutputStream out = response.getOutputStream();   

        // write the data out   

        ImageIO.write(bi, "jpg", out);   

        try {   

            out.flush();   

        } finally {   

            out.close();   

        }   

        return null;   

    }

 

}

增加了登錄頁面路徑映射以及驗證碼生成接口。

修改在包“com.example.demo”中新建一個“MisApplication”類,代碼如下:

package com.example.demo;

 

import java.util.Properties;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;

import com.google.code.kaptcha.Constants;

import com.google.code.kaptcha.impl.DefaultKaptcha;

import com.google.code.kaptcha.util.Config;

 

@SpringBootApplication

public class MisApplication {

 

    public static void main(String[] args) {

         SpringApplication.run(MisApplication.class, args);

    }

   

    /**

     * 驗證碼

     * @return

     */

    @Bean 

    public DefaultKaptcha captchaProducer() { 

        DefaultKaptcha captchaProducer = new DefaultKaptcha(); 

        Properties properties = new Properties(); 

//      properties.setProperty(Constants.KAPTCHA_BORDER, "yes"); 

//      properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "red"); 

//      properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); 

        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "50"); 

        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "宋體,楷體,微軟雅黑"); 

        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); 

        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "0123456789"); 

        properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "120"); 

        properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "50"); 

        properties.setProperty(Constants.KAPTCHA_SESSION_CONFIG_KEY, "code"); 

        Config config = new Config(properties); 

        captchaProducer.setConfig(config); 

        return captchaProducer

    } 

 

}

對驗證碼的生成進行配置。

      1. 登錄與註銷接口

修改在包“com.example.demo.controller”中新建一個“UserController”類,代碼如下:

package com.example.demo.controller;

 

import java.io.File;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.util.StringUtils;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.multipart.MultipartFile;

 

import com.example.demo.model.User;

import com.example.demo.service.UserService;

import com.example.demo.util.SnowflakeIdWorker;

import com.example.demo.vo.DataTableResult;

import com.example.demo.vo.Json;

import com.example.demo.vo.UserVO;

import com.google.code.kaptcha.Constants;

 

@Controller

@RequestMapping("/UserController")

public class UserController {

 

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

 

    private String prefix = "admin/user";// 頁面的路徑,注意admin前面不要有/

 

    // 圖片存放根路徑,從application.yml中讀取upload

    @Value("${upload}")

    private String UPLOAD_PATH;

 

    @Autowired

    private UserService userService;// 注入業務層的service

 

    // 未加入@ResponseBody用來返回數據給頁面

    @RequestMapping("view")

    public String view(Model model) {

//       String str="個人";

//       model用來回傳數據給前端頁面

//       setTitle(model, new TitleVo("列表", str+"管理", true,"歡迎進入"+str+"頁面", true, false));

         return prefix + "/view";

    }

 

    // @ResponseBody,直接通過js異步返回數據給頁面

    @RequestMapping("list")

    @ResponseBody

    public DataTableResult list(HttpServletRequest request, UserVO userVO) {

         // DataTableResult返回給datatables控件的數據格式

         DataTableResult result = new DataTableResult();

         // 獲取分頁參數

         int start = Integer.parseInt(request.getParameter("start"));

         int length = Integer.parseInt(request.getParameter("length"));

         // 獲取排序字段

         String orderIdx = request.getParameter("order[0][column]");

         // 獲取排序字段名

         String orderField = request.getParameter("columns[" + orderIdx + "][name]");

         // 獲取排序方式,降序desc或者升序asc

         String orderDir = request.getParameter("order[0][dir]");

         // 調用分頁查詢方法

         result = userService.selectUserListPage(userVO, start, length, orderField, orderDir);

//       result.setDraw(userVO.getDraw());

         return result;

    }

    // @ResponseBody,直接通過js異步返回數據給頁面

    @RequestMapping("insert")

    @ResponseBody

    public Json insert(User user) {

         Json j = new Json();

         if (userService.insert(user) > 0) {

             j.setSuccess(true);

             j.setMsg("添加成功!");

         } else {

             j.setSuccess(false);

             j.setMsg("添加失敗!");

         }

         return j;

    }

 

    // @ResponseBody,直接通過js異步返回數據給頁面

    @RequestMapping("update")

    @ResponseBody

    public Json updateById(User user) {

         Json j = new Json();

         if (userService.updateById(user) > 0) {

             j.setSuccess(true);

             j.setMsg("修改成功!");

         } else {

             j.setSuccess(false);

             j.setMsg("修改失敗!");

         }

         return j;

    }

 

    // @ResponseBody,直接通過js異步返回數據給頁面

    @RequestMapping("select")

    @ResponseBody

    public Json selectById(User user) {

         Json j = new Json();

         j.setSuccess(true);

         j.setObj(userService.selectById(user.getId()));

         return j;

    }

 

    // @ResponseBody,直接通過js異步返回數據給頁面

    @RequestMapping("delete")

    @ResponseBody

    public Json delete(HttpServletRequest request) {

         Json j = new Json();

         String ids = request.getParameter("ids");

         if (!StringUtils.isEmpty(ids)) {

             j.setSuccess(true);

             j.setObj("成功刪除" + userService.delete(ids) + "條記錄");

         } else {

             j.setSuccess(false);

             j.setMsg("沒有需要刪除的記錄!");

         }

         return j;

    }

 

    // @ResponseBody,直接通過js異步返回數據給頁面

    // @RequestParam("file[]") MultipartFile[] file 多個文件

    @RequestMapping("upload")

    @ResponseBody

    public Json upload(HttpServletRequest request, @RequestParam("file") MultipartFile file) {

         Json j = new Json();

         if (!file.isEmpty()) {

             try {

                  String originalFilename = file.getOriginalFilename();

                  // 隨機文件名

                  String newFileName = SnowflakeIdWorker.getUUID()

                          + originalFilename.substring(originalFilename.lastIndexOf("."));

                  // 上傳文件路徑

                  File upload = new File(UPLOAD_PATH, "images/");

                 if (!upload.exists())

                      upload.mkdirs();

                  String uploadPath = upload + "\\";

                  logger.info("uploadPath = " + uploadPath);

                  File uploadfile = new File(uploadPath + newFileName);

                  // 將上傳文件保存到一個目標文件當中

                  file.transferTo(uploadfile);

                  j.setSuccess(true);

                  j.setObj("/upload/images/" + newFileName);

             } catch (IllegalStateException | IOException e) {

                  // TODO Auto-generated catch block

                  e.printStackTrace();

                  j.setSuccess(false);

                  j.setObj("上傳異常");

             }

 

         } else {

             j.setSuccess(false);

             j.setObj("上傳失敗");

         }

         return j;

    }

 

    /**

     * 登錄驗證

     * @param request

     * @param user

     * @return

     */

    // @ResponseBody,直接通過js異步返回數據給頁面

    @RequestMapping("login")

    @ResponseBody

    public Json login(HttpServletRequest request, User user) {

         Json j = new Json();

         HttpSession session = request.getSession();

         String code = (String) session.getAttribute(Constants.KAPTCHA_SESSION_KEY);

         String kaptcha = request.getParameter("kaptcha");

         if (kaptcha.equals(code)) {

             // 驗證碼正確

             User loginUser = userService.selectByUser(user);

             if (loginUser != null) {

                  j.setSuccess(true);

                  loginUser.setPassword("");// 密碼不回傳

                  j.setObj(loginUser);

                  j.setMsg("登錄成功!");

                  session.setAttribute("user", loginUser);// 保存session會話

             } else {

                  j.setSuccess(false);

                  j.setMsg("登錄失敗!");

             }

         } else {

             j.setSuccess(false);

             j.setMsg("驗證碼錯誤!");

         }

         return j;

    }

 

    /**

     * 註銷

     * @param request

     * @param model

     * @return

     */

    // 未加入@ResponseBody用來返回數據給頁面

    @RequestMapping("logout")

    public String logout(HttpServletRequest request,Model model) {

         HttpSession session = request.getSession();

         session.removeAttribute("user");

         return "admin/login";

    }

 

}

增加了用戶登錄與註銷接口。

      1. 登錄界面

添加登錄界面文件,在“admin”文件夾-> 右鍵->new->file,輸入“login.html”,代碼如下:

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

 

    <title> - 登錄</title>

    <meta name="keywords" content="">

    <meta name="description" content="">

    <link th:href="@{/static/css/bootstrap.min.css}" rel="stylesheet">

    <link th:href="@{/static/css/font-awesome.css?v=4.4.0}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">

    <link th:href="@{/static/css/style.css}" rel="stylesheet">

    <link th:href="@{/static/css/login.css}" rel="stylesheet">

    <!-- toastr -->

    <link th:href="@{/static/css/plugins/toastr/toastr.min.css}" rel="stylesheet">   

    <!--[if lt IE 9]>

    <meta http-equiv="refresh" content="0;ie.html" />

    <![endif]-->

    <script>

        if (window.top !== window.self) {

            window.top.location = window.location;

        }

    </script>

 

</head>

 

<body class="signin">

    <div class="signinpanel">

        <div class="row">

            <div class="col-sm-12">

                <form>

                    <h4 class="no-margins">登錄:</h4>

                    <p class="m-t-md">登錄XXX後臺管理系統</p>

                    <input type="text" name="username" id="username" class="form-control uname" placeholder="用戶名" />

                    <input type="password" name="password" id="password" class="form-control pword m-b" placeholder="密碼" />

                    <div class="input-group" style="margin-top:15px;color:#333;">

                          <input type="text" name="kaptcha" id="kaptcha" class="form-control" style="margin-top:0px;" placeholder="驗證碼" >

                          <span style="padding:1px;" class="input-group-addon "><img src="/kaptcha" id="kaptchaImage" style="height:30px;vertical-align:middle;" alt="點擊刷新" title="點擊刷新" onclick='$("#kaptchaImage").attr("src","/kaptcha?r="+Math.random())'></span>

                      </div>

                    <a href="">忘記密碼了?</a>

                    <button type="button" id="btn_login" class="btn btn-success btn-block">登錄</button>

                </form>

            </div>

        </div>

        <div class="signup-footer">

            <div class="pull-left">

                &copy; 福建江夏學院電子信息科學學院信息管理系,2019

            </div>

        </div>

    </div>

    <!-- 全局js -->

    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>

    <!-- Toastr script -->

    <script th:src="@{/static/js/plugins/toastr/toastr.min.js}"></script>

    <!-- Page-Level Scripts -->

    <script>

    $(document).ready(function () {

         //toastr選項

    toastr.options = {

       "positionClass": "toast-bottom-center",

    }

        

         $("#btn_login").click(function(){

             var username=$("#username").val();

             var password=$("#password").val();

             var kaptcha=$("#kaptcha").val();

             if(username.length==0 || password.length==0 || kaptcha.length==0){

                  toastr.error("用戶名、密碼或者驗證碼爲空!", '錯誤!');

             }else{

                  //異步添加數據

            $.ajax({

                  type: "post",

                  data: {

                      username:$("#username").val(),

                      password:$("#password").val(),

                      kaptcha:$("#kaptcha").val(),

                  },

                  url: "/UserController/login",//後臺處理地址

                  success: function (data) {

                     if(data.success){

                         toastr.success(data.msg, '登錄成功!');

                         location.href="/index";

                     }else{

                         toastr.error(data.msg, '登錄失敗!');

                     }

                  }

            });  // end ajax

             }

            

    });//end btn_login

    });//end ready

    </script>

</body>

</html>

 

      1. 動態加載菜單

修改主界面文件,在“admin”文件夾中的“index.html”,代碼如下:

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta name="renderer" content="webkit">

 

    <title> hAdmin- 主頁</title>

 

    <meta name="keywords" content="">

    <meta name="description" content="">

 

    <!--[if lt IE 9]>

    <meta http-equiv="refresh" content="0;ie.html" />

    <![endif]-->

 

    <link rel="shortcut icon" href="favicon.ico">

    <link th:href="@{/static/css/bootstrap.min.css?v=3.3.6}" rel="stylesheet">

    <link th:href="@{/static/css/font-awesome.min.css?v=4.4.0}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">

    <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

   

</head>

 

<body class="fixed-sidebar full-height-layout gray-bg" style="overflow:hidden">

    <div id="wrapper">

        <!--左側導航開始-->

        <nav class="navbar-default navbar-static-side" role="navigation">

            <div class="nav-close"><i class="fa fa-times-circle"></i>

            </div>

            <div class="sidebar-collapse">

                <ul class="nav" id="side-menu">

                    <li class="nav-header">

                        <div class="dropdown profile-element">

                            <a data-toggle="dropdown" class="dropdown-toggle" href="#">

                                <span class="clear">

                                    <span class="block m-t-xs" style="font-size:20px;">

                                        <i class="fa fa-bank"></i>

                                        <strong class="font-bold">管理系統</strong>

                                    </span>

                                </span>

                            </a>

                        </div>

                        <div class="logo-element">管理系統

                        </div>

                    </li>

 

                    <li>

                        <a class="J_menuItem" href="/home">

                            <i class="fa fa-home"></i>

                            <span class="nav-label">主頁</span>

                        </a>

                    </li>

                   

                   

 

                   

                    <li th:each="menu,menuStat:${menulist}">

                        <a href="#">

                            <i th:class="${menu.menu.menuIcon}"></i>

                            <span class="nav-label" th:text="${menu.menu.menuText}"></span>

                            <span class="fa arrow"></span>

                        </a>

                        <ul class="nav nav-second-level">

                            <li th:each="submenu,submenuStat:${menu.submenus}">

                                <a class="J_menuItem" th:href="@{${submenu.menuUrl}}" th:text="${submenu.menuText}"></a>

                            </li>

                        </ul>

                    </li>

                   

                 

 

 

                </ul>

            </div>

        </nav>

        <!--左側導航結束-->

        <!--右側部分開始-->

        <div id="page-wrapper" class="gray-bg dashbard-1">

            <div class="row border-bottom">

                <nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0">

                    <div class="navbar-header"><a class="navbar-minimalize minimalize-styl-2 btn btn-info " href="#"><i class="fa fa-bars"></i> </a>

                        <form role="search" class="navbar-form-custom" method="post" action="search_results.html">

                            <div class="form-group">

                                <input type="text" placeholder="請輸入您需要查找的內容 …" class="form-control" name="top-search" id="top-search">

                            </div>

                        </form>

                    </div>

                    <ul class="nav navbar-top-links navbar-right">

                        <li>

                           <span th:text="${username}"></span><span><a href="/UserController/logout">註銷</a></span>

                        </li>

                        <li class="dropdown">

                            <a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">

                                <i class="fa fa-envelope"></i> <span class="label label-warning">16</span>

                            </a>

                            <ul class="dropdown-menu dropdown-messages">

                                <li class="m-t-xs">

                                    <div class="dropdown-messages-box">

                                        <a href="profile.html" class="pull-left">

                                            <img alt="image" class="img-circle" th:src="@{/static/img/a7.jpg}">

                                        </a>

                                        <div class="media-body">

                                            <small class="pull-right">46小時前</small>

                                            <strong>小四</strong> 是不是隻有我死了,你們纔不罵爵跡

                                            <br>

                                            <small class="text-muted">3天前 2014.11.8</small>

                                        </div>

                                    </div>

                                </li>

                                <li class="divider"></li>

                                <li>

                                    <div class="dropdown-messages-box">

                                        <a href="profile.html" class="pull-left">

                                            <img alt="image" class="img-circle" th:src="@{/static/img/a4.jpg}">

                                        </a>

                                        <div class="media-body ">

                                            <small class="pull-right text-navy">25小時前</small>

                                            <strong>二愣子</strong> 呵呵

                                            <br>

                                            <small class="text-muted">昨天</small>

                                        </div>

                                    </div>

                                </li>

                                <li class="divider"></li>

                                <li>

                                    <div class="text-center link-block">

                                        <a class="J_menuItem" href="mailbox.html">

                                            <i class="fa fa-envelope"></i> <strong> 查看所有消息</strong>

                                        </a>

                                    </div>

                                </li>

                            </ul>

                        </li>

                        <li class="dropdown">

                            <a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">

                                <i class="fa fa-bell"></i> <span class="label label-primary">8</span>

                            </a>

                            <ul class="dropdown-menu dropdown-alerts">

                                <li>

                                    <a href="mailbox.html">

                                        <div>

                                            <i class="fa fa-envelope fa-fw"></i> 您有16條未讀消息

                                            <span class="pull-right text-muted small">4分鐘前</span>

                                        </div>

                                    </a>

                                </li>

                                <li class="divider"></li>

                                <li>

                                    <a href="profile.html">

                                        <div>

                                            <i class="fa fa-qq fa-fw"></i> 3條新回覆

                                            <span class="pull-right text-muted small">12分鐘錢</span>

                                        </div>

                                    </a>

                                </li>

                                <li class="divider"></li>

                                <li>

                                    <div class="text-center link-block">

                                        <a class="J_menuItem" href="notifications.html">

                                            <strong>查看所有 </strong>

                                            <i class="fa fa-angle-right"></i>

                                        </a>

                                    </div>

                                </li>

                            </ul>

                        </li>

                    </ul>

                </nav>

            </div>

            <div class="row J_mainContent" id="content-main">

                <iframe id="J_iframe" width="100%" height="100%" src="/home" frameborder="0" data-id="/home" seamless></iframe>

            </div>

        </div>

        <!--右側部分結束-->

    </div>

 

    <!-- 全局js -->

    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>

    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.6}"></script>

    <script th:src="@{/static/js/plugins/metisMenu/jquery.metisMenu.js}"></script>

    <script th:src="@{/static/js/plugins/slimscroll/jquery.slimscroll.min.js}"></script>

    <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>

 

    <!-- 自定義js -->

    <script th:src="@{/static/js/hAdmin.js?v=4.1.0}"></script>

    <script type="text/javascript" th:src="@{/static/js/index.js}"></script>

 

    <!-- 第三方插件 -->

    <script th:src="@{/static/js/plugins/pace/pace.min.js}"></script>

 

</body>

 

</html>

利用“th:each”對後臺返回的"${menulist}"數據進行二重遍歷,動態構造出用戶的菜單。

打開瀏覽器,先輸入地址http://127.0.0.1:8080/index,會發現跳轉到登錄頁面,效果如下:

以不同身份登錄時菜單不同,以用戶名和密碼都爲“e”登錄:

點擊右上角的註銷鏈接後,以用戶名和密碼都爲“a”登錄:

還可以通過後臺動態修改角色的權限和用戶的角色,注意首先是對角色分配權限,然後再把角色分配給用戶。

完整的項目源碼已經分享在GitHub網站上(https://github.com/gjq246/springboot2author)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章