接着上篇继续,博客网站少不了后台管理页面,在后台可以添加文章以及维护基础数据,因此本文主要就介绍怎样添加视图页面、怎样使用视图模型、绑定静态资源以及ThymeLeaf模板引擎的基本使用,具体如下:
1. 添加Menu类,表示后台管理页面中的左侧菜单
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.lvniao.blog.model; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class Menu { 7 8 private Long id; 9 10 private String name; 11 12 private String addr; 13 14 private String icon; 15 16 private Menu parent; 17 18 private List<Menu> children = new ArrayList<Menu>(); 19 20 public Long getId() { 21 return id; 22 } 23 24 public void setId(Long id) { 25 this.id = id; 26 } 27 28 public String getName() { 29 return name; 30 } 31 32 public void setName(String name) { 33 this.name = name; 34 } 35 36 public String getAddr() { 37 return addr; 38 } 39 40 public void setAddr(String addr) { 41 this.addr = addr; 42 } 43 44 public String getIcon() { 45 return icon; 46 } 47 48 public void setIcon(String icon) { 49 this.icon = icon; 50 } 51 52 public Menu getParent() { 53 return parent; 54 } 55 56 public void setParent(Menu parent) { 57 this.parent = parent; 58 } 59 60 public List<Menu> getChildren() { 61 return children; 62 } 63 64 public void setChildren(List<Menu> children) { 65 this.children = children; 66 } 67 }
2. 添加对应的Mapper类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.lvniao.blog.mapper; 2 3 import java.util.List; 4 5 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Param; 7 import org.apache.ibatis.annotations.Result; 8 import org.apache.ibatis.annotations.Results; 9 import org.apache.ibatis.annotations.Select; 10 import org.apache.ibatis.mapping.FetchType; 11 import org.apache.ibatis.annotations.Many; 12 13 import com.lvniao.blog.model.Menu; 14 15 @Mapper 16 public interface MenuMapper { 17 18 @Select("select id, name, addr, icon, parentid from menus where parentid is null") 19 @Results({ 20 @Result(id=true, column="id", property="id"), 21 @Result(column="name", property="name"), 22 @Result(column="addr", property="addr"), 23 @Result(column="icon", property="icon"), 24 @Result(column="id", property="children", 25 many=@Many(select="com.lvniao.blog.mapper.MenuMapper.getMenuByParent", fetchType=FetchType.EAGER)) 26 }) 27 public List<Menu> getParentMenu(); 28 29 @Select("select id, name, addr, icon, parentid from menus where parentid=#{id}") 30 @Results({ 31 @Result(id=true, column="id", property="id"), 32 @Result(column="name", property="name"), 33 @Result(column="addr", property="addr"), 34 @Result(column="icon", property="icon"), 35 }) 36 public List<Menu> getMenuByParent(Long id); 37 }
这儿使用了注解来完成一对多的映射;
3. 在控制器中添加动作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.lvniao.blog.admin.controller; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.stereotype.Controller; 7 import org.springframework.ui.Model; 8 import org.springframework.web.bind.annotation.RequestMapping; 9 10 import com.lvniao.blog.mapper.MenuMapper; 11 import com.lvniao.blog.mapper.UserMapper; 12 import com.lvniao.blog.model.Menu; 13 14 @Controller 15 @RequestMapping("/admin") 16 public class AdminController { 17 18 @Autowired 19 private UserMapper userMapper; 20 21 @Autowired 22 private MenuMapper menuMapper; 23 24 @RequestMapping("/") 25 public String index(Model model) { 26 model.addAttribute("users", userMapper.getUsers()); 27 model.addAttribute("menus", menuMapper.getParentMenu()); 28 return "admin/index"; 29 } 30 }
通过在index方法中添加Model参数,这样调用该方法时,系统会自动注入视图模型,这样要在视图中显示的数据就可以通过视图模型来传递到视图中。
4. 添加视图
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>lvniao</title> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/> 7 <link rel="stylesheet" th:href="@{/css/base.css}"/> 8 <link rel="stylesheet" th:href="@{/css/font-awesome.css}"/> 9 <script th:src="@{/js/jquery-3.2.1.js}"></script> 10 <script th:src="@{/js/base.js}"></script> 11 <script> 12 $(function(){ 13 init(); 14 }); 15 16 function logout(){ 17 $.ajax({ 18 url:"${pageContext.request.contextPath}/admin/home/logout", 19 success:function(data){ 20 window.location.reload(); 21 } 22 }) 23 24 } 25 </script> 26 </head> 27 <body class="lv-container"> 28 <div class="lv-head-section"> 29 <div class="lv-head-logo">LVNIAO</div> 30 <div class="lv-head-function"> 31 <div class="lv-head-btn lv-fold fa fa-bars"></div> 32 <div class="lv-sys-menu"> 33 <div class="lv-head-btn lv-first lv-sys-btn fa fa-th-list"> 34 <div class="lv-sys-panel"> 35 <div class="lv-sys-panel-content"> 36 </div> 37 </div> 38 </div> 39 <div class="lv-head-btn lv-sys-btn fa fa-comment"> 40 <div class="lv-sys-panel"> 41 <div class="lv-sys-panel-content"> 42 </div> 43 </div> 44 </div> 45 <div class="lv-head-btn lv-sys-btn fa fa-info-circle"> 46 <div class="lv-sys-panel"> 47 <div class="lv-sys-panel-content"> 48 </div> 49 </div> 50 </div> 51 <div class="lv-head-btn lv-sys-btn fa fa-user-circle"> 52 <div class="lv-sys-panel"> 53 <div class="lv-sys-panel-content"> 54 <h1>hello ${sessionScope.CurrentUser.name }</h1> 55 <a onclick="logout();">logout</a> 56 </div> 57 </div> 58 </div> 59 <div class="lv-head-btn lv-sys-btn fa fa-cog"> 60 <div class="lv-sys-panel"> 61 <div class="lv-sys-panel-content"> 62 </div> 63 </div> 64 </div> 65 </div> 66 </div> 67 </div> 68 <div class="lv-left-section"> 69 <ul class="lv-main-menu"> 70 <li class="lv-menu-item" th:each="menu:${menus}"> 71 <div class="lv-title" > 72 <div class="lv-img " th:attrappend="class=${' ' + menu.icon}"></div> 73 <div class="lv-text" th:text="${menu.name}"></div> 74 </div> 75 <ul class="lv-items"> 76 <li class="lv-item" th:each="sub:${menu.children}" th:attr="addr=${sub.addr}"> 77 <div class="lv-text" th:text="${sub.name}"></div> 78 </li> 79 </ul> 80 </li> 81 </ul> 82 </div> 83 <div class="lv-center-section"> 84 <div class="lv-tab-container"> 85 <div class="lv-tab-titles"> 86 <div class="lv-tab-title selected"> 87 <span class="lv-tab-icon fa fa-home"></span><span class="lv-tab-title-text">主页</span> 88 </div> 89 </div> 90 <div class="lv-tab-pages"> 91 <div class="lv-tab-page"> 92 93 </div> 94 </div> 95 </div> 96 </div> 97 </body> 98 </html>
其中通过<link rel="stylesheet" th:href="@{/css/base.css}"/>来引入css文件,通过<script th:src="@{/js/jquery-3.2.1.js}"></script>
来引入js文件,这些资源文件一定要放在static目录下才可以被发现。其中link一定要以/>结尾,否则视图解析会出错。
在上述代码片段中有以下代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<li class="lv-menu-item" th:each="menu:${menus}"> <div class="lv-title" > <div class="lv-img " th:attrappend="class=${' ' + menu.icon}"></div> <div class="lv-text" th:text="${menu.name}"></div> </div> <ul class="lv-items"> <li class="lv-item" th:each="sub:${menu.children}" th:attr="addr=${sub.addr}"> <div class="lv-text" th:text="${sub.name}"></div> </li> </ul> </li>
其中th:each=”menu:${menus}”表示遍历视图模型中menus的集合数据,迭代变量是menu;而th:attrappend="class=${' ' + menu.icon}"表示给class属性添加后缀,注意一定要在绑定表达式中添加空格字符;
5. 在static目录下添加favicon.icon,并在application.properties文件中添加spring.mvc.favicon.enabled=false,这样就可以使用自己的网站图标了;
6. 运行,并输入http://localhost:8080/admin/,即可看到运行效果