Browse Source

Merge branch 'master' into jfinal-java8

James 8 years ago
parent
commit
370323bc00

+ 16 - 0
src/main/java/com/jfinal/template/Engine.java

@@ -392,6 +392,22 @@ public class Engine {
 		return devMode;
 	}
 	
+	/**
+	 * 设置 ISourceFactory 用于为 engine 切换不同的 ISource 实现类
+	 * ISource 用于从不同的来源加载模板内容
+	 * 
+	 * <pre>
+	 * 配置为 ClassPathSourceFactory 时特别注意:
+	 *    由于 JFinal 会在 configEngine(Engine me) 方法调用 “之前”,会默认调用一次如下方法:
+	 *       me.setBaseTemplatePath(PathKit.getWebRootPath())
+	 *    
+	 *    而 ClassPathSourceFactory 在以上默认值下不能工作,所以需要通过如下方式清掉该值:
+	 *       me.setBaseTemplatePath(null)
+	 *    
+	 *    或者配置上合理可用的 baseTemplatePath 值,例如在 Spring boot 中通常配置为:
+	 *       me.setBaseTemplatePath("templates");
+	 * </pre>
+	 */
 	public Engine setSourceFactory(ISourceFactory sourceFactory) {
 		this.config.setSourceFactory(sourceFactory);	// 放第一行先进行参数验证
 		this.sourceFactory = sourceFactory;

+ 4 - 0
src/main/java/com/jfinal/template/ext/spring/JFinalView.java

@@ -27,6 +27,9 @@ import javax.servlet.http.HttpSession;
 import org.springframework.web.servlet.view.AbstractTemplateView;
 
 /**
+ * JFinalView
+ * 
+ * <pre>
  * 关键设置:
  * 1:setContentType("text/html;charset=UTF-8") 设置 content type 字符集为 UTF-8
  * 
@@ -40,6 +43,7 @@ import org.springframework.web.servlet.view.AbstractTemplateView;
  *      JFinalView.setExposeSessionAttributes(true) 可实现
  *      相似的功能,区别在于前者访问方式为 #(session.value) 而后者为
  *      #(value),两种配置只选其一
+ * </pre>
  */
 public class JFinalView extends AbstractTemplateView {
 	

+ 145 - 28
src/main/java/com/jfinal/template/ext/spring/JFinalViewResolver.java

@@ -16,23 +16,41 @@
 
 package com.jfinal.template.ext.spring;
 
+import java.util.ArrayList;
+import java.util.List;
 import javax.servlet.ServletContext;
 import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
 import com.jfinal.kit.StrKit;
+import com.jfinal.template.Directive;
 import com.jfinal.template.Engine;
+import com.jfinal.template.source.ClassPathSourceFactory;
+import com.jfinal.template.source.ISourceFactory;
 
 /**
- * 关键设置:
- * 1:setBaseTemplatePath(path) 设置模板文件所在的基础路径
- * 2:setDevMode(true) 设置模板文件被修改后的热加载
- * 3:setSessionInView(true) 设置在模板中可通过 #(session.value) 访问 session 中的数据
- * 3:setCreateSession(boolean) 用来设置 request.getSession(boolean) 调时的参数
+ * JFinalViewResolver
+ * 
+ * <pre>
+ * 关键配置:
+ * 1:setDevMode(true) 设置支持热加载模板文件
+ * 
+ * 2:addSharedFunction(file) 添加共享函数文件
+ * 
+ * 3:setSourceFactory(new ClassPathSourceFactory()),从 class path 与 jar 包中加载模板文件
+ *    一般用于 sprint boot
+ * 
+ * 4:setSessionInView(true) 设置在模板中可通过 #(session.value) 访问 session 中的数据
+ * 
+ * 5:setCreateSession(boolean) 用来设置 request.getSession(boolean) 调时的参数
+ * 
+ * 6:setBaseTemplatePath(path) 设置模板文件所在的基础路径,通常用于 spring mvc
+ *   默认值为 web 根路径,一般不需要设置
+ * </pre>
  */
 public class JFinalViewResolver extends AbstractTemplateViewResolver {
 	
 	public static final Engine engine = new Engine();
 	
-	static String sharedFunctionFiles = null;
+	static List<String> sharedFunctionFiles = new ArrayList<String>();
 	static boolean sessionInView = false;
 	static boolean createSession = true;
 	
@@ -41,23 +59,96 @@ public class JFinalViewResolver extends AbstractTemplateViewResolver {
 	}
 	
 	/**
-	 * 添加 shared function 文件,多个文件用逗号分隔
+	 * 设置开发模式,值为 true 时支持模板文件热加载
 	 */
-	public void setSharedFunction(String sharedFunctionFiles) {
-		if (StrKit.isBlank(sharedFunctionFiles)) {
-			throw new IllegalArgumentException("sharedFunctionFiles can not be blank");
-		}
-		JFinalViewResolver.sharedFunctionFiles = sharedFunctionFiles;
-	}
-	
 	public void setDevMode(boolean devMode) {
 		engine.setDevMode(devMode);
 	}
 	
+	/**
+	 * 添加 shared function 文件,可调用多次添加多个文件
+	 */
+	public void addSharedFunction(String fileName) {
+		// 等待 SourceFactory、baseTemplatePath 配置到位,利用 sharedFunctionFiles 实现延迟加载
+		sharedFunctionFiles.add(fileName);
+	}
+	
+	/**
+	 * 添加自定义指令
+	 */
+	public void addDirective(String directiveName, Directive directive) {
+		engine.addDirective(directiveName, directive);
+	}
+	
+	/**
+	 * 添加共享对象
+	 */
+	public void addSharedObject(String name, Object object) {
+		engine.addSharedObject(name, object);
+	}
+	
+	/**
+	 * 添加共享方法
+	 */
+	public void addSharedMethod(Object sharedMethodFromObject) {
+		engine.addSharedMethod(sharedMethodFromObject);
+	}
+	
+	/**
+	 * 添加共享方法
+	 */
+	public void addSharedMethod(Class<?> sharedMethodFromClass) {
+		engine.addSharedMethod(sharedMethodFromClass);
+	}
+	
+	/**
+	 * 添加扩展方法
+	 */
+	public static void addExtensionMethod(Class<?> targetClass, Object objectOfExtensionClass) {
+		Engine.addExtensionMethod(targetClass, objectOfExtensionClass);
+	}
+	
+	/**
+	 * 添加扩展方法
+	 */
+	public static void addExtensionMethod(Class<?> targetClass, Class<?> extensionClass) {
+		Engine.addExtensionMethod(targetClass, extensionClass);
+	}
+	
+	/**
+	 * 设置 ISourceFactory 用于为 engine 切换不同的 ISource 实现类
+	 * 
+	 * <pre>
+	 * 配置为 ClassPathSourceFactory 时特别注意:
+	 *    由于在 initServletContext() 通过如下方法中已设置了 baseTemplatePath 值:
+	 *        setBaseTemplatePath(servletContext.getRealPath("/"))
+	 *    
+	 *    而 ClassPathSourceFactory 在 initServletContext() 方法中设置的
+	 *    值之下不能工作,所以在本方法中通过如下方法清掉了该值:
+	 *         setBaseTemplatePath(null)
+	 *    
+	 *    这种处理方式适用于绝大部分场景,如果在使用 ClassPathSourceFactory 的同时
+	 *    仍然需要设置 baseTemplatePath,则在调用该方法 “之后” 通过如下代码再次配置:
+	 *         setBaseTemplatePath(value)
+	 * </pre>
+	 */
+	public void setSourceFactory(ISourceFactory sourceFactory) {
+		if (sourceFactory instanceof ClassPathSourceFactory) {
+			engine.setBaseTemplatePath(null);
+		}
+		engine.setSourceFactory(sourceFactory);
+	}
+	
+	/**
+	 * 设置模板基础路径
+	 */
 	public void setBaseTemplatePath(String baseTemplatePath) {
 		engine.setBaseTemplatePath(baseTemplatePath);
 	}
 	
+	/**
+	 * 设置为 true 时支持在模板中使用 #(session.value) 形式访问 session 中的数据
+	 */
 	public void setSessionInView(boolean sessionInView) {
 		JFinalViewResolver.sessionInView = sessionInView;
 	}
@@ -70,6 +161,16 @@ public class JFinalViewResolver extends AbstractTemplateViewResolver {
 		JFinalViewResolver.createSession = createSession;
 	}
 	
+	/**
+	 * 设置 encoding
+	 */
+	public void setEncoding(String encoding) {
+		engine.setEncoding(encoding);
+	}
+	
+	/**
+	 * 设置 #date(...) 指令,对于 Date、Timestamp、Time 的输出格式
+	 */
 	public void setDatePattern(String datePattern) {
 		engine.setDatePattern(datePattern);
 	}
@@ -85,29 +186,45 @@ public class JFinalViewResolver extends AbstractTemplateViewResolver {
 	}
 	
 	@Override
+	protected Class<?> requiredViewClass() {
+		return JFinalView.class;
+	}
+	
+	/**
+	 * spring 回调,利用 ServletContext 做必要的初始化工作
+	 */
+	@Override
 	protected void initServletContext(ServletContext servletContext) {
 		super.initServletContext(servletContext);
 		
-		if (StrKit.isBlank(engine.getBaseTemplatePath())) {
-			String path = servletContext.getRealPath("/");
-			engine.setBaseTemplatePath(path);
-		}
-		
-		initSharedFunctionFiles();
+		initBaseTemplatePath(servletContext);
+		initSharedFunction();
 	}
 	
-	private void initSharedFunctionFiles() {
-		if (sharedFunctionFiles != null) {
-			String[] fileArray = sharedFunctionFiles.split(",");
-			for (String file : fileArray) {
-				engine.addSharedFunction(file.trim());
+	/**
+	 * 初始化 baseTemplatePath 值,启用 ClassPathSourceFactory 时
+	 * 无需设置 baseTemplatePath 为 web 根路径
+	 */
+	private void initBaseTemplatePath(ServletContext servletContext) {
+		if (engine.getSourceFactory() instanceof ClassPathSourceFactory) {
+			// do nothing
+		} else {
+			if (StrKit.isBlank(engine.getBaseTemplatePath())) {
+				String path = servletContext.getRealPath("/");
+				engine.setBaseTemplatePath(path);
 			}
 		}
 	}
 	
-	@Override
-	protected Class<?> requiredViewClass() {
-		return JFinalView.class;
+	/**
+	 * 利用 sharedFunctionFiles 延迟调用 addSharedFunction
+	 * 因为需要等待 baseTemplatePath 以及 ISourceFactory 设置完毕以后
+	 * 才能正常工作
+	 */
+	private void initSharedFunction() {
+		for (String file : sharedFunctionFiles) {
+			engine.addSharedFunction(file.trim());
+		}
 	}
 }