基于AdminLTE+Sitemesh3的框架化

AdminLTE是一个优秀的bootstrap框架,前端展现很美观,是个github的开源项目,demo的地址为:https://almsaeedstudio.com/preview   说明文档的地址为:https://almsaeedstudio.com/themes/AdminLTE/documentation/index.html

AdminLTE每个页面都是单独存在的,头部和左边菜单是重复的,需要进行框架改造。

最近在研究使用AdminLTE框架化,本文讲解使用sitemesh3使AdminLTE框架化的过程。系统架构为:SpringMVC+Spring+Hibernate+Maven+FreeMarker+Sitemesh(本项目集成并二次开发了许多bootstrap组件,目前正在持续开发中,将会在10.1之前完成所有的框架功能)

先看一下实现的效果图:

用户列表:

用户编辑:

字典管理:

图标选择器:

回到正题,下面详细讲解sitemesh3在这个项目上的使用:(sitemesh3的配置可参考本人上篇博客)

1、Maven中引入Sitemesh3

<dependency>
        <groupId>org.sitemesh</groupId>
	<artifactId>sitemesh</artifactId>
	<version>3.0.0</version>
</dependency>

2、web.xml中配置sitemesh3过滤器

<filter>
	<filter-name>sitemesh</filter-name>
	<filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>sitemesh</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

3、在web.xml的同级目录配置sitemesh3.xml

<?xml version="1.0" encoding="UTF-8"?>
<sitemesh>
	<mapping path="/*" decorator="/decorator"></mapping>
    <mapping path="/*/*edit" exclue="true"></mapping>
<!--     <mapping path="/*/*addUpdate" exclue="true"></mapping>
    <mapping path="/*/*add" exclue="true"></mapping>
    <mapping path="/*/*update" exclue="true"></mapping> -->
	<mapping path="/resources/*" exclue="true" />
	<mapping path="/*/nodecorator/*" exclue="true"/>
	<mapping path="/nodecorator/*" exclue="true"/>

	<!-- 自定义 tag 规则 -->
	<!-- Sitemesh 3 默认只提供了 body,title,head 等 tag 类型,我们可以通过实现 TagRuleBundle 扩展自定义的 tag 规则: -->
	<content-processor>
		<tag-rule-bundle class="com.cnpc.framework.tags.CSSTagRuleBundle" />
		<tag-rule-bundle class="com.cnpc.framework.tags.ScriptTagRuleBundle" />
	</content-processor>

</sitemesh>

上面定义了两个自定义标签,主要是将子页面的样式和脚本渲染到装饰页面

CSSTagRuleBundle.java

package com.cnpc.framework.tags;

import org.sitemesh.SiteMeshContext;
import org.sitemesh.content.ContentProperty;
import org.sitemesh.content.tagrules.TagRuleBundle;
import org.sitemesh.content.tagrules.html.ExportTagToContentRule;
import org.sitemesh.tagprocessor.State;

public class CSSTagRuleBundle implements TagRuleBundle {

    @Override
    public void install(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) {

        defaultState.addRule("myCSS", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("myCSS"), false));

    }

    @Override
    public void cleanUp(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) {

        // TODO Auto-generated method stub

    }

}

ScriptTagRuleBundle.java

package com.cnpc.framework.tags;

import org.sitemesh.SiteMeshContext;
import org.sitemesh.content.ContentProperty;
import org.sitemesh.content.tagrules.TagRuleBundle;
import org.sitemesh.content.tagrules.html.ExportTagToContentRule;
import org.sitemesh.tagprocessor.State;

public class ScriptTagRuleBundle implements TagRuleBundle {

    @Override
    public void install(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) {

        defaultState.addRule("myScript", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("myScript"), false));

    }

    @Override
    public void cleanUp(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) {

        // TODO Auto-generated method stub

    }

}

4、其中/decorator跳转的路径

   @RequestMapping(method = RequestMethod.GET, value = "/decorator")
    public String decorator(HttpServletRequest request) {

        return "decorator";
    }

