2024-02-17 03:01

login action 中验证方式:

@Clear
public void login(String username, String password) {
if (!validateCaptcha("verificationCode") && !CaptchaRender.validate(get("captchaKey"), get("verificationCode"))) {
renderJson(Ret.fail("验证码不正确,请重新输入"));
return;
}
..... 具体登录代码在此
}

2024-02-17 02:59

然后在 controller 中这么使用:

private void captcha() {
try {
String uuid = StrKit.getRandomUUID();
JsonCaptchaRender render = new JsonCaptchaRender(uuid);
Kv data = Kv.of("captchaKey", uuid);
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
ImageIO.write(render.getImage(), "jpg", os);
data.set("img", Base64.encode(os.toByteArray()));
renderJson(Ret.data(data));
} catch (IOException e) {
renderJson(Ret.fail(e.getMessage()));
}
}

2024-02-17 02:54

先写一个 JsonCaptchaRender.java,代码如下:

import com.jfinal.captcha.Captcha;
import com.jfinal.captcha.CaptchaManager;
import com.jfinal.captcha.CaptchaRender;
import com.jfinal.kit.StrKit;

import java.awt.image.BufferedImage;

public class JsonCaptchaRender extends CaptchaRender {

private final String captchaKey;
private String code;
BufferedImage image;

public BufferedImage getImage() {
return image;
}

public void setImage(BufferedImage image) {
this.image = image;
}

public String getCaptchaKey() {
return captchaKey;
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public JsonCaptchaRender(String captchaKey) {
if (StrKit.isBlank(captchaKey)) {
throw new StockException("验证码参数 captchaKey 不能为空");
}
this.captchaKey = captchaKey;
Captcha captcha = createCaptcha();
CaptchaManager.me().getCaptchaCache().put(captcha);
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
String code = captcha.getValue();
this.setCode(code);
drawGraphic(code, image);
this.setImage(image);
}

/**
* 使用前端传入 captchaKey
*/
@Override
protected Captcha createCaptcha() {
return new Captcha(this.captchaKey, getRandomString(), Captcha.DEFAULT_EXPIRE_TIME);
}

/**
* 生成验证码
*/
@Override
public void render() {

}
}

2024-02-03 00:02

如果一定要在 main 方法放启动之外的代码,可以使用一下 addSystemClassPrefix 方法将那些相关的 class 通过系统级 classLoader 来加载,大致这么玩:

UnsertowServer.create(...).addSystemClassPrefix("xxx.yyy.LocalManager").start();

2024-02-02 23:57

启动类的 main 方法中除了放启动代码之外,不要放任何其它代码,因为 main 方法中的代码执行时 classloader 是 JVM 默认的,而 UndertowServer.start(...) 启动后才会切到 jfinal undertow 自定义的 HotswapClassloader

将 LocalManager 那段代码想办法挪到项目内部的某个地方调用

2024-02-01 10:58

眼力太好了,已更正,谢谢反馈

2024-01-27 18:18

小杜总有能好东西分享,点赞收藏一波

2024-01-03 12:42

cannot be cast .... 这类错误,或者说热加载错误两个主要方法:
1: 配置 hotSwap
2: 如果配置解决不了,可能是被依赖的类发生了变化,需要重新编译依赖的类

2024-01-02 14:17

SaTokenActionHandler 是不是基于老版本 jfinal 编译到 jar 中了,注意要跟着升级到新版本再编译

此外 jfinal-undertow 也升一下级

2023-12-07 18:45

ActionHandler.java 中触发的,看下源码

2023-12-06 15:58

估计你的这个字段是 timestamp 类型,并且设置了 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,例如:

字段名 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

无论如何都是与 jfinal 无关的

2023-12-05 19:42

在控制台看一下异常输出就清楚问题了,如果控制没有异常输入,需要配置好日志,注意下载官方的 jfinal-admin、jfinal-club 参考里面的日配置配置

2023-11-30 18:50

备忘一下这个改进的原理:按照modifyFlag不同分组,分批执行

这确实是个不错的方案,或许是最好的方案。

如果数据量大的话,性能怎么样?

2023-11-28 18:26

这里的两处关键:#for 指令中的第一个 if :
#if( for.index % 4 == 0 )

第二个 if
#if( for.count % 4 == 0 || for.last)

灵活用好 enjoy 现有功能,一般来说都可以实现, enjoy code enjoy life

2023-11-28 18:25

刚刚用 enjoy 现有指令实现了,你试一下:

public static void main(String[] args) {
String t = "#set(test=[1,2,3,4,5,6,7,8,9])" +
"#for(item : test)" +
"#if( for.index % 4 == 0 ) <div style='width:100%'>\n #end" +
"\t\t<span style='padding-right:10px'>#(item)</span>\n" +
"#if( for.count % 4 == 0 || for.last) </div>\n #end" +
"#end";

Engine.use().getTemplateByString(t).render(System.out);
}