2016-10-18 16:46

失去时分秒并不是这个原因引起的,因为 getModel 方法最底层利的 TypeConverter.java 这个类进行的转换,注意看一下里面有关对 Date 的转换源代码,会先判断你字段的长度,然后优先会转成 Timestamp

所以解决方案极其简单,让表单中提供的 time 满足这个格式:"yyyy-MM-dd HH:mm:ss"

以外我再将 jfinal 这部分源码copy来此,你一看便知,与类型无关:
if (type == java.util.Date.class) {
if (s.length() >= timeStampLen) {
return new SimpleDateFormat(timeStampPattern).parse(s);
}
else {
return new SimpleDateFormat(datePattern).parse(s);
}
}
注意看这个 if 语句,先是优先转换为 timestamp

2016-10-18 16:38

最后还忘了说了有一点,该处理方式,你仍然可以 setXxx(new Timestamp(new Date().getTime()); 因为 Date 是 Timestamp 的父类,所以完全没有阻止你使用 Timestamp,所以叫有百利无一害

2016-10-18 16:36

timestamp 的处理方式,简单来说是 java.sql.Timestamp 创建方式并不支持 new Timestamp(),你必须写很多代码来创建它,同时 new Date() 可以代替这些代码

2016-10-18 16:35

因为 java.util.Date 是 java.sql.Timestamp 父类,你可以对这类字段直接 setXxx(new Date()),而不用去苦哈哈去创建一个 Timestamp 对象,得这样写:
timestamp = new Timestamp(new Date().getTime()); 然后再
setXxx(timestamp) 在功能上与 jfinal 现在的做法是一样的,何必舍简求繁?

生成器的扩展极其简单,直接创建继承类,覆盖掉父类的相关方法即可,jfinal 所有生成器是面向扩展设计的,所有属性与方法是 protected 的,继承即可扩展

2016-10-18 16:27

不可以不继承,struts 2 用过三年多的时间,他的可以不继承 ActionSupport 的搞法,理想上是去除去框架的依赖,但是这样搞却要去依赖 ActionContext 这样的东东

这种对框架的 “必要” 的依赖是逃不掉的,在某一个地方暂时性的逃掉了,但在后面某处必然要补回来,例如通过 ActionContext.getContent() 这样的静态方法给补回来,出来混迟早要还的

所以, jfinal 并不避讳让用户的代码有轻量的依赖,例如,你的控制层可以是继承 Controller,而你希望的可独立运行于其它环境的控制层完全不需要依赖 jfinal,所以在 jfinal 的世界观里面,对框架的绑定在某个地方必不可少,并且是使用框架所提供功能的必要手段,但你可以将需要独立的地方独立出来,例如业务层,可以与任何框架毫无依赖关系

2016-10-18 16:05

@hjcscscs 正确,就是这样

2016-10-18 11:57

3:注意页面 form 表单的提交按钮的 typ 类型是常规的 submit:type="submit"

jquery form 这个工具的关键功能就是:页面要提交的表单,按照常规的非 ajax 的方式去组织,例如提交铵钮是 submit 而不是 button 类型,然后 jquery form 通过 $(...).ajaxForm(...) 这行代码可以接管提交这个动作,将你的普通表单提交直接改变成 ajax 提交

jquery form 的核心价值在于将你的普通表单提交自动转化成 ajax 提交

2016-10-18 11:40

别折腾得这么麻烦,直接下载本站的 jquery form 文件:http://www.jfinal.com/assets/jquery_form/jquery.form.min.js 然后用下面几行代码搞定:
$(document).ready(function() {
$("#myArticleForm").ajaxForm({
dataType: "json"
, success: function(ret) {}
, error: function(ret) {}
});
});

这行代码的两个关键点注意一下:
1:注意页面 form 表单的 id 属性为:myArticleForm,这个可以改,注意对上js中的选择器使用的名称就好,也可以使用别的选择器
2:注意页面 form 表单需要设置 method 与 enctype 属性: method="POST" enctype="multipart/form-data"

2016-10-18 11:32

以上介绍的方式中,有几个关键点:
1:去掉 Account 这些个 model 中的 public Account dao 对象创建,首先是避免有人误用,引发线程安全问题,其次是在强调所有数据库操作放在业务中,而不是张口就来写 sql, Account.dao.find(sql) 这种代码永远不要出现,而是要先在 service 层中创建一个方法,在此方法中 dao.find(sql),别处需要使用的就转调这个业务方法

2:dao 对象只存在于业务层,业务层以外永远不要出现数据库查询这样的代码,让业务层承载所有的数据库查询,当某个数据库查询的功能还没有的时候,就在相应的 Serivce 业中创建一个,如果没有合适的 serivce 类,则创建一个

养成好的业务层构建习惯,用上三天,就会知道这样做的巨大好处

2016-10-18 11:27

问题一: jfinal 最核心的优势在于开发效率高、学习成本低、开发体验好、代码量少,并且 jfinal 的体量很小,只有一万行代码左右,核心代码只有 2000 行左右,所以可控性与扩展性极好。建议先试用一下,这样才有所体会

问题二:对工作流并没有多少经验,感觉上是建议自己写一个简单的,如果要集成的话,一定要选择简洁优雅的方案

问题三:对 jfinal 项目来说,业务层几乎是必须的,不带业务层的都是很小的项目应用场景,业务层做成无状态的,这样的话,内部可以持有一个全局变量,供所有地方直接使用,不用每次都创建 Service,以下是一个 AccountService 的示例:
public class AccountService {
// 全局共享的业务对象,但要保障无状态,这样才是线程安全的
public static final AccountService me = Enhancer.enhance(AccountService.class);
// dao 对象只让本业务使用,其它要用它的地方统统在业务层创建方法来转调
private final Account dao = new Account();

@Before(Tx.class)
public class doIt() {
....
}
}

在Controller 中可以有两种对业务层的用法,以下是用法一:
public class AccountController {
private AccountService srv = AccoutService.me;
public void action() {
srv.doIt();
}

对于其它非 AccountController 以下是用法二:
public class OtherController {
public void action() {
// 直接使用 me 对象
AccountService.me.doIt();
}

2016-10-18 11:15

@云海 在页面文件中可以获取到变量,是因为在后端使用 render(xxx.html) 对该页面进行了渲染,而你的 server-set.js 这个文件是个独立的资源文件, render(xxx.html) 时并不会去处理你的 server-set.js文件

js css jpg 等等这类资源是在 html 中使用链接指向的方式指定的,浏览器在发送第一次请求以后获取到的仅仅只是 html 文件内容而已,通过解析文件内容,得到 js css jpg 这些资源的 url 链接以后,浏览器会再次发起 n 个请求去获取这些资源,而这些请求通常是 tomcat jetty nginx 接管的,你的程序,尤其是你的 render(xxx.html) 对此全然不知

2016-10-18 11:10

在 Tx.java 中的 intercept 方法中设置一个断点,单步调试一下程序是否走到了 conn.commit() 这行代码,这行是提交动作

2016-10-18 00:11

spring 引入 IOC是为了接管对象创建,进而可以在创建对象时注入其依赖的其它对象,进而在注入代理类来代理这些类的行为,再进而实现 AOP

有了 AOP,spring 才方便去实现声明式事务、权限管理等等功能,所以 IOC 在本质上是为了实现 AOP

而 jfinal 天然支持 AOP,并且不需要 IOC 配合使用,所以不建议使用 IOC。引入 IOC 势必要对依赖和注入进行配置,通常是通过 xml 或注解进行配置,这种搞法会让你的整个系统充满足依赖关系的配置与管理,对真正的业务开发带来极大的噪音

2016-10-17 18:50

补充一下,如果只需要使用切换模板的方式使用国际化功能,前面两步应该可以省略

2016-10-17 18:25

@bobwill 几年前有个项目用了这种方式,代码找不到了,非常简单,按照下面的步骤做:
1:先创建国际化资源文件,假定叫 i18n.properties,里面可以先不写东西,把文件放在资源路径之下,maven项目是 resource 目录

2:在YourJFinalConfig.configConstant(...) 中添加 me.setI18nDefaultBaseName("i18n"),由于第一步中的资源文件的主文件名是 "i18n",这一步可以省略,别的名称则不能省

3:在 YourJFinalConfig.configInterceptor(...) 中添加I18nInterceptor全局拦截器:
me.add(new I18nInterceptor("_locale", "_res", true))

4:假定你在的某个页面叫 index.html,那么在这个页面相同的目录下面再创建一个 "zh_TW" 目录,然后在该子目录下创建繁体版的 index.html 文件,其中的 "zh_TW" 目录就表示繁体版的 locale,通过这种不断创建不同 locale 子目录的方式可以任意扩展多种国际化模板出来

5:在请求的时候,通过在浏览器中的 url 最后面添加 locale 信息就可以切换了,并且会一直保持住这个 locale 到 cookie 中,直到切换成新的 locale,url 例如:
http://yourwebsite.com/user?_locale=zh_TW

以上 url 中最的后面的 ?_locale=zh_TW 参数就是告诉拦截器切换使用这个地区的模板,这个 "_locale" 参数注是在第 3 步中创建 I18nInterceptor 对象时第一个参数指定的,可以修改

本质上,只要看一下 I18nInterceptor 就完全会使用了,搞定后记得回来写篇分享,不枉我写了这么多文字