2017-09-30 14:27

抱歉,可能是我IDE缓存的原因,当我清理后,afterJFinalStart()只会运行一次了。

2017-09-30 13:22

@社会你冲哥 Jedis.psubscribe()是一个阻塞式方法,订阅完成后会一直卡在那,导致JFinal的其他模块无法运行,造成启动超时,你可以再开一个线程启动。
private static final OrderSubscribe redisListener = new OrderSubscribe();
public void afterJFinalStart() {
new Thread(new Runnable() {
public void run() {
Jedis jedis = Redis.use("overall").getJedis();
jedis.psubscribe(redisListener, "__keyevent@0__:expired");
}
).start();
}
项目关闭时,取消订阅:
public void beforeJFinalStop() {
//取消redis订阅
redisListener.punsubscribe("__keyevent@0__:expired");
}

注意,JFinal启动时afterJFinalStart() 方法会运行两次,这样会导致你订阅2次,同一个key过期事件消息收到2次,所以你需要在afterJFinalStart() 方法中处理一下,使其中的代码只运行一次,这里不赘述。
@JFinal afterJFinalStart() 运行两次,没细看,什么梗?

2017-09-14 16:55

谈一下我自己的理解吧,为了更简洁清晰的实现WEB程序的开发,实现WEB程序的智能分工,大伙就整合了一套通用的架构方式,即MVC。

MVC提出三个概念,M-模型,数据的表示及载体,jfinal中就是各种Model类了;V-视图,数据的呈现,提供给用户的UI界面,这个根据实际需要决定如何展示;C-控制器,视图与模型连接的桥梁,纷发业务产生合适的数据(模型),传递数据给视图进行良好的展现,jfianl中就是Controller类了。

但实际开发中,仅仅有这三者还是不够的,要开发一个完整的项目,我们还需要其他的很多模块,同时遵从MVC思想,即明确分工(分层),WEB项目中又会有数据访问层(dao层),jfianl中就是Model中的各种增删改查的方法了,同时为了处理不同的业务,还会有业务层,这就是你说的service了, jfianl的文档和demo中只是列举框架的应用,所以没给出service层,这个也不好给,每个人的业务逻辑都不同,所以jfinal鼓励根据自己的需求构建service层,有了service层后,Controller中则只负责接受request,以及返回response,什么业务都不需要处理,代码会干净很多,管理维护也更方便。

我是这样处理的,构建一个类,用来存储通用的返回格式,controller中只负责接收参数,然后传递参数给service处理业务,service处理完返回一个通用的返回格式给controller,controller将此内容回传给客户端。如此,代码会精简很多,看起来也会更舒服,controller中类似:

/**
* 获取用户信息
* url:http://localhost:8080/mate/user/getUserInfo
*/
public void getUserInfo() {
DefaultResponse response = UserService.service.getUserInfo(getLanguage(), getUid());
renderJson(response);
}

service中类似:
public DefaultResponse getUserInfo(int language, long uid) {
if (uid == 0) {
logger.error(getMsg(uid, "need_login"));
return fail(language, ReturnCode.NEED_LOGIN, "need_login");
}

User user = User.dao.findById(uid);
user.remove("password");//去除不需要回传的字段

return success(user);
}
等等。

2017-09-14 16:14

一般为两种情况:
1.有这个类,类中没有这个方法;
2.有好几个这个类,类之间发生了冲突。
一般就是导包错误,导的好几个包版本不匹配,或者多个包中都有同名的类,仔细检查一下,导对正确的包即可。

2017-09-14 16:07

Record是一个可用于序列化的超类,在jfinal中可以将其理解为model的一个泛指的实例,其内部实现就是一个Map,其set()方法即相当于Map的put(),转换为json就相当于将Map转换为JsonObject,理论上是不会出现大小写混淆的问题的。
比如,在某个controller中进行测试:
public void test() {
Record record = new Record();
record.set("userName","张三");
renderJson(record);
}
是不会出现什么问题的,推测是你其他什么地方代码导致的,最有可能就是某个对象的get、set方法由get/setUserName()写成了get/setUsername()才导致了这个问题,仔细检查一下代码。

2017-09-14 11:05

@JFinal 感谢,已进行验证,确实不行

2017-09-13 18:04

@坚强的地瓜 不客气,解决了吗?开发工具中属性文件都有中文和Unicode相互转换的功能的,没有可以装个插件,不想装插件在线转贴过去也行:http://tool.chinaz.com/tools/unicode.aspx

2017-09-13 16:45

读取的是.txt还是.properties,如果是.properties的话,源文件中的内容如果有汉字的话,要写其Unicode,如:
test=\u4f60\u597d
不能写:
test=你好
不然读出来必然是乱码,.txt的话好像没碰到过什么乱码。

2017-06-29 13:27

@JFinal 谢谢及时解答,很清楚。我本身有一些疏忽,使用的Postman调试工具,POST提交会默认选择multipart/form-data类型,手动切换其他POST类型,比如:x-www-form-urlencoded就可以了,我列举的案例正好是你所说的两种情况,普通request及multipart request,感谢!!!

2017-05-19 10:23

同问,波哥,对于kotlin你有什么看法?

2017-03-29 17:32

我的处理方式是,接管System.out流自己进行处理:
package com.alone.mate.utils;

import java.io.PrintStream;

import org.apache.log4j.Logger;

/**
* 将所有System.out流转发到自定义流中以便用log4j记录日志
*
* @author alone
*/
public class LogUtils {

private static final Logger logger = Logger.getLogger(LogUtils.class);

public static void init() {
PrintStream printStream = new PrintStream(System.out) {

@Override
public void print(boolean b) {
log(Boolean.valueOf(b));
}

@Override
public void print(char c) {
log(Character.valueOf(c));
}

@Override
public void print(char[] s) {
log(s == null ? null : new String(s));
}

@Override
public void print(double d) {
log(Double.valueOf(d));
}

@Override
public void print(float f) {
log(Float.valueOf(f));
}

@Override
public void print(int i) {
log(Integer.valueOf(i));
}

@Override
public void print(long l) {
log(l);
}

@Override
public void print(Object obj) {
log(obj);
}

@Override
public void print(String s) {
log(s);
}

@Override
public void println(boolean b) {
logLn(Boolean.valueOf(b));
}

@Override
public void println(char c) {
logLn(Character.valueOf(c));
}

@Override
public void println(char[] s) {
logLn(s == null ? null : new String(s));
}

@Override
public void println(double d) {
logLn(Double.valueOf(d));
}

@Override
public void println(float f) {
logLn(Float.valueOf(f));
}

@Override
public void println(int i) {
logLn(Integer.valueOf(i));
}

@Override
public void println(long l) {
logLn(l);
}

@Override
public void println(Object obj) {
logLn(obj);
}

@Override
public void println(String s) {
logLn(s);
}
};
System.setOut(printStream);
System.setErr(printStream);
}

private static void log(Object info) {
if (info.toString().startsWith("Sql:")) {
info = info.toString().replace("\n", "").replace("\t", "");
}
logger.info("System.out.print: " + info);
}

private static void logLn(Object info) {
if (info.toString().startsWith("Sql:")) {
info = info.toString().replace("\n", "").replace("\t", "");
}
logger.info("System.out.println: " + info);
}
}

手动获取SqlReporter类中invoke方法打印的sql,进行判断,从而去除sql中的\n 与 \t,但是这种方法治标不治本,不能从源头上解决问题。

2017-03-29 17:22

需要去掉字符串中的\n与\t