浅析初始化过程

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

jfinal

com.jfinal.core.JFinalFilter

configClass

com.fw.config.MppConfig

jfinal

/*

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

public final class JFinalFilter implementsFilter {privateHandler handler;privateString encoding;privateJFinalConfig jfinalConfig;privateConstants constants;private static final JFinal jfinal =JFinal.me();private staticLog log;private intcontextPathLength;public void init(FilterConfig filterConfig) throwsServletException {

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 voidcreateJFinalConfig(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 instanceofJFinalConfig)

jfinalConfig=(JFinalConfig)temp;else

throw 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

booleaninit(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 voidinitPathUtil() {

String path= servletContext.getRealPath("/");

PathKit.setWebRootPath(path);

}

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

static voidconfigJFinal(JFinalConfig jfinalConfig) {

jfinalConfig.configConstant(constants); initLogFactory();

jfinalConfig.configRoute(routes);

jfinalConfig.configPlugin(plugins); startPlugins();//very important!!!

jfinalConfig.configInterceptor(interceptors);

jfinalConfig.configHandler(handlers);

}

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

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

 public class MppConfig extendsJFinalConfig {//配置常量

public voidconfigConstant(Constants me) {

PropKit.use("jdbc.properties");

me.setDevMode(PropKit.getBoolean("devMode", false));

}//配置路由

public voidconfigRoute(Routes me) {

me.add(newRoutesMapping());

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

}//配置插件

public voidconfigPlugin(Plugins me) {//配置C3p0数据库连接池插件

C3p0Plugin C3p0Plugin =createC3p0Plugin();

me.add(C3p0Plugin);//配置ActiveRecord插件

ActiveRecordPlugin arp = newActiveRecordPlugin(C3p0Plugin);

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

arp.setContainerFactory(newCaseInsensitiveContainerFactory());//缓存插件

me.add(newEhCachePlugin());//所有配置在 MappingKit 中搞定

ModelMapping.mapping(arp);

}//配置全局拦截器

public voidconfigInterceptor(Interceptors me) {

me.add(new SessionInViewInterceptor());//session拦截器,用于在View模板中取出session值

}//配置处理器,接管所有 web 请求

public voidconfigHandler(Handlers me) {

me.add(new ContextPathHandler("contextPath"));//设置上下文路径

}//系统启动完成后回调,如创建调度线程

public voidafterJFinalStart(){}//系统关闭前回调,如写回缓存

public voidbeforeJFinalStop(){}

}View Code

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

initActionMapping();

initHandler();

initRender();

initOreillyCos();

initTokenManager();

Init ActionMapping

private voidinitActionMapping() {

actionMapping= newActionMapping(Config.getRoutes(), Config.getInterceptors());

actionMapping.buildActionMapping();

Config.getRoutes().clear();

}

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

final classActionMapping {private static final String SLASH = "/";privateRoutes routes;//ActionMapping 映射

private final Map mapping = new HashMap();//构造方法,routes 参数传进来

ActionMapping(Routes routes, Interceptors interceptors) {this.routes =routes;

}private SetbuildExcludedMethodName() {

Set excludedMethodName = new HashSet();

Method[] methods= Controller.class.getMethods();for(Method m : methods) {if (m.getParameterTypes().length == 0)

excludedMethodName.add(m.getName());

}returnexcludedMethodName;

}voidbuildActionMapping() {//初始化,我将要向里面塞东西了,要清空一下

mapping.clear();//这个方法返回的是 Controller接口的所有方法集合。

Set excludedMethodName =buildExcludedMethodName();//得到 InterceptorManager 的实例

InterceptorManager interMan =InterceptorManager.me();//遍历一个 Entry 集合。Entry 的 key 为访问路径,value 为其对应的 Controller。

for (Entry>entry : routes.getEntrySet()) {//得到访问路径对应的 Controller class

Class 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 = newAction(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));//填充 HashMap(访问路径为 key,Action 为 value)

if (mapping.put(actionKey, action) != null)throw newRuntimeException(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 voidinitHandler() {

Handler actionHandler= newActionHandler(actionMapping, constants);

handler=HandlerFactory.getHandler(Config.getHandlers().getHandlerList(), actionHandler);

}

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

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

public classHandlerFactory {privateHandlerFactory() {}/*** 创建一个 handler 链条,最后返回的 result 是 handler 链的头部,链尾是 ActionHandler*/@SuppressWarnings("deprecation")public static Handler getHandler(ListhandlerList, 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;

}returnresult;

}

}

Init Render

private voidinitRender() {

RenderFactory.me().init(constants, servletContext);

}

继续跟~

public classRenderFactory {public voidinit(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= newFreeMarkerRenderFactory();

}else if (defaultViewType ==ViewType.JSP) {

mainRenderFactory= newJspRenderFactory();

}else if (defaultViewType ==ViewType.VELOCITY) {

mainRenderFactory= newVelocityRenderFactory();

}else{throw new RuntimeException("View Type can not be null.");

}

}//创建 errorRenderFactory

