未加星标

JFinal 的初始化

字体大小 | |
[系统(linux) 所属分类 系统(linux) | 发布者 店小二05 | 时间 20160901 | 作者 红领巾 ] 0人收藏点击收藏
浅析初始化过程

首先要从 web 容器进行初始化

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<filter>
<filter-name>jfinal</filter-name>
<filter-class>com.jfinal.core.JFinalFilter</filter-class>
<init-param><param-name>configClass</param-name><param-value>com.fw.config.MppConfig</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>jfinal</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

从 web.xml 可以看出,容器初始化的时候会加载 JFinalFilter 这个类并且调用其 init 方法。

public final class JFinalFilter implements Filter {

private Handler handler;
private String encoding;
private JFinalConfig jfinalConfig;
private Constants constants;
private static final JFinal jfinal = JFinal.me();
private static Log log;
private int contextPathLength;

public void init(FilterConfig filterConfig) throws ServletException {
createJFinalConfig(filterConfig.getInitParameter("configClass"));

if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false)throw new RuntimeException("JFinal init error!");

handler = jfinal.getHandler();
constants = Config.getConstants();
encoding = constants.getEncoding();
jfinalConfig.afterJFinalStart();

String contextPath = filterConfig.getServletContext().getContextPath();
contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length());
}

private void createJFinalConfig(String configClass) {
if (configClass == null)throw new RuntimeException("Please set configClass parameter of JFinalFilter in web.xml");

Object temp = null;
try {temp = Class.forName(configClass).newInstance();
} catch (Exception e) {throw new RuntimeException("Can not create instance of class: " + configClass, e);
}

if (temp instanceof JFinalConfig)jfinalConfig = (JFinalConfig)temp;
elsethrow new RuntimeException("Can not create instance of class: " + configClass + ". Please check the config in web.xml");
}
// ...
}

init 方法中的参数正是 web.xml 中的 JFinalFilter 的初始化参数,即 com.fw.config.MppConfig,它继承于 JFinalConfig,在 createJFinalConfig 中利用该参数使用反射机制得到 JFinalConfig 的实例。

jfinal.init

boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
this.servletContext = servletContext;
this.contextPath = servletContext.getContextPath();

initPathUtil();

Config.configJFinal(jfinalConfig);
constants = Config.getConstants();

initActionMapping();
initHandler();
initRender();
initOreillyCos();
initTokenManager();

return true;
}

第一、initPathUtil,初始化 Path工具类的 webRootPath(即项目根路径)。

private void initPathUtil() {
String path = servletContext.getRealPath("/");
PathKit.setWebRootPath(path);
}

第二、Config.configJFinal 加载 JFinalConfig 实例,进行一些配置。

static void configJFinal(JFinalConfig jfinalConfig) {
jfinalConfig.configConstant(constants); initLogFactory();
jfinalConfig.configRoute(routes);
jfinalConfig.configPlugin(plugins); startPlugins(); // very important!!!
jfinalConfig.configInterceptor(interceptors);
jfinalConfig.configHandler(handlers);
}

配置常量,初始化 Log 工具类,配置路由,配置插件,开启插件,配置拦截器,配置 handler。

下面看看我项目中的 JFinalConfig 实例。


JFinal 的初始化
public class MppConfig extends JFinalConfig {

//配置常量
public void configConstant(Constants me) {
PropKit.use("jdbc.properties");
me.setDevMode(PropKit.getBoolean("devMode", false));
}

//配置路由
public void configRoute(Routes me) {
me.add(new RoutesMapping());
}

public static C3p0Plugin createC3p0Plugin() {
return new C3p0Plugin(PropKit.get("jdbcUrl"), PropKit.get("user"), PropKit.get("password").trim());
}

//配置插件
public void configPlugin(Plugins me) {
// 配置C3p0数据库连接池插件
C3p0Plugin C3p0Plugin = createC3p0Plugin();
me.add(C3p0Plugin);

// 配置ActiveRecord插件
ActiveRecordPlugin arp = new ActiveRecordPlugin(C3p0Plugin);
me.add(arp);

// 配置属性名(字段名)大小写不敏感容器工厂 Oracle
arp.setContainerFactory(new CaseInsensitiveContainerFactory());

//缓存插件
me.add(new EhCachePlugin());

// 所有配置在 MappingKit 中搞定
ModelMapping.mapping(arp);
}

//配置全局拦截器
public void configInterceptor(Interceptors me) {
me.add(new SessionInViewInterceptor());//session拦截器,用于在View模板中取出session值
}

//配置处理器,接管所有 web 请求
public void configHandler(Handlers me) {
me.add(new ContextPathHandler("contextPath"));//设置上下文路径
}

//系统启动完成后回调,如创建调度线程
public void afterJFinalStart(){}

//系统关闭前回调,如写回缓存
public void beforeJFinalStop(){}
}View Code

