You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
8.5 KiB
244 lines
8.5 KiB
/**
|
|
* 请勿将俱乐部专享资源复制给其他人,保护知识产权即是保护我们所在的行业,进而保护我们自己的利益
|
|
* 即便是公司的同事,也请尊重 JFinal 作者的努力与付出,不要复制给同事
|
|
*
|
|
* 如果你尚未加入俱乐部,请立即删除该项目,或者现在加入俱乐部:http://jfinal.com/club
|
|
*
|
|
* 俱乐部将提供 jfinal-club 项目文档与设计资源、专用 QQ 群,以及作者在俱乐部定期的分享与答疑,
|
|
* 价值远比仅仅拥有 jfinal club 项目源代码要大得多
|
|
*
|
|
* JFinal 俱乐部是五年以来首次寻求外部资源的尝试,以便于有资源创建更加
|
|
* 高品质的产品与服务,为大家带来更大的价值,所以请大家多多支持,不要将
|
|
* 首次的尝试扼杀在了摇篮之中
|
|
*/
|
|
|
|
package com.bt.common;
|
|
|
|
import java.sql.Connection;
|
|
import com.alibaba.druid.filter.stat.StatFilter;
|
|
import com.alibaba.druid.wall.WallFilter;
|
|
import com.bt._admin.auth.AdminAuthInterceptor;
|
|
import com.bt._admin.auth.AdminAuthKit;
|
|
import com.bt._admin.common.PjaxInterceptor;
|
|
import com.bt._admin.permission.PermissionDirective;
|
|
import com.bt._admin.role.RoleDirective;
|
|
import com.bt.common.kit.DruidKit;
|
|
import com.bt.common.model.Document;
|
|
import com.bt.common.model.Feedback;
|
|
import com.bt.common.model.Project;
|
|
import com.bt.common.model.Share;
|
|
import com.bt.common.model._MappingKit;
|
|
import com.jfinal.config.*;
|
|
import com.jfinal.json.MixedJsonFactory;
|
|
import com.jfinal.kit.Prop;
|
|
import com.jfinal.kit.PropKit;
|
|
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
|
|
import com.jfinal.plugin.cron4j.Cron4jPlugin;
|
|
import com.jfinal.plugin.druid.DruidPlugin;
|
|
import com.jfinal.plugin.ehcache.EhCachePlugin;
|
|
import com.jfinal.render.JsonRender;
|
|
import com.jfinal.server.undertow.UndertowServer;
|
|
import com.jfinal.template.Engine;
|
|
import com.bt.common.handler.UrlSeoHandler;
|
|
import com.bt.common.model.*;
|
|
import com.bt.common.interceptor.LoginSessionInterceptor;
|
|
import com.bt.login.LoginService;
|
|
import com.bt.my.friend.FriendInterceptor;
|
|
|
|
/**
|
|
* JFinalClubConfig
|
|
*/
|
|
public class JFinalClubConfig extends JFinalConfig {
|
|
|
|
// 使用 jfinal-undertow 时此处仅保留声明,不能有加载代码
|
|
private static Prop p;
|
|
|
|
private WallFilter wallFilter;
|
|
|
|
/**
|
|
* 启动入口,运行此 main 方法可以启动项目,此 main 方法
|
|
* 可以放置在任意的 Class 类定义中,不一定要放于此
|
|
*/
|
|
public static void main(String[] args) {
|
|
UndertowServer.start(JFinalClubConfig.class);
|
|
}
|
|
|
|
/**
|
|
* PropKit.useFirstFound(...) 使用参数中从左到右最先被找到的配置文件
|
|
* 从左到右依次去找配置,找到则立即加载并立即返回,后续配置将被忽略
|
|
*/
|
|
static void loadConfig() {
|
|
if (p == null) {
|
|
p = PropKit.useFirstFound("jfinal-club-config-pro.txt", "jfinal-club-config-dev.txt");
|
|
}
|
|
}
|
|
|
|
public void configConstant(Constants me) {
|
|
loadConfig();
|
|
|
|
me.setDevMode(p.getBoolean("devMode", false));
|
|
me.setJsonFactory(MixedJsonFactory.me());
|
|
|
|
// 支持 Controller、Interceptor、Validator 之中使用 @Inject 注入业务层,并且自动实现 AOP
|
|
me.setInjectDependency(true);
|
|
|
|
// 是否对超类中的属性进行注入
|
|
me.setInjectSuperClass(true);
|
|
}
|
|
|
|
/**
|
|
* 路由拆分到 FrontRoutes 与 AdminRoutes 之中配置的好处:
|
|
* 1:可分别配置不同的 baseViewPath 与 Interceptor
|
|
* 2:避免多人协同开发时,频繁修改此文件带来的版本冲突
|
|
* 3:避免本文件中内容过多,拆分后可读性增强
|
|
* 4:便于分模块管理路由
|
|
*/
|
|
public void configRoute(Routes me) {
|
|
// 改用扫描路由,手动注册路由不再使用,FrontRoutes、AdminRoutes 已被删除
|
|
|
|
/**
|
|
* 扫描后台路由
|
|
*/
|
|
me.add(new Routes() {
|
|
public void config() {
|
|
// 添加后台管理拦截器,将拦截在此方法中注册的所有 Controller
|
|
this.addInterceptor(new AdminAuthInterceptor());
|
|
this.addInterceptor(new PjaxInterceptor());
|
|
|
|
this.setBaseViewPath("/_view/_admin");
|
|
|
|
// 如果被扫描的包在 jar 文件之中,需要添加如下配置:
|
|
// undertow.hotSwapClassPrefix = com.bt._admin.
|
|
this.scan("com.bt._admin.");
|
|
}
|
|
});
|
|
|
|
/**
|
|
* 扫描前台路由
|
|
*
|
|
* 注意:
|
|
* 1:scan(...) 方法要添加过滤,过滤掉后台路由,否则后台路由会被扫描到,
|
|
* 造成 baseViewPath 以及 routes 级别的拦截器配置错误
|
|
*
|
|
* 2: 由于 scan(...) 内部避免了重复扫描同一个类,所以需要将扫描前台路由代码
|
|
* 放在扫描后台路由之前才能验证没有过滤造成的后果
|
|
*/
|
|
me.add(new Routes() {
|
|
public void config() {
|
|
this.setBaseViewPath("/_view");
|
|
|
|
// 如果被扫描的包在 jar 文件之中,需要添加如下配置:
|
|
// undertow.hotSwapClassPrefix = com.bt.
|
|
this.scan("com.bt.", className -> {
|
|
// className 为当前正扫描的类名,返回 true 时表示过滤掉当前类不扫描
|
|
return className.startsWith("com.bt._admin.");
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 配置模板引擎,通常情况只需配置共享的模板函数
|
|
*/
|
|
public void configEngine(Engine me) {
|
|
me.setDevMode(p.getBoolean("engineDevMode", false));
|
|
|
|
// 开启压缩功能,常用配置参数有: ' ' 与 '\n'
|
|
// me.setCompressorOn('\n');
|
|
|
|
// 配置用于主菜单的 URL,导航到 https://jfinal.com
|
|
me.addSharedObject("SSL", p.get("SSL"));
|
|
|
|
/**
|
|
* 用于在页面中使用 field 表达式代替 static field 表达式,节省代码量
|
|
*
|
|
* 例如:
|
|
* Feedback.REPORT_BLOCK_NUM
|
|
* 可代替
|
|
* com.jfinal.club.common.model.Feedback::REPORT_BLOCK_NUM
|
|
*/
|
|
me.addSharedObject("Feedback", new Feedback());
|
|
me.addSharedObject("Project", new Project());
|
|
me.addSharedObject("Share", new Share());
|
|
me.addSharedObject("Document", new Document());
|
|
|
|
// 添加角色、权限指令
|
|
me.addDirective("role", RoleDirective.class);
|
|
me.addDirective("permission", PermissionDirective.class);
|
|
me.addDirective("perm", PermissionDirective.class); // 配置一个别名指令
|
|
|
|
// 添加角色、权限 shared method
|
|
me.addSharedMethod(AdminAuthKit.class);
|
|
|
|
me.addSharedFunction("/_view/common/__layout.html");
|
|
me.addSharedFunction("/_view/common/__official_layout.html");
|
|
me.addSharedFunction("/_view/common/__front_layout.html");
|
|
me.addSharedFunction("/_view/common/__b5layout.html");
|
|
me.addSharedFunction("/_view/common/_paginate.html");
|
|
|
|
me.addSharedFunction("/_view/_admin/common/__admin_layout.html");
|
|
me.addSharedFunction("/_view/_admin/common/_admin_paginate.html");
|
|
}
|
|
|
|
/**
|
|
* 抽取成独立的方法,便于 _Generator 中重用该方法,减少代码冗余
|
|
*/
|
|
public static DruidPlugin getDruidPlugin() {
|
|
loadConfig();
|
|
return new DruidPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password"));
|
|
}
|
|
|
|
public void configPlugin(Plugins me) {
|
|
DruidPlugin druidPlugin = getDruidPlugin();
|
|
wallFilter = new WallFilter(); // 加强数据库安全
|
|
wallFilter.setDbType("mysql");
|
|
druidPlugin.addFilter(wallFilter);
|
|
druidPlugin.addFilter(new StatFilter()); // 添加 StatFilter 才会有统计数据
|
|
me.add(druidPlugin);
|
|
|
|
ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
|
|
arp.setTransactionLevel(Connection.TRANSACTION_READ_COMMITTED);
|
|
_MappingKit.mapping(arp);
|
|
// 强制指定复合主键的次序,避免不同的开发环境生成在 _MappingKit 中的复合主键次序不相同
|
|
arp.setPrimaryKey("document", "mainMenu,subMenu");
|
|
me.add(arp);
|
|
arp.setShowSql(p.getBoolean("devMode", false));
|
|
|
|
arp.getEngine().setToClassPathSourceFactory();
|
|
arp.addSqlTemplate("/com/bt/common/_all_sqls.sql");
|
|
|
|
me.add(new EhCachePlugin());
|
|
me.add(new Cron4jPlugin(p));
|
|
}
|
|
|
|
public void configInterceptor(Interceptors me) {
|
|
me.add(new LoginSessionInterceptor());
|
|
}
|
|
|
|
public void configHandler(Handlers me) {
|
|
me.add(DruidKit.getDruidStatViewHandler()); // druid 统计页面功能
|
|
me.add(new UrlSeoHandler()); // index、detail 两类 action 的 url seo
|
|
}
|
|
|
|
/**
|
|
* 本方法会在 jfinal 启动过程完成之后被回调,详见 jfinal 手册
|
|
*/
|
|
public void onStart() {
|
|
// 调用不带参的 renderJson() 时,排除对 loginAccount、remind 的 json 转换
|
|
JsonRender.addExcludedAttrs(
|
|
LoginService.loginAccountCacheName,
|
|
LoginSessionInterceptor.remindKey,
|
|
FriendInterceptor.followNum, FriendInterceptor.fansNum, FriendInterceptor.friendRelation
|
|
);
|
|
|
|
// 让 druid 允许在 sql 中使用 union
|
|
// https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE-wallfilter
|
|
wallFilter.getConfig().setSelectUnionCheck(false);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|