if (errorRenderFactory == null) {

errorRenderFactory= newErrorRenderFactory();

}if (xmlRenderFactory == null) {

xmlRenderFactory= newXmlRenderFactory();

}

}private voidinitFreeMarkerRender(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 extendsRender {private static final String contentType = "text/html; charset=" +getEncoding();private static final Configuration config = newConfiguration();static void init(ServletContext servletContext, Locale locale, inttemplate_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 voidinitOreillyCos() {

OreillyCos.init(constants.getBaseUploadPath(), constants.getMaxPostSize(), constants.getEncoding());

}

很简单,附上相关代码:

public classOreillyCos {//先加载上传组件

public static void init(String uploadPath, intmaxPostSize, 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, intmaxPostSize, 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 extendsHttpServletRequestWrapper {private staticString baseUploadPath;private static intmaxPostSize;private staticString encoding;static void init(String baseUploadPath, intmaxPostSize, String encoding) {

MultipartRequest.baseUploadPath=baseUploadPath;

MultipartRequest.maxPostSize=maxPostSize;

MultipartRequest.encoding=encoding;

}//...

}

View Code

Init Token令牌

private voidinitTokenManager() {

ITokenCache tokenCache=constants.getTokenCache();if (tokenCache != null)

TokenManager.init(tokenCache);

}

先给个代码吧:

public classTokenManager {private staticITokenCache tokenCache;private static Random random = newRandom();privateTokenManager() {

}public static voidinit(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 voidrun() {removeTimeOutToken();}},

halfTimeOut,

halfTimeOut);

}//...

}

----- End -----

JFinal的详细介绍:请点这里

JFinal的下载地址:请点这里

jfinal linux编码,JFinal 的初始化相关推荐

  1. Swift3.0语言教程使用编码创建和初始化字符串

    Swift3.0语言教程使用编码创建和初始化字符串 使用编码创建和初始化字符串 创建和初始化字符串除了可以使用上文中提到的方法外,还可以使用init(coder:)方法,此方法一般不常使用,其语法形式 ...

  2. 在Linux系统下初始化COM组件,Linux操作系统的引导和初始化.doc

    Linux操作系统的引导和初始化 系统引导和初始化概述 相关代码(引导扇区的程序及其辅助程序,以x86体系为例): \linux-2.4.22\arch\i386\boot\bootsect.S:Li ...

  3. linux usb host复位,Linux USB Host-Controller的初始化代码框架分析

    Linux USB Host-Controller的初始化代码框架分析 http://blog.csdn.net/zkami usb_hcd_omap_probe (const struct hc_d ...

  4. linux中断初始化程序,Linux x86_64 内核中断初始化

    Linux x86_64 内核中断初始化 中断分类 Linux 系统中, 中断分为: 硬中断: 由外部设备或者执行异常产生的需要快速处理的中断如缺页中断定时器硬件中断 根据内部产生还是外部产生, 分为 ...

  5. Astyle Linux编码风格配置

    一.安装Astyle 1.1 下载Astyle 下载地址:  Artistic Style download | SourceForge.net 1.2 安装Astyle Astyle是免安装的,只需 ...

  6. jfinal linux 乱码,分享JFinal中renderFile方法中文文件名乱码问题的解决办法

    最近在一直在使用JFinal进行web项目的开发工作,使用起来感觉非常之方便效率,不愧是名为急速WEB开发框架,呵呵! 废话不说,进入正题.项目开发过程中经常遇到文件的上传于下载,JFinal中提供的 ...

  7. linux编码安装mysql_在Ubuntu 15.10下安装mysql设置数据库编码

    在从windows 10 的开发环境换到Ubuntu 15.10 后,发现原来的项目竟然不能正常地对数据库进行初始化,后来在控制台查看后,发现是数据库编码的问题. 1.在Ubuntu中安装mysql可 ...

  8. linux 3.4内核初始化,S3C2440移植linux3.4.2内核之内核框架介绍及简单修改

    @[TOC] uboot启动内核分析 进入cmd_bootm.c,找到对应的bootm命令对应的do_bootm():int do_bootm(cmd_tbl_t *cmdtp, int flag, ...

  9. linux c 结构体初始化的四种方法

    定义: struct InitMember {int first:double second:char* third:float four; }; 方法一:定义时赋值 struct InitMembe ...

最新文章

  1. 菜鸟要做架构师(二)——java性能优化之for循环
  2. 通过path绘制点击区域
  3. LINUX下统计代码行数
  4. 基因编辑婴儿追踪:该被编辑的是我们的心
  5. 基于MVC4+EasyUI的Web开发框架经验总结(6)--在页面中应用下拉列表的处理
  6. python中索引和下标_Series下标索引、标签索引、切片索引、布尔索引
  7. python 怎么样才有output_[学]Python用户手册笔记_4_Input and Output
  8. oracle 导入导出数据库、删除用户以及该用户所有的对象
  9. 新写的一个商品比较控件CompareGrid,没有做设计视图。有兴趣的联络我。公布源码。...
  10. docker 数据卷 mysql_Docker 数据卷
  11. 一套价值十万的微信公众号采集解决方案
  12. matlab幅度归一化,matlab归一化方法
  13. H5倍速播放视频播放器(2x/1.5x/0.5x播放)
  14. 使用爱思助手备份苹果手机数据的方法
  15. lighttp 配置php扩展包,Lighttpd配置
  16. ROS2初学者教程(Dashing和Eloquent)Windows
  17. [ - OpenGLES3.0 - ] 第一集 主线 - 打开新世界的大门
  18. 优秀的免费高清图片素材网站推荐
  19. js 排班插件_js jquery 实现 排班,轮班,日历,日程。使用fullcalendar 插件
  20. Swift语法学习--字典

热门文章

  1. 京东与阿里要用区块链打击假货 造假将无可遁形
  2. 通过CFA一级有用吗?是什么水平?
  3. 永续合约系统开发功能亮点
  4. 【JiyaChieng】(壹)Chieng_v1.0
  5. C语言输入输出重定向与fopen函数使用详解
  6. 计算机毕业论文java毕业设计成品源码网站springMVC图书管理系统|借阅[包运行成功]
  7. -uc/OS系统移植(基于STM32F103C8T6,超详细讲解)
  8. Nature Biotechnol: 用16S及18S rRNA全长进行微生物多样性研究
  9. 【自动驾驶】车辆运动学模型
  10. 博弈论——1218:取石子游戏