decorator.html即为“母版页”,其代码如下,请主要下面<sitemesh:write 部分

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>AdminLTE |
      <span style="color:#FF0000;">
        <sitemesh:write property='title' /></span></title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <!-- -->
    <link rel="shortcut icon" type="image/ico" href="http://www.datatables.net/favicon.ico" media="screen">
    <!-- <link rel="shortcut icon" type="image/x-icon" href="${basePath}/resources/adminlte/base/img/ysd.ico" media="screen" />-->
    <!-- Bootstrap 3.3.6 -->
    <link rel="stylesheet" href="${basePath}/resources/adminlte/bootstrap/css/bootstrap.min.css">
    <!-- Font Awesome -->
    <link rel="stylesheet" href="${basePath}/resources/adminlte/css/font-awesome.min.css">
    <!-- Ionicons -->
    <link rel="stylesheet" href="${basePath}/resources/adminlte/css/ionicons.min.css">
    <!-- Theme style -->
    <link rel="stylesheet" href="${basePath}/resources/adminlte/dist/css/AdminLTE.min.css">
    <!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. -->
    <link rel="stylesheet" href="${basePath}/resources/adminlte/dist/css/skins/_all-skins.min.css">
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <!-- 加入页面的样式 -->
    <span style="color:#FF0000;">
      <sitemesh:write property='myCSS' /></span>
  </head>

  <body class="hold-transition skin-blue sidebar-mini">
    <div class="wrapper">
      <header class="main-header">
        <!-- Logo -->
        <a href="${basePath}/main" class="logo">
          <!-- mini logo for sidebar mini 50x50 pixels -->
          <span class="logo-mini">
            <b>A</b>LT</span>
          <!-- logo for regular state and mobile devices -->
          <span class="logo-lg">
            <b>Admin</b>LTE</span>
        </a>
        <!-- Header Navbar: style can be found in header.less -->
        <nav class="navbar navbar-static-top">
          <!--此处为顶部导航功能 代码略-->
		 </nav>
      </header>
      <!-- Left side column. contains the logo and sidebar -->
      <aside class="main-sidebar">

          <!--此处为左部菜单功能 代码略--></aside>
      <!-- Content Wrapper. Contains page content -->
      <div class="content-wrapper">
        <sitemesh:write property='body' /></div>
      <!-- /.content-wrapper -->
      <footer class="main-footer">
            <!--此处为底部版权声明功能 代码略-->
	  </footer>
      <!-- Control Sidebar -->
      <aside class="control-sidebar control-sidebar-dark">
          <!--此处为右侧浮动配置功能 代码略-->
	  </aside>
      <!-- /.control-sidebar -->
      <!-- Add the sidebar's background. This div must be placed immediately after the control sidebar -->
      <div class="control-sidebar-bg"></div>
    </div>
    <!-- ./wrapper -->
    <script type="text/javascript">var basePath = "${basePath}"; //给外部js文件传递路径参数
      </script>
    <!-- jQuery 2.2.0 -->
    <script src="${basePath}/resources/adminlte/plugins/jQuery/jQuery-2.2.0.min.js"></script>
    <!-- Bootstrap 3.3.6 -->
    <script src="${basePath}/resources/adminlte/bootstrap/js/bootstrap.min.js"></script>
    <!-- FastClick -->
    <script src="${basePath}/resources/adminlte/plugins/fastclick/fastclick.js"></script>
    <!-- AdminLTE App -->
    <script src="${basePath}/resources/adminlte/dist/js/app.min.js"></script>
    <!-- Sparkline -->
    <!-- AdminLTE for demo purposes -->
    <script src="${basePath}/resources/adminlte/dist/js/demo.js"></script>
    <script type="text/javascript" src="${basePath}/resources/common/js/base.js"></script>
    <script type="text/javascript" src="${basePath}/resources/common/js/base-modal.js"></script>
    <!-- 加入页面的的脚本 -->
    <sitemesh:write property='myScript' /></body>

</html>

5、一个“子页面”的配置,如用户管理列表界面 user_list.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>用户列表</title>
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- Bootstrap 3.3.6 -->

<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
  <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
  <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
  <![endif]-->
<myCSS>
<link rel="stylesheet" href="${basePath}/resources/adminlte/plugins/datatables/dataTables.bootstrap.css">
<link rel="stylesheet" href="${basePath}/resources/adminlte/plugins/datatables/select.bootstrap.min.css">
<link rel="stylesheet" href="${basePath}/resources/adminlte/plugins/bootstrap-validator/dist/css/bootstrap-validator.css"/>
<link rel="stylesheet" href="${basePath}/resources/adminlte/plugins/iCheck/all.css">
<link rel="stylesheet" href="${basePath}/resources/adminlte/plugins/datepicker/datepicker3.css">
</myCSS>

