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("\nException: " + 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>