第三、初始化 ActionMapping、Handler、Render等。

initActionMapping();
initHandler();
initRender();
initOreillyCos();
initTokenManager();
Init ActionMapping
private void initActionMapping() {
actionMapping = new ActionMapping(Config.getRoutes(), Config.getInterceptors());
actionMapping.buildActionMapping();
Config.getRoutes().clear();
}

第一、创建 ActionMapping,映射所有访问路径和其对应的Action,填充得到一个 HashMap。下面是创建 ActionMapping 代码和注释,涉及到其他类的源码请自行查看。


JFinal 的初始化
final class ActionMapping {

private static final String SLASH = "/";
private Routes routes;

// ActionMapping 映射
private final Map<String, Action> mapping = new HashMap<String, Action>();

// 构造方法,routes 参数传进来
ActionMapping(Routes routes, Interceptors interceptors) {
this.routes = routes;
}

private Set<String> buildExcludedMethodName() {
Set<String> excludedMethodName = new HashSet<String>();
Method[] methods = Controller.class.getMethods();
for (Method m : methods) {if (m.getParameterTypes().length == 0) excludedMethodName.add(m.getName());
}
return excludedMethodName;
}


void buildActionMapping() {
// 初始化,我将要向里面塞东西了,要清空一下
mapping.clear();

// 这个方法返回的是 Controller接口的所有方法集合。
Set<String> excludedMethodName = buildExcludedMethodName();

// 得到 InterceptorManager 的实例
InterceptorManager interMan = InterceptorManager.me();

// 遍历一个 Entry 集合。Entry 的 key 为访问路径,value 为其对应的 Controller。
for (Entry<String, Class<? extends Controller>> entry : routes.getEntrySet()) {// 得到访问路径对应的 Controller classClass<? extends Controller> controllerClass = entry.getValue();// 如果 Controller class没有拦截器注解,则返回一个空数组。反之返回这个类所有拦截器组成的数组Interceptor[] controllerInters = interMan.createControllerInterceptor(controllerClass);boolean sonOfController = (controllerClass.getSuperclass() == Controller.class); // 这里必定为 true// getDeclaredMethods 得到这个类的所有方法以及其接口的所有方法,不包括继承的方法Method[] methods = (sonOfController ? controllerClass.getDeclaredMethods() : controllerClass.getMethods());for (Method method : methods) { String methodName = method.getName(); //若这个方法是继承自 Controller的方法 或 该方法有参数,过滤掉 if (excludedMethodName.contains(methodName) || method.getParameterTypes().length != 0) continue ; // 若这个方法不是 public 方法,过滤掉 if (sonOfController && !Modifier.isPublic(method.getModifiers())) continue ; // 想进行到这里,这个方法必须满足:不是继承自 Controller、不能有参数、必须是 public 方法 // 得到包含所有拦截器的数组(包括全局的拦截器,类级别的拦截器、方法级别的拦截器) Interceptor[] actionInters = interMan.buildControllerActionInterceptor(controllerInters, controllerClass, method); String controllerKey = entry.getKey(); ActionKey ak = method.getAnnotation(ActionKey.class); String actionKey; // ActionKey 不为空的话为设置自定义的访问路径(说明有方法被注有 @ActionKey 注解) if (ak != null) { actionKey = ak.value().trim(); if ("".equals(actionKey)) throw new IllegalArgumentException(controllerClass.getName() + "." + methodName + "(): The argument of ActionKey can not be blank."); if (!actionKey.startsWith(SLASH)) actionKey = SLASH + actionKey; } // ActionKey为空,methodName 为 index的情况下:actionKey = controllerKey else if (methodName.equals("index")) { actionKey = controllerKey; } // ActionKey为空,methodName 不为 index的情况下:actionKey = controllerKey +"/" + methodName else { actionKey = controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName; } // 组合装配成一个 Action Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey)); // 填充 HashMap(访问路径为 key,Action 为 value) if (mapping.put(actionKey, action) != null) throw new RuntimeException(buildMsg(actionKey, controllerClass, method));}
}

// support url = controllerKey + urlParas with "/" of controllerKey
Action action = mapping.get("/");
if (action != null)mapping.put("", action);
}

// ...
}
View Code

