2020-06-20 18:06

@北流家园网 这里解决过了:
http://www.jfinal.com/feedback/1925

这里可以下载解决方案的代码:
http://free-download.jfinal.com/download/MyRenderFactory.zip

2020-06-20 18:05

@jfinalyl 将 sql 模板文件命名为以 ".sql" 为后缀,开发工具会自动当其当成 sql, IDEA 这样的工具会有提示, eclipse 的 sql 插件也应该可以支持

2020-06-20 18:00

正如 @杜福忠 同学所说,想要让 controller 成为单例,无法解决 controller 同部一些属性的多线程问题

虽然你自己放入 controller 的业务层等等实例是无状态的,但 controller 内部持有的一些属性却是有状态的

官方提供的 FastControllerFactory 虽然不是让 controller 成为单例,但是可以让 controller 对象可以被复用,从而可以不必每次都创建 controller 对象

此外,jfinal 的 inject 是极快的,绝大部分情况下无需考虑这方面的性能。jfinal 只是为了追求极致才提供了 FastControllerFactory

jfinal 未将 FastControllerFactory 配置为默认值,是因为担心使用者在 controller 中自己再使用了 "有状态" 的属性,从而引发线程安全问题。这个问题需要覆盖 controller 中的 _clear_() 方法来解决。 在源码中有详细说明

性能一定是排在安全性之后的,况且 jfinal 性能早已过剩

2020-06-20 17:44

@feng_xing Validate 一般用于字段数比较多的表单提交,如果表单有大量重复字段的可以重用同一个 Validator

对于字段比较少的,直接在 controller 中通过 if 判断就可以了

再一个 Validator 属于拦截器,作为一种实现方案存在,你完全可以使用拦截器定制一套自己的 Validator,大量重用代码

我自己的项目中的 Validator 一般很少,一般的 web 项目都是 "读多写少"

2020-06-20 17:41

jfinal 4.9 新增了对 Iterable 的支持,在此之前,对于你当前的 ClusterIndexHealth 应该是当成 java bean 去转换了

如果对这个类的转换用得少的话,建议这么来用:
String json = FastJson.getJson().toJson(...);
renderJson(json);

像上面这样临时用一下 fastjson,其它地方不变

当然,你还可以通过 JFinalJson.addToJson(...) 来彻底地添加对 ClusterIndexHealth 的转让逻辑来解决

2020-06-20 17:36

jfinal 只是将你的 sql + para 直接扔给了底层的 JDBC 去执行,只要是 JDBC 支持就会被支持

2020-06-20 17:34

@呵呵哒aaa 在最终的 model 中添加 getStateInfo 覆盖掉 base model 中的方法去处理

2020-06-20 17:33

@doubuxingle 当某个线程被 lock.lock() 锁住的时候,它持有的 cacheData 是 null,当该线程被重新唤醒时必须再通过 CacheKit.get(...) 获取数据,否则 cacheData 仍是 null,那这段代码就毫无意义了

2020-06-20 17:31

@穿越123 将事情搞复杂是很容易的,反之是很难的,jfinal 擅长将复杂问题简化

2020-06-20 17:30

很久没有关注 reids plugin 了, 发布、订阅这个功能很重要,希望 @杜福忠 同学能提交 PR 过来

2020-06-20 17:26

@SamUU jfinal 重点关注在 web + orm + aop + enjoy 这四个方面,不能平均使力,资源总是有限的

2020-06-20 17:24

jfinal undertow 的代码虽然极少,但细节极多,要实现的功能十分丰富

从 jfinal undertow 项目中的配置 demo 可以获取到 95% 以上的配置项用法,剩下的需要看看源码,当然,大分部分配置不需要关注, jfinal undertow 很贴心的处理好了默认该做什么

博主的分享非常详细,通过阅读,我自己也回忆起了一篇当初写这些代码的细节。

要实现功能是极端容易的,要简单、全面、通用、体贴入微地实现这些功能是很不容易的,魔鬼都在细节之中

最后,对于人脑来说,输出才是最好的输入,将所理解的知识通过文字或者其它方式输出,才是最好地掌握这些知识的方法

2020-06-16 17:12

如果你希望一旦出现错误的数据就立即返回使用下面的方法即可:
setShortCircuit(true);

2020-06-16 17:11

结合 setRet(...) 与 getRet() 来用:

public class LoginValidator extends Validator {

protected void validate(Controller c) {
setShortCircuit(true);

/**
* 注入 Ret 对象,validateXxx(...) 方法的验证结果将被存放于该 Ret 对象之中,
* 以便于 handleError 中使用:
* controller.renderJson(getRet());
*
* 具体到本例,LoginController.doLogin() 中使用的 renderJson(ret)
* 与 LoginValidator.handleError() 中使用的 c.renderJson(getRet())
* 实现了返回值格式的统一(Ret 设置 state、msg 属性值),所以前端 js 可以
* 统一处理返回数据:
* if (ret.state == "ok") {
* location.href = ret.returnUrl;
* } else {
* alert(ret.msg);
* }
*
* 否则 Validator 层与 Service 层返回的 Ret 值格式将不同,前端 js 需要
* 对两种格式分别做处理
*/
setRet(Ret.fail()); // Ret.fail() 将设置 state : "fail" 值

validateRequired("userName", "msg", "邮箱不能为空");
validateEmail("userName", "msg", "邮箱格式不正确");

validateRequired("password", "msg", "密码不能为空");
validateCaptcha("captcha", "msg", "验证码不正确");
}

protected void handleError(Controller c) {
// getRet() 与 setRet(...) 配合使用
Ret ret = getRet();
c.renderJson(ret);
}
}

2020-06-16 17:08

你配置了 CaseInsensitiveContainerFactory,注意在用这个配置的时候,要去除其中的 true 与 false 参数,这样用:
arp.setContainerFactory(new CaseInsensitiveContainerFactory());

注意,构造方法中没有传入 true 和 false,而你是像下面这样用的:
new CaseInsensitiveContainerFactory(true);
就会被转成大写或者小写