</head>
<body class="hold-transition skin-blue sidebar-mini">
	<!-- Content Header (Page header) -->
	<section class="content-header">
		<h1>
			用户管理 <small>列表</small>
		</h1>
		<ol class="breadcrumb">
			<li><a href="#"><i class="fa fa-dashboard"></i> 首页</a></li>
			<li><a href="#">系统管理</a></li>
			<li class="active">用户管理</li>
		</ol>
	</section> 

	<!-- Main content -->
	<section class="content">
		<div class="row">
			<div class="col-xs-12">
				<div class="box">
					<!-- /.box-header -->
					<div class="dataTables_filter" id="searchDiv">
						<input placeholder="请输入姓名" name="name" class="form-control" type="search" likeOption="true" /> <input
							placeholder="请输入登录名" name="loginName" class="form-control" type="search" likeOption="true" />
						<div class="btn-group">
							<button type="button" class="btn btn-primary" 	action_type="search">查询</button>
							<button type="button" class="btn btn-default" action_type="reset">重置</button>
						</div>
						<div class="btn-group">
							<button type="button" class="btn btn-default" action_type="add">新增</button>
							<button type="button" class="btn btn-default" action_type="edit" >编辑</button>
							<button type="button" class="btn btn-default" action_type="delete">删除</button>
						</div>
					</div>
					<div class="box-body">
						<table id="user_table" class="table table-bordered table-striped table-hover">
						</table>
					</div>
					<!-- /.box-body -->
				</div>
			</div>
			<!-- /.col -->
		</div>
		<!-- /.row -->
	</section>

	<myScript>
	    <script src="${basePath}/resources/adminlte/plugins/datatables/jquery.dataTables.js"></script>
	    <script	src="${basePath}/resources/adminlte/plugins/datatables/dataTables.bootstrap.min.js"></script>
		<script src="${basePath}/resources/common/js/dataTables.js"></script>
		<!-- form -->
		<script src="${basePath}/resources/adminlte/plugins/bootstrap-validator/dist/js/bootstrap-validator.js"></script>
		<script src="${basePath}/resources/adminlte/plugins/iCheck/icheck.min.js"></script>
		<script src="${basePath}/resources/adminlte/plugins/datepicker/bootstrap-datepicker.js"></script>
		<script>
			//tableId,queryId,conditionContainer
			var userTable;
			var winId="userWin";
			$(function() {
				//init table and fill data
				userTable = new CommonTable("user_table", "user_list", "searchDiv");

				//button event
				$('button[action_type]').click(function() {
					var action = $(this).attr('action_type');
					var rowId=userTable.getSelectedRowId();
					switch (action) {
					case 'add':
                        modals.openWin({
                        	winId:winId,
                        	title:'新增用户',
                        	top:'auto',
                        	width:'900px',
                        	url:basePath+"/user/edit"
                        	/*, hideFunc:function(){
                        		modals.info("hide me");
                        	},
                        	showFunc:function(){
                        		modals.info("show me");
                        	} */
                        });
						break;
					case 'edit':
						if(!rowId){
							modals.info('请选择要编辑的行');
							return false;
						}
						modals.openWin({
                        	winId:winId,
                        	title:'编辑用户【'+userTable.getSelectedRowData().name+'】',
                        	top:'auto',
                        	width:'900px',
                        	url:basePath+"/user/edit?id="+rowId
                        });
					   break;
					case 'delete':
						if(!rowId){
							modals.info('请选择要删除的行');
							return false;
						}
						modals.confirm("是否要删除该行数据?",function(){
							ajaxPost(basePath+"/user/delete/"+rowId,null,function(data){
								if(data.success){
									//modals.correct("已删除该数据");
									userTable.reloadRowData();
								}
							});
						})
						break;
					}

				});
				//form_init();
			})

		</script>
    </myScript>
</body>
</html>

以上过程完成了AdminLTE的框架化,但是存在一个性能问题,即每次需要访问/decorator路径,会重置顶部导航和左侧菜单,导致不能记住顶部导航和左侧当前菜单。后续可能不会使用Sitemesh3,可能会用jquery 的load方法。

当然有人说,sitemesh3太折腾了,用iframe不就可以吗?确实可以,但iframe的高度自适应的问题是在太恶心了,也存在一些其他问题。

时间: 2024-10-24 08:34:33

基于AdminLTE+Sitemesh3的框架化的相关文章

基于gulp的前端框架开发规范

前端开发及相关规范 - 基于gulp的前端框架开发规范 1.前端开发工具的安装和使用说明 前端开发工具的目录结构 htmlcodeBuilder - v0.9 ├── statics ├── html //静态文件开发 ├── js // 非require引入的js文件 ├── Lib // 第三方JS包 ├── ve_2_1 // ├── css // 样式目录 ├── fonts // bootstrap的图标字体 ├── img // 图片目录 ├── less // less源码 ├──