第二、Config.routes 已经用过了,以后也不会再用上了,清空路由的所有信息。

Init Handler
private void initHandler() {
Handler actionHandler = new ActionHandler(actionMapping, constants);
handler = HandlerFactory.getHandler(Config.getHandlers().getHandlerList(), actionHandler);
}

第一、创建一个 ActionHandler 实例 actionHandler。

第二、HandlerFactory.getHandler 创建一个 Handler 链,链尾是 actionHandler,并且返回链首。

public class HandlerFactory {

private HandlerFactory() {}

/**
* 创建一个 handler 链条,最后返回的 result 是 handler 链的头部,链尾是 ActionHandler
*/
@SuppressWarnings("deprecation")
public static Handler getHandler(List<Handler> handlerList, Handler actionHandler) {
Handler result = actionHandler;

for (int i=handlerList.size()-1; i>=0; i--) {Handler temp = handlerList.get(i);temp.next = result;temp.nextHandler = result;result = temp;
}

return result;
}
}
Init Render
private void initRender() {
RenderFactory.me().init(constants, servletContext);
}

继续跟~

public class RenderFactory {

public void init(Constants constants, ServletContext servletContext) {
this.constants = constants;
this.servletContext = servletContext;

// 初始化 Render
Render.init(constants.getEncoding(), constants.getDevMode()); // 初始化编码和开发模式
initFreeMarkerRender(servletContext); // 初始化 FreeMarkerRender
initVelocityRender(servletContext);
initJspRender(servletContext);
initFileRender(servletContext);

// 创建 mainRenderFactory
if (mainRenderFactory == null) {
ViewType defaultViewType = constants.getViewType();
if (defaultViewType == ViewType.FREE_MARKER) {
mainRenderFactory = new FreeMarkerRenderFactory();
} else if (defaultViewType == ViewType.JSP) {
mainRenderFactory = new JspRenderFactory();
} else if (defaultViewType == ViewType.VELOCITY) {
mainRenderFactory = new VelocityRenderFactory();
} else {
throw new RuntimeException("View Type can not be null.");
}
}

// 创建 errorRenderFactory
if (errorRenderFactory == null) {
errorRenderFactory = new ErrorRenderFactory();
}

if (xmlRenderFactory == null) {
xmlRenderFactory = new XmlRenderFactory();
}
}

private void initFreeMarkerRender(ServletContext servletContext) {
try {
Class.forName("freemarker.template.Template"); // 加载 freemarker 模板
FreeMarkerRender.init(servletContext, Locale.getDefault(), constants.getFreeMarkerTemplateUpdateDelay());
} catch (ClassNotFoundException e) {
// 若加载模板失败,比如没有引入 jar 包
LogKit.logNothing(e);
}
}

// ...
}
public class FreeMarkerRender extends Render {

private static final String contentType = "text/html; charset=" + getEncoding();
private static final Configuration config = new Configuration();


static void init(ServletContext servletContext, Locale locale, int template_update_delay) {
// 初始化 freemarker 配置:config = new Configuration();
// 设置 freemarker 页面的存放位置为项目根路径
config.setServletContextForTemplateLoading(servletContext, "/");

// 设置开发模式下更新延迟时间
if (getDevMode()) {
config.setTemplateUpdateDelay(0);
}
else {
config.setTemplateUpdateDelay(template_update_delay);
}

// - Set an error handler that prints errors so they are readable with
// a HTML browser.
// config.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

// - Use beans wrapper (recommmended for most applications)
config.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
config.setDefaultEncoding(getEncoding()); // 设置默认编码
config.setOutputEncoding(getEncoding()); // 设置输出编码
// - Set the default locale
config.setLocale(locale /* Locale.CHINA */ ); // 设置时区
config.setLocalizedLookup(false);

// 去掉int型输出时的逗号, 例如: 123,456
// config.setNumberFormat("#"); // config.setNumberFormat("0"); 也可以
config.setNumberFormat("#0.#####");
config.setDateFormat("yyyy-MM-dd");
config.setTimeFormat("HH:mm:ss");
config.setDateTimeFormat("yyyy-MM-dd HH:mm:ss");
}

// ...
}
Init 上传组件
private void initOreillyCos() {
OreillyCos.init(constants.getBaseUploadPath(), constants.getMaxPostSize(), constants.getEncoding());
}

