public void init(FilterConfig filterConfig) throws ServletException { this.createJFinalConfig(filterConfig.getInitParameter("configClass")); if (!jfinal.init(this.jfinalConfig, filterConfig.getServletContext())) { throw new RuntimeException("JFinal init error!"); } else { this.handler = jfinal.getHandler(); this.constants = Config.getConstants(); this.encoding = this.constants.getEncoding(); this.jfinalConfig.afterJFinalStart(); String contextPath = filterConfig.getServletContext().getContextPath(); this.contextPathLength = contextPath != null && !"/".equals(contextPath) ? contextPath.length() : 0; } }
public void init(FilterConfig filterConfig) throws boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
this.servletContext = servletContext; this.contextPath = servletContext.getContextPath(); this.initPathUtil(); Config.configJFinal(jfinalConfig); this.constants = Config.getConstants(); this.initActionMapping(); this.initHandler(); this.initRender(); this.initOreillyCos(); this.initTokenManager(); return true; }在初始化时调用 JFina里的
第一、initPathUtil,初始化 Path工具类的 webRootPath(即项目根路径)。
private void initPathUtil() { String path = this.servletContext.getRealPath("/"); PathKit.setWebRootPath(path); }
init 方法中的参数正是 web.xml 中的 JFinalFilter 的初始化参数,即 com.fw.config.MppConfig,它继承于 JFinalConfig,在 createJFinalConfig 中利用该参数使用反射机制得到 JFinalConfig 的实例。
第二、Config.configJFinal 加载 JFinalConfig 实例,进行一些配置。
配置常量,初始化 Log 工具类,配置路由,配置插件,开启插件,配置拦截器,配置 handler。
jfinalConfig.configConstant(constants);
static void configJFinal(JFinalConfig jfinalConfig) { jfinalConfig.configConstant(constants); initLogFactory(); initEngine(); jfinalConfig.configRoute(routes); jfinalConfig.configEngine(engine); jfinalConfig.configPlugin(plugins); startPlugins(); jfinalConfig.configInterceptor(interceptors); jfinalConfig.configHandler(handlers); }
jfinalConfig.configConstant(constants);
static void configJFinal(JFinalConfig jfinalConfig) { jfinalConfig.configConstant(constants); initLogFactory(); initEngine(); jfinalConfig.configRoute(routes); jfinalConfig.configEngine(engine); jfinalConfig.configPlugin(plugins); startPlugins(); jfinalConfig.configInterceptor(interceptors); jfinalConfig.configHandler(handlers); }
第三、初始化 ActionMapping、Handler、Render等
ActionMapping
private void initActionMapping() { this.actionMapping = new ActionMapping(Config.getRoutes(), Config.getInterceptors()); this.actionMapping.buildActionMapping(); Config.getRoutes().clear(); }第一、创建 ActionMapping,映射所有访问路径和其对应的Action,填充得到一个 HashMap。下面是创建 ActionMapping 代码和注释
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.core; import com.jfinal.aop.Interceptor; import com.jfinal.aop.InterceptorManager; import com.jfinal.config.Interceptors; import com.jfinal.config.Routes; import com.jfinal.config.Routes.Route; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; final class ActionMapping { private static final String SLASH = "/"; private Routes routes; private final Map<String, Action> mapping = new HashMap();// ActionMapping 映射 ActionMapping(Routes routes, Interceptors interceptors) {//构造方法参数传递进入来fu
this.routes = routes;
}
private
Set<String> buildExcludedMethodName() { Set<String> excludedMethodName =
new
HashSet()
;
Method[] methods = Controller.
class
.getMethods()
;
Method[] arr$ = methods
;
int
len$ = methods.length
;
for
(
int
i$ =
0
;
i$ < len$
;
++i$) { Method m = arr$[i$]
;
if
(m.getParameterTypes().length ==
0
) { excludedMethodName.add(m.getName())
;
} }
return
excludedMethodName
;
}
private
List<Routes> getRoutesList() { List<Routes> routesList = Routes.getRoutesList()
;
List<Routes> ret =
new
ArrayList(routesList.size() +
1
)
;
ret.add(
this
.routes)
;
ret.addAll(routesList)
;
return
ret
;
}
void
buildActionMapping() {// 初始化,我将要向里面塞东西了,要清空一下
this
.mapping.clear()
;Set<String> excludedMethodName = this .buildExcludedMethodName() ;//返回的是 Controller接口的所有方法集合 InterceptorManager interMan = InterceptorManager.me() ;// 得到 InterceptorManager 的实例 Iterator i$ = this .getRoutesList().iterator() ; while (i$.hasNext()) { // 遍历一个 Entry 集合。Entry 的 key 为访问路径,value 为其对应的 Controller。 Routes routes = (Routes)i$.next() ; Iterator i$ = routes.getRouteItemList().iterator() ; while (i$.hasNext()) { Route route = (Route)i$.next() ; Class<? extends Controller> controllerClass = route.getControllerClass() ; // 得到访问路径对应的 Controller class Interceptor[] controllerInters = interMan.createControllerInterceptor(controllerClass) ; // 如果 Controller class没有拦截器注解,则返回一个空数组。反之返回这个类所有拦截器组成的数组 boolean sonOfController = controllerClass.getSuperclass() == Controller. class; // 这里必定为 true,获取class Method[] methods = sonOfController ? controllerClass.getDeclaredMethods() : controllerClass.getMethods() ; //getDeclaredMethods 得到这个类的所有方法以及其接口的所有方法,不包括继承的方法 Method[] arr$ = methods ; int len$ = methods.length ; for ( int i$ = 0 ; i$ < len$ ; ++i$) { Method method = arr$[i$] ; String methodName = method.getName() ; if (!excludedMethodName.contains(methodName) && method.getParameterTypes().length == 0 && (!sonOfController || Modifier.isPublic(method.getModifiers()))) { //若这个方法是继承自 Controller的方法 或 该方法有参数,过滤掉 Interceptor[] actionInters = interMan.buildControllerActionInterceptor(routes.getInterceptors() , controllerInters , controllerClass , method) ; // 得到包含所有拦截器的数组(包括全局的拦截器,类级别的拦截器、方法级别的拦截器) String controllerKey = route.getControllerKey() ; //获取controller的路径key值 ActionKey ak = (ActionKey)method.getAnnotation(ActionKey. class ) ; String actionKey ; if (ak != null ) {
// ActionKey 不为空的话为设置自定义的访问路径(说明有方法被注有 @ActionKey 注解)
actionKey = ak.value().trim()
;
if
(
""
.equals(actionKey)) {
throw new
IllegalArgumentException(controllerClass.getName() +
"."
+ methodName +
"(): The argument of ActionKey can not be blank."
)
;
}
if
(!actionKey.startsWith(
"/"
)) { actionKey =
"/"
+ actionKey
;
} }
else if
(methodName.equals(
"index"
)) {
// ActionKey为空,methodName 为 index的情况下:actionKey = controllerKey
actionKey = controllerKey
;
}
else
{
// ActionKey为空,methodName 不为 index的情况下:actionKey = controllerKey +"/" + methodName
actionKey = controllerKey.equals(
"/"
) ?
"/"
+ methodName : controllerKey +
"/"
+ methodName
;
}
// 组合装配成一个 Action // 填充 HashMap(访问路径为 key,Action 为 value)
Action action =
new
Action(controllerKey
,
actionKey
,
controllerClass
,
method
,
methodName
,
actionInters
,
route.getFinalViewPath(routes.getBaseViewPath()))
;
if
(
this
.mapping.put(actionKey
,
action) !=
null
) {
throw new RuntimeException(buildMsg(actionKey, controllerClass, method));} } } } } this .routes.clear() ; Action action = (Action) this .mapping.get( "/" ) ; if (action != null ) { this .mapping.put( "" , action) ; } } private static final String buildMsg(String actionKey , Class<? extends Controller> controllerClass , Method method) { StringBuilder sb = ( new StringBuilder( "The action \" " )).append(controllerClass.getName()).append( "." ).append(method.getName()).append( "() \" can not be mapped, " ).append( "actionKey \" " ).append(actionKey).append( " \" is already in use." ) ; String msg = sb.toString() ; System.err.println( " \n Exception: " + msg) ; return msg ; } Action getAction(String url , String[] urlPara) { Action action = (Action) this .mapping.get(url) ; if (action != null ) { return action ; } else { int i = url.lastIndexOf( "/" ) ; if (i != - 1 ) { action = (Action) this .mapping.get(url.substring( 0 , i)) ; urlPara[ 0 ] = url.substring(i + 1 ) ; } return action ; } } List<String> getAllActionKeys() { List<String> allActionKeys = new ArrayList( this .mapping.keySet()) ; Collections.sort(allActionKeys) ; return allActionKeys ; }}
初始化Handler
第一、创建一个 ActionHandler 实例 actionHandler。
第二、HandlerFactory.getHandler 创建一个 Handler 链,链尾是 actionHandler,并且返回链首。
private void initHandler() { Handler actionHandler = new ActionHandler(this.actionMapping, this.constants); this.handler = HandlerFactory.getHandler(Config.getHandlers().getHandlerList(), actionHandler); }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.core; import com.jfinal.aop.Invocation; import com.jfinal.config.Constants; import com.jfinal.handler.Handler; import com.jfinal.log.Log; import com.jfinal.render.Render; import com.jfinal.render.RenderException; import com.jfinal.render.RenderManager; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ActionHandler extends Handler { private final boolean devMode; private final ActionMapping actionMapping; private static final RenderManager renderManager = RenderManager.me(); private static final Log log = Log.getLog(ActionHandler.class); public ActionHandler(ActionMapping actionMapping, Constants constants) { this.actionMapping = actionMapping; this.devMode = constants.getDevMode(); } public final void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) { if (target.indexOf(46) == -1) { isHandled[0] = true; String[] urlPara = new String[]{null}; Action action = this.actionMapping.getAction(target, urlPara); if (action == null) { if (log.isWarnEnabled()) { String qs = request.getQueryString(); log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs)); } renderManager.getRenderFactory().getErrorRender(404).setContext(request, response).render(); } else { String qs; String msg; try { Controller controller = (Controller)action.getControllerClass().newInstance(); controller.init(request, response, urlPara[0]); if (this.devMode) { if (ActionReporter.isReportAfterInvocation(request)) { (new Invocation(action, controller)).invoke(); ActionReporter.report(target, controller, action); } else { ActionReporter.report(target, controller, action); (new Invocation(action, controller)).invoke(); } } else { (new Invocation(action, controller)).invoke(); } Render render = controller.getRender(); if (render instanceof ForwardActionRender) { msg = ((ForwardActionRender)render).getActionUrl(); if (target.equals(msg)) { throw new RuntimeException("The forward action url is the same as before."); } this.handle(msg, request, response, isHandled); return; } if (render == null) { render = renderManager.getRenderFactory().getDefaultRender(action.getViewPath() + action.getMethodName()); } render.setContext(request, response, action.getViewPath()).render(); } catch (RenderException var11) { if (log.isErrorEnabled()) { qs = request.getQueryString(); log.error(qs == null ? target : target + "?" + qs, var11); } } catch (ActionException var12) { int errorCode = var12.getErrorCode(); msg = null; if (errorCode == 404) { msg = "404 Not Found: "; } else if (errorCode == 401) { msg = "401 Unauthorized: "; } else if (errorCode == 403) { msg = "403 Forbidden: "; } String qs; if (msg != null) { if (log.isWarnEnabled()) { qs = request.getQueryString(); log.warn(msg + (qs == null ? target : target + "?" + qs)); } } else if (log.isErrorEnabled()) { qs = request.getQueryString(); log.error(qs == null ? target : target + "?" + qs, var12); } var12.getErrorRender().setContext(request, response, action.getViewPath()).render(); } catch (Exception var13) { if (log.isErrorEnabled()) { qs = request.getQueryString(); log.error(qs == null ? target : target + "?" + qs, var13); } renderManager.getRenderFactory().getErrorRender(500).setContext(request, response, action.getViewPath()).render(); } } } } }
//
创建一个 handler 链条,最后返回的 result 是 handler 链的头部,链尾是 ActionHandler
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package
com.jfinal.handler
;
import
java.util.List
;
public class HandlerFactory {
private
HandlerFactory() { }
创建一个 handler 链条,最后返回的 result 是 handler 链的头部,链尾是 ActionHandler
public static
Handler getHandler(List<Handler> handlerList
,
Handler actionHandler) { Handler result = actionHandler
;
for
(
int
i = handlerList.size() -
1
;
i >=
0
;
--i) { Handler temp = (Handler)handlerList.get(i)
;
temp.next = result
;
temp.nextHandler = result
;
result = temp
;
}
return
result
;
}}
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.config; import com.jfinal.handler.Handler; import java.util.ArrayList; import java.util.List; public final class Handlers { private final List<Handler> handlerList = new ArrayList(); public Handlers() { } public Handlers add(Handler handler) { if (handler == null) { throw new IllegalArgumentException("handler can not be null"); } else { this.handlerList.add(handler); return this; } } public List<Handler> getHandlerList() { return this.handlerList; } }
初始化Render
private void initRender() { RenderManager.me().init(Config.getEngine(), this.constants, this.servletContext); }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.render; import com.jfinal.config.Constants; import com.jfinal.kit.LogKit; import com.jfinal.kit.PathKit; import com.jfinal.plugin.activerecord.ModelRecordElResolver; import com.jfinal.template.Engine; import java.io.File; import java.util.Locale; import javax.servlet.ServletContext; public class RenderManager { private Engine engine; private Constants constants; private ServletContext servletContext; private IRenderFactory renderFactory = null; private static final RenderManager me = new RenderManager(); private RenderManager() { } public static RenderManager me() { return me; } public IRenderFactory getRenderFactory() { return this.renderFactory; } public void setRenderFactory(IRenderFactory renderFactory) { if (renderFactory == null) { throw new IllegalArgumentException("renderFactory can not be null"); } else { this.renderFactory = renderFactory; } } public void init(Engine engine, Constants constants, ServletContext servletContext) { this.engine = engine; this.constants = constants; this.servletContext = servletContext; Render.init(constants.getEncoding(), constants.getDevMode()); this.initTemplateRender(); this.initFreeMarkerRender(servletContext); this.initVelocityRender(servletContext); this.initJspRender(servletContext); this.initFileRender(servletContext); if (this.renderFactory == null) { this.renderFactory = new RenderFactory(); } this.renderFactory.init(engine, constants, servletContext); } private void initTemplateRender() { TemplateRender.init(this.engine); } private void initFreeMarkerRender(ServletContext servletContext) { try { Class.forName("freemarker.template.Template"); FreeMarkerRender.init(servletContext, Locale.getDefault(), this.constants.getFreeMarkerTemplateUpdateDelay()); } catch (ClassNotFoundException var3) { LogKit.logNothing(var3); } } private void initVelocityRender(ServletContext servletContext) { try { Class.forName("org.apache.velocity.VelocityContext"); VelocityRender.init(servletContext); } catch (ClassNotFoundException var3) { LogKit.logNothing(var3); } } private void initJspRender(ServletContext servletContext) { try { Class.forName("javax.el.ELResolver"); Class.forName("javax.servlet.jsp.JspFactory"); ModelRecordElResolver.init(servletContext); } catch (ClassNotFoundException var3) { LogKit.logNothing(var3); } catch (IllegalStateException var4) { throw var4; } catch (Exception var5) { LogKit.logNothing(var5); } } private void initFileRender(ServletContext servletContext) { String downloadPath = this.constants.getBaseDownloadPath(); downloadPath = downloadPath.trim(); downloadPath = downloadPath.replaceAll("\\\\", "/"); String baseDownloadPath; if (PathKit.isAbsolutelyPath(downloadPath)) { baseDownloadPath = downloadPath; } else { baseDownloadPath = PathKit.getWebRootPath() + File.separator + downloadPath; } if (!baseDownloadPath.equals("/") && baseDownloadPath.endsWith("/")) { baseDownloadPath = baseDownloadPath.substring(0, baseDownloadPath.length() - 1); } FileRender.init(baseDownloadPath, servletContext); } public Engine getEngine() { return this.engine; } public Constants getConstants() { return this.constants; } public ServletContext getServletContext() { return this.servletContext; } }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.render; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public abstract class Render { protected String view; protected HttpServletRequest request; protected HttpServletResponse response; private static String encoding = "UTF-8"; private static boolean devMode = false; public Render() { } static void init(String encoding, boolean devMode) { encoding = encoding; devMode = devMode; } public static String getEncoding() { return encoding; } public static boolean getDevMode() { return devMode; } public Render setContext(HttpServletRequest request, HttpServletResponse response) { this.request = request; this.response = response; return this; } public Render setContext(HttpServletRequest request, HttpServletResponse response, String viewPath) { this.request = request; this.response = response; if (this.view != null && this.view.length() > 0 && this.view.charAt(0) != '/') { this.view = viewPath + this.view; } return this; } public String getView() { return this.view; } public void setView(String view) { this.view = view; } public abstract void render(); }
TemplateRender.init(this.engine);
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.render; import com.jfinal.template.Engine; import java.io.PrintWriter; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; public class TemplateRender extends Render { private static Engine engine; private static final String contentType = "text/html; charset=" + getEncoding(); static void init(Engine engine) { if (engine == null) { throw new IllegalArgumentException("engine can not be null"); } else { engine = engine; } } public TemplateRender(String view) { this.view = view; } public String getContentType() { return contentType; } public void render() { this.response.setContentType(this.getContentType()); Map<Object, Object> data = new HashMap(); Enumeration attrs = this.request.getAttributeNames(); while(attrs.hasMoreElements()) { String attrName = (String)attrs.nextElement(); data.put(attrName, this.request.getAttribute(attrName)); } PrintWriter writer = null; try { writer = this.response.getWriter(); engine.getTemplate(this.view).render(data, writer); } catch (Exception var7) { throw new RenderException(var7); } finally { if (writer != null) { writer.close(); } } } public String toString() { return this.view; } }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.render; import com.jfinal.core.JFinal; import freemarker.template.Configuration; import freemarker.template.ObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateException; import freemarker.template.TemplateExceptionHandler; import java.io.PrintWriter; import java.util.Enumeration; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Properties; import javax.servlet.ServletContext; public class FreeMarkerRender extends Render { private static final String contentType = "text/html; charset=" + getEncoding(); private static final Configuration config = new Configuration(); public FreeMarkerRender(String view) { this.view = view; } public static Configuration getConfiguration() { return config; } public static void setProperty(String propertyName, String propertyValue) { try { getConfiguration().setSetting(propertyName, propertyValue); } catch (TemplateException var3) { throw new RuntimeException(var3); } } public static void setSharedVariable(String name, Object object) { try { getConfiguration().setSharedVariable(name, object); } catch (TemplateException var3) { throw new RuntimeException(var3); } } public static void setProperties(Properties properties) { try { getConfiguration().setSettings(properties); } catch (TemplateException var2) { throw new RuntimeException(var2); } } public static void setTemplateLoadingPath(String path) { config.setServletContextForTemplateLoading(JFinal.me().getServletContext(), path); } //
// 初始化 freemarker 配置:config = new Configuration();
// 设置 freemarker 页面的存放位置为项目根路径
static void init(ServletContext servletContext, Locale locale, int template_update_delay) {
config.setServletContextForTemplateLoading(servletContext
,
"/"
)
;
if
(getDevMode()) {//
// 设置开发模式下更新延迟时间config.setTemplateUpdateDelay( 0 ) ; } else { config.setTemplateUpdateDelay(template_update_delay) ; } config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER) ; config.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER) ; config.setDefaultEncoding(getEncoding()) ;
// 设置默认编码// 设置输出编// 设置时区
// 去掉int型输出时的逗号, 例如: 123,456
setNumberFormat
config.setOutputEncoding(getEncoding())
;
config.setLocale(locale)
;
config.setLocalizedLookup(
false
)
;
config.setNumberFormat(
"#0.#####"
)
;
config.setDateFormat(
"yyyy-MM-dd"
)
;
config.setTimeFormat(
"HH:mm:ss"
)
;
config.setDateTimeFormat(
"yyyy-MM-dd HH:mm:ss"
)
;
}
public
String getContentType() {
return
contentType
;
}
public void
render() {
this
.response.setContentType(
this
.getContentType())
;
Map data =
new
HashMap()
;
Enumeration attrs =
this
.request.getAttributeNames()
;
while
(attrs.hasMoreElements()) { String attrName = (String)attrs.nextElement()
;
data.put(attrName
, this
.request.getAttribute(attrName))
;
} PrintWriter writer =
null;
try
{ Template template = config.getTemplate(
this
.view)
;
writer =
this
.response.getWriter()
;
template.process(data
,
writer)
;
}
catch
(Exception var7) {
throw new
RenderException(var7)
;
}
finally
{
if
(writer !=
null
) { writer.close()
;
} } }
Init 上传组件
private void initOreillyCos() { OreillyCos.init(this.constants.getBaseUploadPath(), this.constants.getMaxPostSize(), this.constants.getEncoding()); }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.upload; import com.jfinal.kit.LogKit; import com.jfinal.kit.PathKit; import com.jfinal.kit.StrKit; import com.oreilly.servlet.multipart.FileRenamePolicy; import java.io.File; public class OreillyCos { public OreillyCos() { } //加载上传组件 public static void init(String uploadPath, int maxPostSize, String encoding) { if (StrKit.isBlank(uploadPath)) { throw new IllegalArgumentException("uploadPath can not be blank."); } else { try { Class.forName("com.oreilly.servlet.MultipartRequest"); doInit(uploadPath, maxPostSize, encoding); } catch (ClassNotFoundException var4) { LogKit.logNothing(var4); } } } public static void setFileRenamePolicy(FileRenamePolicy fileRenamePolicy) { if (fileRenamePolicy == null) { throw new IllegalArgumentException("fileRenamePolicy can not be null."); } else { MultipartRequest.fileRenamePolicy = fileRenamePolicy; } } 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
;
}
if
(!baseUploadPath.equals(
"/"
) && baseUploadPath.endsWith(
"/"
)) { baseUploadPath = baseUploadPath.substring(
0
,
baseUploadPath.length() -
1
)
;
} MultipartRequest.init(baseUploadPath
,
maxPostSize
,
encoding)
;
}}
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.upload; import com.oreilly.servlet.multipart.DefaultFileRenamePolicy; import com.oreilly.servlet.multipart.FileRenamePolicy; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class MultipartRequest extends HttpServletRequestWrapper { private static String baseUploadPath; private static int maxPostSize; private static String encoding; static FileRenamePolicy fileRenamePolicy = new DefaultFileRenamePolicy(); private List<UploadFile> uploadFiles; private com.oreilly.servlet.MultipartRequest multipartRequest; static void init(String baseUploadPath, int maxPostSize, String encoding) { baseUploadPath = baseUploadPath; maxPostSize = maxPostSize; encoding = encoding; } public MultipartRequest(HttpServletRequest request, String uploadPath, int maxPostSize, String encoding) { super(request); this.wrapMultipartRequest(request, this.getFinalPath(uploadPath), maxPostSize, encoding); } public MultipartRequest(HttpServletRequest request, String uploadPath, int maxPostSize) { super(request); this.wrapMultipartRequest(request, this.getFinalPath(uploadPath), maxPostSize, encoding); } public MultipartRequest(HttpServletRequest request, String uploadPath) { super(request); this.wrapMultipartRequest(request, this.getFinalPath(uploadPath), maxPostSize, encoding); } public MultipartRequest(HttpServletRequest request) { super(request); this.wrapMultipartRequest(request, baseUploadPath, maxPostSize, encoding); } private String getFinalPath(String uploadPath) { if (uploadPath == null) { throw new IllegalArgumentException("uploadPath can not be null."); } else { uploadPath = uploadPath.trim(); if (!uploadPath.startsWith("/") && !uploadPath.startsWith("\\")) { return baseUploadPath + File.separator + uploadPath; } else { return baseUploadPath.equals("/") ? uploadPath : baseUploadPath + uploadPath; } } } private void wrapMultipartRequest(HttpServletRequest request, String uploadPath, int maxPostSize, String encoding) { File dir = new File(uploadPath); if (!dir.exists() && !dir.mkdirs()) { throw new RuntimeException("Directory " + uploadPath + " not exists and can not create directory."); } else { this.uploadFiles = new ArrayList(); try { this.multipartRequest = new com.oreilly.servlet.MultipartRequest(request, uploadPath, maxPostSize, encoding, fileRenamePolicy); Enumeration files = this.multipartRequest.getFileNames(); while(files.hasMoreElements()) { String name = (String)files.nextElement(); String filesystemName = this.multipartRequest.getFilesystemName(name); if (filesystemName != null) { String originalFileName = this.multipartRequest.getOriginalFileName(name); String contentType = this.multipartRequest.getContentType(name); UploadFile uploadFile = new UploadFile(name, uploadPath, filesystemName, originalFileName, contentType); if (this.isSafeFile(uploadFile)) { this.uploadFiles.add(uploadFile); } } } } catch (IOException var12) { throw new RuntimeException(var12); } } } private boolean isSafeFile(UploadFile uploadFile) { String fileName = uploadFile.getFileName().trim().toLowerCase(); if (!fileName.endsWith(".jsp") && !fileName.endsWith(".jspx")) { return true; } else { uploadFile.getFile().delete(); return false; } } public List<UploadFile> getFiles() { return this.uploadFiles; } public Enumeration getParameterNames() { return this.multipartRequest.getParameterNames(); } public String getParameter(String name) { return this.multipartRequest.getParameter(name); } public String[] getParameterValues(String name) { return this.multipartRequest.getParameterValues(name); } public Map getParameterMap() { Map map = new HashMap(); Enumeration enumm = this.getParameterNames(); while(enumm.hasMoreElements()) { String name = (String)enumm.nextElement(); map.put(name, this.multipartRequest.getParameterValues(name)); } return map; } }
加载initTokenManager
private void initTokenManager() { ITokenCache tokenCache = this.constants.getTokenCache(); if (tokenCache != null) { TokenManager.init(tokenCache); } }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jfinal.token; import com.jfinal.core.Controller; import com.jfinal.kit.StrKit; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Timer; import java.util.TimerTask; public class TokenManager { private static ITokenCache tokenCache; private static Random random = new Random(); private TokenManager() { } public static void init(ITokenCache tokenCache) { if (tokenCache != null) { tokenCache = tokenCache; long halfTimeOut = 150000L;
// Token最小过期时间的一半时间作为任务运行的间隔时间
(
new
Timer(
"TokenManager"
, true
)).schedule(
new
TimerTask() {
public void
run() { TokenManager.removeTimeOutToken()
;
} }
,
halfTimeOut
,
halfTimeOut)
;
} }
public static void
createToken(Controller controller
,
String tokenName
, int
secondsOfTimeOut) {
if
(tokenCache ==
null
) { String tokenId = String.valueOf(random.nextLong())
;
controller.setAttr(tokenName
,
tokenId)
;
controller.setSessionAttr(tokenName
,
tokenId)
;
createTokenHiddenField(controller
,
tokenName
,
tokenId)
;
}
else
{ createTokenUseTokenIdGenerator(controller
,
tokenName
,
secondsOfTimeOut)
;
} }
private static void
createTokenHiddenField(Controller controller
,
String tokenName
,
String tokenId) { StringBuilder sb =
new
StringBuilder()
;
sb.append(
"<input type='hidden' name='"
).append(tokenName).append(
"' value='"
+ tokenId).append(
"' />"
)
;
controller.setAttr(
"token"
,
sb.toString())
;
}
private static void
createTokenUseTokenIdGenerator(Controller controller
,
String tokenName
, int
secondsOfTimeOut) {
if
(secondsOfTimeOut <
300
) { secondsOfTimeOut =
300
;
} String tokenId =
null;
Token token =
null;
int
var5 =
8
;
do
{
if
(var5-- ==
0
) {
throw new
RuntimeException(
"Can not create tokenId."
)
;
} tokenId = String.valueOf(random.nextLong())
;
token =
new
Token(tokenId
,
System.currentTimeMillis() + (
long
)(secondsOfTimeOut *
1000
))
;
}
while
(tokenId ==
null
|| tokenCache.contains(token))
;
controller.setAttr(tokenName
,
tokenId)
;
tokenCache.put(token)
;
createTokenHiddenField(controller
,
tokenName
,
tokenId)
;
}
public static synchronized boolean
validateToken(Controller controller
,
String tokenName) { String clientTokenId = controller.getPara(tokenName)
;
if
(tokenCache !=
null
) { Token token =
new
Token(clientTokenId)
;
boolean
result = tokenCache.contains(token)
;
tokenCache.remove(token)
;
return
result
;
}
else
{ String serverTokenId = (String)controller.getSessionAttr(tokenName)
;
controller.removeSessionAttr(tokenName)
;
return
StrKit.notBlank(clientTokenId) && clientTokenId.equals(serverTokenId)
;
} }
private static void
removeTimeOutToken() { List<Token> tokenInCache = tokenCache.getAll()
;
if
(tokenInCache !=
null
) { List<Token> timeOutTokens =
new
ArrayList()
;
long
currentTime = System.currentTimeMillis()
;
Iterator i$ = tokenInCache.iterator()
;
Token token
;
while
(i$.hasNext()) { token = (Token)i$.next()
;
if
(token.getExpirationTime() <= currentTime) { timeOutTokens.add(token)
;
} } i$ = timeOutTokens.iterator()
;
while
(i$.hasNext()) { token = (Token)i$.next()
;
tokenCache.remove(token)
;
} } }}
总结:
解析JFinalFilter文件的解读加载顺序
开始是默认加载Filter的init方法
然后调用JFinal的init方法,
初始化加载initPathUtil,constants ,configJFinal,initActionMapping,initHandler,initRender,initOreillyCos,initOreillyCos,initTokenManager。
if (!jfinal.init(this.jfinalConfig, filterConfig.getServletContext())) {
其中所有类加载时都会有各自的init方法和实现或者集成的类,工厂等。
boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
this.servletContext = servletContext;this.contextPath = servletContext.getContextPath();
this.initPathUtil();
Config.configJFinal(jfinalConfig);
this.constants = Config.getConstants();
this.initActionMapping();
this.initHandler();
this.initRender();
this.initOreillyCos();
this.initTokenManager();
return true;
}
configJFinal下默认加载的东西,同理,也有各自需要加载的文件。
static void configJFinal(JFinalConfig jfinalConfig) { jfinalConfig.configConstant(constants); initLogFactory(); initEngine(); jfinalConfig.configRoute(routes); jfinalConfig.configEngine(engine); jfinalConfig.configPlugin(plugins); startPlugins(); jfinalConfig.configInterceptor(interceptors); jfinalConfig.configHandler(handlers); }
然后加载Filter默认的doFilter方法,
运行最后会调用来实现后台和前台的交互。
chain.doFilter(request, response);
//配置过滤器2 <filter> <filter-name>jfinal</filter-name> <filter-class>com.jfinal.core.JFinalFilter</filter-class> <init-param> <param-name>configClass</param-name> <param-value>com.tspace.common.TspaceConfig</param-value> </init-param> </filter> <filter-mapping> <filter-name>jfinal</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>