FreeMarker использует String#substring
для выполнения фактического вычисления подстроки (на основе UTF-16-chars?), Что не очень хорошо работает с китайскими иероглифами.Вместо этого следует использовать кодовые точки Unicode.Основываясь на этой записи и собственной встроенной подстроке FreeMarker, я взломал реализацию FreeMarker TemplateMethodModelEx
, которая работает с кодовыми точками:
public class CodePointSubstring implements TemplateMethodModelEx {
@Override
public Object exec(List args) throws TemplateModelException {
int argCount = args.size(), left = 0, right = 0;
String s = "";
if (argCount != 3) {
throw new TemplateModelException(
"Error: Expecting 1 string and 2 numerical arguments here");
}
try {
TemplateScalarModel tsm = (TemplateScalarModel) args.get(0);
s = tsm.getAsString();
} catch (ClassCastException cce) {
String mess = "Error: Expecting numerical argument here";
throw new TemplateModelException(mess);
}
try {
TemplateNumberModel tnm = (TemplateNumberModel) args.get(1);
left = tnm.getAsNumber().intValue();
tnm = (TemplateNumberModel) args.get(2);
right = tnm.getAsNumber().intValue();
} catch (ClassCastException cce) {
String mess = "Error: Expecting numerical argument here";
throw new TemplateModelException(mess);
}
return new SimpleScalar(getSubstring(s, left, right));
}
private String getSubstring(String s, int start, int end) {
int[] codePoints = new int[end - start];
int length = s.length();
int i = 0;
for (int offset = 0; offset < length && i < codePoints.length;) {
int codepoint = s.codePointAt(offset);
if (offset >= start) {
codePoints[i] = codepoint;
i++;
}
offset += Character.charCount(codepoint);
}
return new String(codePoints, 0, i);
}
}
Вы можете поместить его экземпляр в свою модель данныхroot, например
SimpleHash root = new SimpleHash();
root.put("substring", new CodePointSubstring());
template.process(root, ...);
и использовать пользовательский метод подстроки в FTL:
${substring(description, 0, 80)}
Я протестировал его с некитайскими символами, которые все еще работали, но до сих пор у меня нетпопробовал с китайскими иероглифами.Может быть, вы хотите попробовать.