很简单,附上相关代码:


JFinal 的初始化
public class OreillyCos {

// 先加载上传组件
public static void init(String uploadPath, int maxPostSize, String encoding) {
if (StrKit.isBlank(uploadPath)) {
throw new IllegalArgumentException("uploadPath can not be blank.");
}
try {
Class.forName("com.oreilly.servlet.MultipartRequest");
doInit(uploadPath, maxPostSize, encoding);
}catch (ClassNotFoundException e) {
LogKit.logNothing(e);
}
}

private static void doInit(String uploadPath, int maxPostSize, String encoding) {
uploadPath= uploadPath.trim();
uploadPath= uploadPath.replaceAll("\\\\", "/");

String baseUploadPath;

// 判断上传路径是否是绝对路径,如果不是把它加工成绝对路径
if (PathKit.isAbsolutelyPath(uploadPath)) {
baseUploadPath= uploadPath;
}else {
baseUploadPath= PathKit.getWebRootPath() + File.separator + uploadPath;
}

// remove "/" postfix
if (baseUploadPath.equals("/") == false) {
if (baseUploadPath.endsWith("/")) {
baseUploadPath= baseUploadPath.substring(0, baseUploadPath.length() - 1);
}
}

MultipartRequest.init(baseUploadPath, maxPostSize, encoding);
}

// ...
}
public class MultipartRequest extends HttpServletRequestWrapper {

private static String baseUploadPath;
private static int maxPostSize;
private static String encoding;

static void init(String baseUploadPath, int maxPostSize, String encoding) {
MultipartRequest.baseUploadPath= baseUploadPath;
MultipartRequest.maxPostSize= maxPostSize;
MultipartRequest.encoding= encoding;
}

// ...
}
View Code
Init Token令牌
private void initTokenManager() {
ITokenCache tokenCache = constants.getTokenCache();
if (tokenCache != null)
TokenManager.init(tokenCache);
}

先给个代码吧:

public class TokenManager {

private static ITokenCache tokenCache;
private static Random random = new Random();

private TokenManager() {

}

public static void init(ITokenCache tokenCache) {
if (tokenCache == null)return;

TokenManager.tokenCache = tokenCache;

long halfTimeOut = Const.MIN_SECONDS_OF_TOKEN_TIME_OUT * 1000 / 2; // Token最小过期时间的一半时间作为任务运行的间隔时间
new Timer().schedule(new TimerTask() {public void run() {removeTimeOutToken();}}, halfTimeOut, halfTimeOut);
}

// ...
}

----- End -----

Jfinal学习之路---Controller使用 http://www.linuxidc.com/Linux/2014-07/104323.htm

JFinal开发8个常见问题 http://www.codesec.net/Linux/2015-02/113421.htm

JFinal的详细介绍:请点这里
JFinal的下载地址:请点这里

本文地址:http://www.codesec.net/Linux/2016-09/135258.htm


JFinal 的初始化

本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统

主题: LinuxHTMLJSPXMLUT数据ETHCITTI数据库
分页:12
转载请注明
本文标题:JFinal 的初始化
本站链接:http://www.codesec.net/view/483488.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 系统(linux) | 评论(0) | 阅读(35)