为什么使用Jfinal Enjoy作为前端页面渲染?
简单高效
模板引擎的对比:https://blog.csdn.net/qq_43107323/article/details/104595368
1.引入Enjoy
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>enjoy</artifactId>
<version>4.5</version>
</dependency>
2.ApplicationListener
package kim.lln.web.config;
import com.jfinal.template.ext.spring.JFinalViewResolver;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
public class EnjoyViewResolver extends JFinalViewResolver implements
ApplicationListener<ContextRefreshedEvent> {
/**
* 添加默认路径
* @param contextRefreshedEvent
*/
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
getEngine().addSharedObject("ctx", getServletContext().getContextPath());
}
}
3.EnjoyConfig
package kim.lln.web.config;
import kim.lln.common.constants.Constant;
import com.jfinal.template.Engine;
import com.jfinal.template.ext.spring.JFinalViewResolver;
import kim.lln.web.admin.security.realm.HasPermissionTag;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EnjoyConfig {
@Bean(name = "enjoyViewResolver")
public EnjoyViewResolver getJFinalViewResolver() {
// 创建用于整合 spring boot 的 ViewResolver 扩展对象
EnjoyViewResolver jfr = new EnjoyViewResolver();
// 对 spring boot 进行配置
jfr.setDevMode(!Constant.isPro());
jfr.setSuffix(".html");
jfr.setContentType("text/html;charset=UTF-8");
jfr.setOrder(0);
jfr.setSessionInView(true);
// jfr.setRequestContextAttribute("ctx");
// 获取 engine 对象,对 enjoy 模板引擎进行配置
Engine engine = JFinalViewResolver.engine;
// 热加载配置能对后续配置产生影响,需要放在最前面
engine.setDevMode(!Constant.isPro());
// 使用 ClassPathSourceFactory 从 class path 与 jar 包中加载模板文件
engine.setToClassPathSourceFactory();
// 在使用 ClassPathSourceFactory 时要使用 setBaseTemplatePath
// 代替 jfr.setPrefix("/view/")
engine.setBaseTemplatePath("/view/");
//添加自定义指令(标签)
engine.addDirective("hasPermission", HasPermissionTag.class);
return jfr;
}
}
4.如果使用的是Shiro(其他方式雷同),添加以下代码即可在html页面进行权限限制
package kim.lln.web.admin.security.realm;
import com.jfinal.template.Env;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.stat.Scope;
import org.apache.commons.lang3.ArrayUtils;
import com.jfinal.template.Directive;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
/**
* 验证当前Subject是否有该权限
* #hasPermission(permissionName)
* body
* #end
*/
@DefineDirective(tag = "hasPermission")
public class HasPermissionTag extends Directive {
private Expr[] exprs;
public void setExprList(ExprList exprList) {
exprs = exprList.getExprArray();
}
public void exec(Env env, Scope scope, com.jfinal.template.io.Writer writer) {
if (getSubject() != null && ArrayUtils.isNotEmpty(exprs))
if (getSubject().isPermitted(exprs[0].toString()))
stat.exec(env, scope, writer);
}
public boolean hasEnd() {
return true;
}
private Subject getSubject() {
return SecurityUtils.getSubject();
}
}
5.贴一个我项目中的list页面写法 ,文件名 list.html
引入公共模板并调用,更多使用方法请前往jfinal官网
引入公共模板 -> #include("/_layout.html")
调用公共模板 -> #@layout("list","楼栋列表")
#include("/_layout.html")
#@layout("list","楼栋列表")
#define content()
<div class="layui-form layui-card-header layuiadmin-card-header-auto layui-form-pane" id="searchDiv">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">名称</label>
<div class="layui-input-inline">
<input type="text" name="name" id="name" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-inline">
<select name="status" id="enable">
<option value="">请选择</option>
</select>
</div>
</div>
<div class="layui-inline">
<button class="layui-btn layuiadmin-btn-useradmin layui-click-btn" onclick="javascript:window.search()"><i class="layui-icon layui-icon-search layuiadmin-button-btn"></i></button>
<button class="layui-btn layuiadmin-btn-useradmin layui-click-btn" onclick="javascript:window.clear()">清空</button>
</div>
</div>
</div>
<div class="layui-card-body">
<table class="layui-hide" id="tableData" lay-filter="tableData"></table>
</div>
#end
#define script()
<script type="text/html" id="toolbar">
#hasPermission("community:community_building:save")
<a class="layui-btn btn-add btn-default" lay-event="add"><i class="layui-icon"></i>新增</a>
#end
</script>
<script type="text/html" id="columnToolbar">
#hasPermission("community:community_building:view")
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="view"><i class="layui-icon layui-icon-list"></i>查看</a>
#end
#hasPermission("community:community_building:update")
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>编辑</a>
#end
#hasPermission("community:community_building:delete")
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>
#end
</script>
<script type="text/javascript">
var enable={"1":"启用","0":"禁用"};
v2option("enable",enable);
var datas = [[ //表头
{field: 'id', title: 'ID', width: 100},
{field: 'communityName', title: '社区名称',width: 200,templet: function (data) { return data.communityName+'/'+data.communityId;}},
{field: 'buildingName', title: '楼栋单元',width: 130},
{field: 'totalFloors', title: '总楼层',width: 130,templet: function (data) { return "共"+data.totalFloors+'层';}},
{field: 'filterFloors', title: '没有的楼层',width: 130},
{field: 'lift', title: '电梯/楼梯/货梯',width: 130,templet: function (data) { return data.lift+"梯/"+data.stairs+"梯/"+data.cargoLift+"梯";}},
{field: 'status', title: '状态',width: 130,templet: function (data) { return v2m(data.status,enable);}},
{field: 'remark', title: '备注',width: 130},
{fixed: 'right', title: '操作', width: 260, align: 'center', toolbar: '#columnToolbar'} //这里的toolbar值是模板元素的选择器
]];
$(function () {
var listPage = new ListPage();
listPage.pageReqUrl = ctx + '/admin/community/communityBuilding/list.html';
listPage.iframeTitle = '楼栋单元';
listPage.columns = datas;
listPage.events=[
{"title":"新增楼栋单元", "event":"add", successFunction : listPage.editIframeSuccessFunction , yesFunction: listPage.editYesFunction, "ui":ctx + '/admin/community/communityBuilding/saveUI.html', "operate":ctx + '/admin/community/communityBuilding/save.html', "type":"edit"},
{"title":"修改楼栋单元", "event":"edit", successFunction : listPage.editIframeSuccessFunction , yesFunction:listPage.editYesFunction, "ui":ctx + '/admin/community/communityBuilding/updateUI.html', "operate":ctx + '/admin/community/communityBuilding/update.html', "type":"edit"},
{"title":"查看楼栋单元信息","event":"view","successFunction":listPage.initForm, "ui":ctx + '/admin/community/communityBuilding/viewUI.html', "operate":ctx + '/admin/community/communityBuilding/viewUI.html',"type":"view", "filterFields":""},
{"title":"删除楼栋单元", "event":"del", "ui":ctx + '/admin/community/communityBuilding/delete.html', "operate":ctx + '/admin/community/communityBuilding/delete.html', "type":"delete","tips":"确认删除楼栋单元?"}
];
listPage.initPageTable();
});
</script>
#end
定义公共模板 -> #define layout(type,title)
#define layout(type,title)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>#(title)-#(merchantName??'蓝灵通')</title>
<link rel="icon" href="/image/favicons.png">
#@style?()
<style>
.layui-table-tool{
background: white;
}
</style>
#if(type=='list')
#include("/common/list_head.html")
#else
#include("/common/form_head.html")
#end
</head>
<body class="body">
<div class="layui-fluid">
<div class="layui-card">
#@content?()
</div>
</div>
</body>
<script>
var isSuperAdmin=#(isSuperAdmin)||false;
var isPlatform=#(isPlatform)||false;
</script>
#@script?()
</html>
#end
效果
相关项目