基于Selenium的自动化测试框架 - SeLion学习之一(基本介绍)

SeLion是一个基于Selenium的自动化测试框架,是Selenium下的一款非常优秀的框架结构,但是资料非常少,在国内使用的也就相对较少,本人会用一系列的文章,比较详细的介绍该框架结构,希望能给广大的自动化测试爱好者提供一个实现思路,如果对该本人文章感兴趣或者有什么问题,欢迎留言,我会尽量回答,也欢迎转载该系列文章.该文章是本系列第一节,SeLion的基本介绍,先让大家对SeLion有一个基本的认识. 一:SeLion是什么?SeLion是基于Selenium的一款开源测试框架,是对Sel

基于SEDA的异步框架设计与实现

基于SEDA的异步框架设计与实现 二.为什么使用SEDA 目前,面对并发环境,主流互联网服务器编程模型有两种:多线程模型以及事件驱动模型.但是这两个模型都不足以解决这个问题.我们来首先看一下这两种编程模型. 1.多线程并发模型 多线程并发模型是目前最普遍的服务器编程模型,该模型的架构如下图所示:        该模型针对每一个请求,会为其创建并分配一个线程.该线程负责这个请求的处理.该模型的优点:执行粒度是整个完整的处理流程.处理逻辑清晰,容易开发.但与此同时缺点也很明显:如果处理过程中某一步骤

基于反射实现自己主动化restful开发

[Author]: kwu 基于反射实现自己主动化restful开发,通用的仅仅须要写查询数据库的sql.并增加相应的javabean实现的高速restful服务的开发. 1.编写数据库的查询sql.相应sql.properties daily = DailyReport;select t.day,t.cnt,t.type from (select day,cnt,type From dailyreport where type=? order by day desc limit ? ) t o

基于asp.net + easyui框架,一步步学习easyui-datagrid——实现分页和搜索(二)

http://blog.csdn.net/jiuqiyuliang/article/details/19967031 目录: 基于asp.net + easyui框架,一步步学习easyui-datagrid——界面(一) 基于asp.net + easyui框架,一步步学习easyui-datagrid——实现分页和搜索(二) 基于asp.net + easyui框架,一步步学习easyui-datagrid——实现添加.编辑.删除(三) 基于asp.net + easyui框架,一步步学习e

Java实现的基于模板的网页结构化信息精准抽取组件:HtmlExtractor

HtmlExtractor是一个Java实现的基于模板的网页结构化信息精准抽取组件,本身并不包含爬虫功能,但可被爬虫或其他程序调用以便更精准地对网页结构化信息进行抽取. HtmlExtractor是为大规模分布式环境设计的,采用主从架构,主节点负责维护抽取规则,从节点向主节点请求抽取规则,当抽取规则发生变化,主节点主动通知从节点,从而能实现抽取规则变化之后的实时动态生效. 如何使用? HtmlExtractor由2个子项目构成,html-extractor和html-extractor-web.

基于QTP的自动化测试框架概述

框架稳定后展示给用户的内容有以下几部分,也就是说测试人员需要去关注去维护的部分就可以了,完全不在care代码内容是什么,只需要按照格式填写就OK 1.测试用例执行模拟控制列表(可用其它管理工具代替,这里用成本最低的方式实现不借助已有的专业管理工具) 2.测试用例控制列表 3.测试数据控制列表 基于QTP的自动化测试框架概述,布布扣,bubuko.com

使用像AdminLTE的前端框架,树形导航菜单实现方式都有哪些?

之前用easyui等富前端框架开发的时候都是使用封装好的县城的插件,现在使用最新的类似AdminLTE似的前段框架实现树形菜单都用什么方式? 后台拼接html然后前端用JS append方法添加还是直接后台返回值前端用js循环添加? 各位看官有啥好的实现方式或者是有其他的方便的插件推荐的,可以说出来一起讨论一下

基于状态机的游戏框架

一 定义 有限状态机就是一个具有有限数量状态, 并且能够根据相应的操作从一个状态变换到另一个状态, 而在同一时刻只能处在一种状态下的智能体. 英文:Finite State Machine 简称:FSM 二 最简单的状态机 最简单的状态机:if-else 实际上if-else就是一个最有两种状态的状态机,分别是true和false 三 伪状态机 当两种情况不能满足我们的需求时,我们可以用if-else if -...-else, 不过,为了方便,我们可以使用switch-case代替 首先,定义