修改:工程简单重构

This commit is contained in:
2023-04-29 23:30:44 +08:00
parent ea8e9f70bd
commit 68f4e2b479
53 changed files with 1869 additions and 1474 deletions

View File

@@ -1,67 +0,0 @@
package net.tccn.bbs.base;
import com.arangodb.ArangoCollection;
import com.arangodb.ArangoDB;
import com.arangodb.ArangoDatabase;
import net.tccn.bbs.base.entity.VisLog;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
/**
* @author: liangxianyou at 2018/11/18 9:02.
*/
public class ArangoKit {
protected static final boolean winos = System.getProperty("os.name").contains("Window");
protected static Function<String, String> chDev = (s) -> s + (winos ? "_dev" : "");
//Arango
protected static ArangoDB arangoDb = new ArangoDB.Builder().host("120.24.230.60", 8529).user("root").password("abc123").build();
protected static ArangoDatabase dbDev = arangoDb.db(chDev.apply("redbbs"));
protected static ArangoCollection colVisLog = dbDev.collection(chDev.apply("vis_log"));
static {
if (!dbDev.exists()) {
dbDev.create();
}
if (!colVisLog.exists()) {
colVisLog.create();
}
//java.net.SocketTimeoutException: Read timed out 加入下面两行,观察是否正常
System.setProperty("sun.net.client.defaultConnectTimeout", String.valueOf(1000));
System.setProperty("sun.net.client.defaultReadTimeout", String.valueOf(1000));
}
public static <T> CompletableFuture<T> save(T t) {
return CompletableFuture.supplyAsync(() -> {
if (t instanceof VisLog) {
colVisLog.insertDocument(t);
}
return t;
});
}
public static long findInt(String aql) {
return dbDev.query(aql, long.class).first();
}
public static long findInt(String aql, Map para) {
return dbDev.query(aql, long.class).first();
}
public static <T> List<T> find(String aql, Class<T> clazz) {
return dbDev.query(aql, clazz).asListRemaining();
}
public static <T> List<T> find(String aql, Map para, Class<T> clazz) {
return dbDev.query(aql, para, clazz).asListRemaining();
}
}

View File

@@ -1,98 +0,0 @@
package net.tccn.bbs.base;
import com.arangodb.ArangoCollection;
import com.arangodb.ArangoDB;
import com.arangodb.ArangoDatabase;
import net.tccn.bbs.base.entity.VisLog;
import org.redkale.net.http.RestMapping;
import org.redkale.net.http.RestService;
import org.redkale.util.AnyValue;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
/**
* @author: liangxianyou at 2018/11/18 9:02.
*/
@RestService(automapping = true, comment = "Arango服务")
public class ArangoService extends BaseService {
protected static final boolean winos = System.getProperty("os.name").contains("Window");
protected Function<String, String> chDev = (s) -> s + (isDev ? "_dev" : "");
@Resource(name = "property.arango.host")
private String arangoHost = "127.0.0.1";
@Resource(name = "property.arango.port")
private int port = 8529;
@Resource(name = "property.arango.database")
private String database = "redbbs";
@Resource(name = "property.arango.user")
private String user = "root";
@Resource(name = "property.arango.password")
private String password = "root";
//日志存放doc名称
private static final String VIS_LOG = "vis_log";
//Arango
protected static ArangoDB arangoDb;
protected static ArangoDatabase db;
protected static ArangoCollection colVisLog;
@Override
public void init(AnyValue config) {
CompletableFuture.runAsync(() -> {
System.out.println("isDev :" + isDev);
arangoDb = new ArangoDB.Builder().host(arangoHost, port).user(user).password(password).build();
db = arangoDb.db(chDev.apply(database));
colVisLog = db.collection(chDev.apply(VIS_LOG));
if (!db.exists()) {
db.create();
}
if (!colVisLog.exists()) {
colVisLog.create();
}
});
}
@RestMapping(auth = false)
public List<Map> hi() {
System.out.println("colVisLog :" + colVisLog.exists());
String aql = String.format("for d in %s limit 10 return d", chDev.apply(VIS_LOG));
List<Map> visLogs = db.query(aql, Map.class).asListRemaining();
return visLogs;
}
public static <T> CompletableFuture<T> save(T t) {
return CompletableFuture.supplyAsync(() -> {
if (t instanceof VisLog) {
colVisLog.insertDocument(t);
}
return t;
});
}
public static long findInt(String aql) {
return db.query(aql, long.class).first();
}
public static long findInt(String aql, Map para) {
return db.query(aql, long.class).first();
}
public static <T> List<T> find(String aql, Class<T> clazz) {
return db.query(aql, clazz).asListRemaining();
}
public static <T> List<T> find(String aql, Map para, Class<T> clazz) {
return db.query(aql, para, clazz).asListRemaining();
}
}

View File

@@ -0,0 +1,14 @@
package net.tccn.bbs.base;
import org.redkale.convert.json.JsonConvert;
/**
* 所有 entity 上层类
*/
public abstract class BaseEntity {
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -1,16 +1,12 @@
package net.tccn.bbs.base;
import com.arangodb.Predicate;
import org.redkale.net.http.RestMapping;
import org.redkale.service.RetResult;
import org.redkale.service.Service;
import org.redkale.source.CacheSource;
import org.redkale.source.DataSource;
import javax.annotation.Resource;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Created by Lxy at 2017/10/3 13:50.
@@ -19,14 +15,13 @@ public class BaseService implements Service {
protected final int sessionExpireSeconds = 7 * 24 * 60 * 60;
@Resource(name = "property.isDev")
public boolean isDev = true;
protected final static RetResult RET_SUCCESS = RetResult.success();
@Resource(name = "SERVER_ROOT")
protected File webroot;
/*@Resource(name = "SERVER_ROOT")
protected File webroot;*/
@Resource(name = "redbbs")
protected DataSource source;
protected DataSource dataSource;
/* 使用redis 代码中配置此处即可
@Resource(name = "redis")*/
@@ -38,35 +33,12 @@ public class BaseService implements Service {
protected static final boolean winos = System.getProperty("os.name").contains("Window");
public static Predicate isEmpty = (x) -> {
if (x == null)
return true;
if (x instanceof List)
return ((List) x).isEmpty();
if (x instanceof String)
return ((String) x).isEmpty();
if (x instanceof Map)
return ((Map) x).isEmpty();
if (x instanceof Collection)
return ((Collection) x).isEmpty();
return false;
};
@RestMapping(ignore = true)
public DataSource getSource() {
return source;
return dataSource;
}
@RestMapping(ignore = true)
public int currentUserid(String sessionid) {
if (sessionid == null) return 0;
long userid = 0;
try {
userid = sessions.getLong(sessionid, 0);
} catch (Exception e) {
e.printStackTrace();
}
return (int) userid;
protected RetResult retError(String info) {
return new RetResult<>(-1, info);
}
}

View File

@@ -1,12 +1,13 @@
package net.tccn.bbs.base;
import com.jfinal.kit.Kv;
import net.tccn.bbs.base.entity.VisLog;
import net.tccn.bbs.base.kit.RetCodes;
import net.tccn.bbs.base.user.UserInfo;
import net.tccn.bbs.base.user.UserService;
import net.tccn.bbs.base.util.RetCodes;
import net.tccn.bbs.base.util.TaskQueue;
import net.tccn.bbs.comment.CommentService;
import net.tccn.bbs.content.ContentService;
import net.tccn.bbs.user.UserInfo;
import net.tccn.bbs.user.UserService;
import net.tccn.bbs.vislog.entity.VisLog;
import org.redkale.net.http.*;
import org.redkale.source.FilterExpress;
import org.redkale.source.FilterNode;
@@ -17,12 +18,11 @@ import java.io.File;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import static net.tccn.bbs.base.kit.RetCodes.RET_USER_UNLOGIN;
import static net.tccn.bbs.base.util.RetCodes.RET_USER_UNLOGIN;
/**
* Created by Lxy at 2017/10/3 13:39.
*/
@HttpUserType(UserInfo.class)
public class BaseServlet extends HttpServlet {
protected static final boolean winos = System.getProperty("os.name").contains("Window");
@@ -59,6 +59,7 @@ public class BaseServlet extends HttpServlet {
if (sessionid != null) {
request.setCurrentUser(userService.current(sessionid));
currentid = userService.currentUserid(sessionid);
request.setCurrentUserid(currentid);
}
String uri = request.getRequestURI();
@@ -156,7 +157,9 @@ public class BaseServlet extends HttpServlet {
public int getParaToInt(HttpRequest request, int index) {
int n = 0;
String para = getPara(request, index);
if (para == null || "".equals(para)) n = 0;
if (para == null || "".equals(para)) {
n = 0;
}
try {
n = Integer.parseInt(para);
} catch (Exception e) {

View File

@@ -1,41 +0,0 @@
package net.tccn.bbs.base;
import org.redkale.net.http.RestMapping;
import org.redkale.net.http.RestService;
import org.redkale.net.http.RestUploadFile;
import org.redkale.service.RetResult;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
/**
* Created by Lxy at 2017/10/3 13:48.
*/
@RestService(automapping = true, comment = "文件服务")
public class FileService extends BaseService {
private static final String dir = "/var/www/upload/redbbs/";
private static final String view = "http://img.1216.top/redbbs/";
private static final String format = "%1$tY%1$tm%1$td%1$tH%1$tM%1$tS";
@RestMapping(name = "upload", comment = "文件上传")
public RetResult upload(@RestUploadFile File tmpFile) throws IOException {
String name = tmpFile.getName();
String suffix = name.substring(name.lastIndexOf("."));
String path = String.format(format, System.currentTimeMillis()) + suffix;
File destFile = new File((winos ? "D:/wk/_own/redbbs/root/tem/" : dir) + path);
destFile.getParentFile().mkdir();
if (!tmpFile.renameTo(destFile)) {
try {
Files.copy(tmpFile.toPath(), destFile.toPath(), StandardCopyOption.ATOMIC_MOVE);
} finally {
tmpFile.delete();//删除临时文件
}
}
RetResult result = RetResult.success();
result.setRetinfo((winos ? "/tem/" : view) + path);
return result;
}
}

View File

@@ -3,8 +3,8 @@ package net.tccn.bbs.base;
import com.jfinal.kit.Kv;
import com.jfinal.template.Engine;
import com.jfinal.template.Template;
import net.tccn.bbs.base.kit.EJ;
import net.tccn.bbs.base.user.UserInfo;
import net.tccn.bbs.base.util.EJ;
import net.tccn.bbs.user.UserInfo;
import org.redkale.convert.Convert;
import org.redkale.net.http.*;
import org.redkale.util.AnyValue;
@@ -16,7 +16,7 @@ import java.util.Map;
/**
* Created by JUECHENG at 2018/1/30 0:18.
*/
public class EnjoyRender implements HttpRender<HttpScope> {
public class TplRender implements HttpRender<HttpScope> {
@Resource(name = "SERVER_ROOT")
protected File webroot;
@@ -25,9 +25,10 @@ public class EnjoyRender implements HttpRender<HttpScope> {
@Override
public void init(HttpContext context, AnyValue config) {
engine.setDevMode(true);
engine.setBaseTemplatePath(webroot.getPath());
engine.addSharedObject("EJ", new EJ());
engine.addSharedFunction("/_t/layout.html");
engine.addSharedFunction("/_tpl/layout.html");
}
@Override

View File

@@ -1,13 +0,0 @@
package net.tccn.bbs.base;
import net.tccn.bbs.base.iface.UI;
/**
* user foreign key (userId)
* Created by liangxianyou at 2018/6/9 14:50.
*/
public interface UF<I extends UI> {
int getUserid();
I createInfo();
}

View File

@@ -0,0 +1,750 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package net.tccn.bbs.base;
import net.tccn.bbs.base.util.Kv;
import org.redkale.source.DataJdbcSource;
import org.redkale.source.DataSource;
import org.redkale.source.Flipper;
import org.redkale.util.Comment;
import org.redkale.util.Reproduce;
import org.redkale.util.Sheet;
import org.redkale.util.Utility;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class Utils {
private Utils() {
}
public static String dateFmt(long time) {
/**
* 刚刚 60秒内 60 * 1000
* x分钟前 1小时候内 60 * 60*1000
* x小时前 1天内 24 * 60*60*1000
* x天前 1周内 7 * 24*60*60*1000
* 年-月-日 1周前
*/
long now = System.currentTimeMillis();
long diff = now - time;
if (diff < 60 * 1000)
return "刚刚";
else if (diff < 60 * 60 * 1000)
return Math.floorDiv(diff, 60 * 1000) + "分钟前";
else if (diff < 24 * 60 * 60 * 1000)
return Math.floorDiv(diff, 60 * 60 * 1000) + "小时前";
else if (diff > 24 * 60 * 60 * 1000 && diff < 7 * 24 * 60 * 60 * 1000)
return Math.floorDiv(diff, 24 * 60 * 60 * 1000) + "天前";
else
return new SimpleDateFormat("yyyy-MM-dd").format(time);
}
public static String delHTMLTag(String htmlStr) {
String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式
Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
Matcher m_script = p_script.matcher(htmlStr);
htmlStr = m_script.replaceAll(""); //过滤script标签
Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
Matcher m_style = p_style.matcher(htmlStr);
htmlStr = m_style.replaceAll(""); //过滤style标签
Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
Matcher m_html = p_html.matcher(htmlStr);
htmlStr = m_html.replaceAll(""); //过滤html标签
return htmlStr.trim(); //返回文本字符串
}
public static <T> T[] listToArray(List list, T[] ts) {
for (int i = 0; i < list.size(); i++) {
ts[0] = (T) list.get(i);
}
return ts;
}
public static int[] listToArray(List list, int[] ts) {
for (int i = 0; i < list.size(); i++) {
ts[0] = (int) list.get(i);
}
return ts;
}
/**
* 判断对象是否为空
*
* @param obj 待判断的对象
* @return
*/
public static boolean isEmpty(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof String) {
return ((String) obj).trim().isEmpty();
} else if (obj instanceof Collection) {
return ((Collection) obj).isEmpty();
} else if (obj instanceof Map) {
return ((Map) obj).isEmpty();
} else if (obj.getClass().isArray() && Array.getLength(obj) == 0) {
return true;
}
return false;
}
private static Map<String, Reproduce> reproduceMap = new HashMap<>();
/**
* @param d 目标对象
* @param s 源对象
* @param <D> 目标对象的数据类型
* @param <S> 源对象的数据类型
* @return
*/
public static <D, S> D copy(D d, S s) {
String reproductKey = d.getClass().getName() + "_" + s.getClass().getName();
Reproduce<D, S> reproduce = reproduceMap.get(reproductKey);
if (reproduce == null) {
if (reproduce == null) {
reproduceMap.put(reproductKey, reproduce = (Reproduce<D, S>) Reproduce.create(d.getClass(), s.getClass()));
}
}
return reproduce.apply(d, s);
}
public static List<String> parseHtmlImage(String html) {
Pattern pattern = Pattern.compile("(?<=(<img\\s?src\\s?=\\s?\"))\\S+\\.[A-Za-z]+");
Matcher match = pattern.matcher(html);
List<String> ls = new ArrayList<>();
while (match.find()) {
ls.add(match.group());
}
return ls;
}
/**
* @param rs
* @param type
* @param <T>
* @return
*/
public static <T> List<T> queryList(ResultSet rs, Class<T> type) {
try {
List list = new ArrayList();
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
while (rs.next()) {
Kv row = Kv.of();
for (int i = 1; i <= count; i++) {
String columnTypeName = metaData.getColumnTypeName(i);
//String columnName = metaData.getColumnName(i);
String columnLabel = metaData.getColumnLabel(i);
row.put(columnLabel, null);
if (rs.getObject(i) != null) {
switch (columnTypeName) {
case "DATETIME", "TIMESTAMP", "DATE" -> row.put(columnLabel, rs.getTimestamp(i).getTime());
default -> row.put(columnLabel, rs.getObject(i));
}
}
}
list.add((Map.class == type || Kv.class == type) ? row : Kv.toBean(row, type));
}
return list;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
/**
* 查询 第一条的 第一列数据 值
*
* @param rs
* @param type
* @param <T>
* @return
*/
public static <T> T findColumn(ResultSet rs, Class<T> type) {
try {
Object v = null;
while (rs.next()) {
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
for (int i = 1; i <= count; i++) {
String columnTypeName = metaData.getColumnTypeName(i);
if (rs.getObject(i) != null) {
switch (columnTypeName) {
case "DATETIME", "TIMESTAMP", "DATE" -> v = rs.getTimestamp(i).getTime();
default -> v = rs.getObject(i);
}
}
break;
}
}
return Kv.toAs(v, type);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
/**
* List 混排
*
* @param list
* @return
*/
public static <T> List<T> mix(List<T> list) {
int len = list.size();
Random random = new Random();
for (int i = 0; i < len; i++) {
int r = random.nextInt(len);
if (i == r) continue;
T x = list.get(i);
list.set(i, list.get(r));
list.set(r, x);
}
return list;
}
@Comment("获取集合随机元素")
public static <T> List<T> randomItems(List<T> list, int len) {
List<Integer> randoms = getRandoms(list.size(), len);
List<T> items = new ArrayList<>(randoms.size());
randoms.forEach(x -> items.add(list.get(x)));
return items;
}
@Comment("获取随机数字符")
public static String randomNumber(int len) {
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < len; i++) {
sb.append(random.nextInt(9));
}
return sb.toString();
}
@Comment("获取随机数集合")
private static List<Integer> getRandoms(int max, int len) {
Set<Integer> randoms = new HashSet<>();
Random random = new Random();
while (randoms.size() < len && randoms.size() < max) {
randoms.add(random.nextInt(max));
}
List<Integer> list = randoms.stream().collect(Collectors.toList());
return mix(list);
}
/**
* unicode转中文
*
* @param str
* @return
*/
public static String unicodeToCn(String str) {
Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
Matcher matcher = pattern.matcher(str);
char ch;
while (matcher.find()) {
ch = (char) Integer.parseInt(matcher.group(2), 16);
str = str.replace(matcher.group(1), ch + "");
}
return str;
}
/**
* 计算字符串的字符长度
*
* @param value
* @return
*/
public static int strLength(String value) {
int valueLength = 0;
String chinese = "[\u4e00-\u9fa5]";
for (int i = 0; i < value.length(); i++) {
String temp = value.substring(i, i + 1);
if (temp.matches(chinese)) {
valueLength += 2;
} else {
valueLength += 1;
}
}
return valueLength;
}
public static String randomIP() {
// aaa.aaa.aaa.aaa
StringBuilder buf = new StringBuilder();
Random r = new Random();
buf.append("x").append(".");
buf.append(r.nextInt(255)).append(".");
buf.append(r.nextInt(255)).append(".");
buf.append(r.nextInt(255));
return buf.toString();
}
public static String fmt36(int n) {
return Integer.toString(n, 36);
}
public static String fmt36(long n) {
return Long.toString(n, 36);
}
public static <T, V> Map<T, V> toMap(Collection<V> list, Function<V, T> fun) {
Map<T, V> map = new HashMap<>(list.size());
for (V v : list) {
if (v == null) {
continue;
}
map.put(fun.apply(v), v);
}
return map;
}
public static <T, V, T2> Map<T, T2> toMap(Collection<V> list, Function<V, T> fun, Function<V, T2> fun2) {
Map<T, T2> map = new HashMap<>(list.size());
for (V v : list) {
if (v == null) {
continue;
}
map.put(fun.apply(v), fun2.apply(v));
}
return map;
}
public static <T, V> List<V> toList(Collection<T> list, Function<T, V> fun) {
if (list == null || list.isEmpty()) {
return new ArrayList<>();
}
List<V> list1 = new ArrayList<>();
list.forEach(x -> list1.add(fun.apply(x)));
return list1;
}
public static <T, V> List<V> toList(Sheet<T> sheet, Function<T, V> fun) {
List<V> list = new ArrayList<>();
sheet.forEach(x -> list.add(fun.apply(x)));
return list;
}
public static <T, V> Set<V> toSet(Collection<T> list, Function<T, V> fun) {
if (list == null || list.isEmpty()) {
return new HashSet<>();
}
Set<V> set = new HashSet<>(list.size());
list.forEach(x -> set.add(fun.apply(x)));
return set;
}
public static <T, V> Set<V> toSet(Sheet<T> sheet, Function<T, V> fun) {
Set<V> set = new HashSet<>();
sheet.forEach(x -> set.add(fun.apply(x)));
return set;
}
public static <T> List<T> filter(Collection<T> list, Predicate<T> predicate) {
if (list == null || list.isEmpty()) {
return new ArrayList<>();
}
List<T> list1 = new ArrayList<>(list.size());
list.forEach(x -> {
if (!predicate.test(x)) {
return;
}
list1.add(x);
});
return list1;
}
public static <T, V> List<V> filterToList(Collection<T> list, Predicate<T> predicate, Function<T, V> fun) {
if (list == null || list.isEmpty()) {
return new ArrayList<>();
}
List<V> list1 = new ArrayList<>(list.size());
list.forEach(x -> {
if (!predicate.test(x)) {
return;
}
list1.add(fun.apply(x));
});
return list1;
}
public static <T, V> Map<V, List<T>> group(Collection<T> list, Function<T, V> fun) {
if (list == null || list.isEmpty()) {
return new HashMap<>();
}
return list.stream().collect(Collectors.groupingBy(fun));
}
public static <T, V, K> Map<V, List<K>> group(Collection<T> list, Function<T, V> fun, Function<T, K> fun2) {
if (list == null || list.isEmpty()) {
return new HashMap<>();
}
Map<V, List<T>> group = group(list, fun);
Map<V, List<K>> _group = new HashMap<>();
group.forEach((k, v) -> _group.put(k, toList(v, fun2)));
return _group;
}
public static String getHtmlBody(String html) {
String s = html.replaceAll("\n", "");
int bodyIndex = s.indexOf("<body>");
if (bodyIndex > -1) {
bodyIndex = bodyIndex + 6;
int lastIndexOf = s.lastIndexOf("</body>");
if (lastIndexOf < bodyIndex) lastIndexOf = s.length();
s = s.substring(bodyIndex, lastIndexOf);
}
return s;
}
public static String getHtmlText(String html) {
return html.replaceAll("<([^ \\f\\n\\r\\t\\v<]| )+>", "");
}
//获取指定日期的 前/后 几天日期
public static long plusDays(long datetime, int daynum) {
if (daynum == 0 || datetime == 0) {
return datetime;
}
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(datetime), zoneId);
time = time.plusDays(daynum);
return time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
}
// -----------------
private static final MessageDigest sha1;
private static final MessageDigest md5;
private static final String AES_KEY = "HAOGAME_20200721";
private static final Cipher aesEncrypter; //加密
private static final Cipher aesDecrypter; //解密
static {
MessageDigest d = null;
try {
d = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException ex) {
throw new Error(ex);
}
sha1 = d;
try {
d = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException ex) {
throw new Error(ex);
}
md5 = d;
Cipher cipher = null;
final SecretKeySpec aesKey = new SecretKeySpec(AES_KEY.getBytes(), "AES");
try {
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
} catch (Exception e) {
throw new Error(e);
}
aesEncrypter = cipher; //加密
try {
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, aesKey);
} catch (Exception e) {
throw new Error(e);
}
aesDecrypter = cipher; //解密
}
//AES加密
public static String encryptAES(String value) {
if (value == null || value.isEmpty()) {
return value;
}
try {
synchronized (aesEncrypter) {
return Utility.binToHexString(aesEncrypter.doFinal(value.getBytes()));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//AES解密
public static String decryptAES(String value) {
if (value == null || value.isEmpty()) {
return value;
}
byte[] hex = Utility.hexToBin(value);
try {
synchronized (aesEncrypter) {
return new String(aesDecrypter.doFinal(hex));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Comment("GET请求参数转换为字符结果p1=v1&p2=v2&p3=v3")
public static String convertHttpParams(Map map, boolean encode) {
if (map == null || map.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
map.forEach((k, v) -> {
if (Utils.isEmpty(k) || Utils.isEmpty(v)) {
return;
}
String value = String.valueOf(v);
if (encode) {
value = URLEncoder.encode(String.valueOf(v), StandardCharsets.UTF_8);
}
sb.append("&").append(k).append("=").append(value);
});
return sb.length() > 0 ? sb.substring(1) : "";
}
@Comment("对象转GET请求参数转换为字符结果p1=v1&p2=v2&p3=v3")
public static String convertHttpParams(Object o, List<String> removeFields, boolean encode) {
Class<? extends Object> c = o.getClass();
Field[] fields = c.getDeclaredFields();
Map<String, Object> map = new TreeMap<String, Object>();
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
if (!Utils.isEmpty(removeFields) && removeFields.contains(name)) {
continue;
}
Object value = null;
try {
value = field.get(o);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (value != null) {
map.put(name, value);
}
}
return convertHttpParams(map, encode);
}
@Comment("GET请求参数转换为字符结果p1=v1&p2=v2&p3=v3")
public static String convertHttpParams(Map<String, Object> map) {
if (map == null || map.isEmpty()) {
return "";
}
Set<String> sortSet = new TreeSet<String>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
sortSet.add(entry.getKey());
}
// 参数名按ASCII码从小到大排序字典序,然后使用( & )连接排好序的key=value集合
StringBuffer sb = new StringBuffer();
boolean isFirst = true;
for (String key : sortSet) {
if (isFirst) {
sb.append(key + "=" + URLEncoder.encode(String.valueOf(map.get(key)), StandardCharsets.UTF_8));
isFirst = false;
} else {
sb.append("&" + key + "=" + URLEncoder.encode(String.valueOf(map.get(key)), StandardCharsets.UTF_8));
}
}
return sb.toString();
}
@Comment("对象转map")
public static Map<String, Object> convertToMap(Object o, List<String> removeFields) {
Class<? extends Object> c = o.getClass();
List<Field> fields = Stream.of(c.getDeclaredFields()).collect(Collectors.toList());
if (c.getSuperclass() != null) {
Field[] superFields = c.getSuperclass().getDeclaredFields();
if (superFields.length > 0) {
fields.addAll(Arrays.asList(superFields));
}
}
Map<String, Object> map = new TreeMap<>();
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
if (!Utils.isEmpty(removeFields) && removeFields.contains(name)) {
continue;
}
Object value = null;
try {
value = field.get(o);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (value != null) {
map.put(name, value);
}
}
return map;
}
@Comment("key字典排序")
public static LinkedHashMap sortedMap(Map<String, ?> map, String... excludeKeys) {
List<String> excludeList = List.of(excludeKeys);
LinkedHashMap<String, Object> linkedHashMap = new LinkedHashMap<>();
map.entrySet().stream()
.filter(f -> !excludeList.contains(f.getKey()))
.sorted(Map.Entry.comparingByKey())
.forEach(x -> linkedHashMap.put(x.getKey(), x.getValue()));
return linkedHashMap;
}
@Comment(" string转化为jsonstring")
public static String convertParamStrToJsonStr(String paramStr) {
StringBuilder builder = new StringBuilder();
Arrays.stream(paramStr.split("&")).forEach(x -> {
//防止有地址传参时造成的错误解析
x = URLDecoder.decode(x, StandardCharsets.UTF_8);
int index = x.indexOf("=");
char c = x.charAt(index + 1);
builder.append(String.format("\"%s\":\"%s\",", x.substring(0, index), c == '[' || c == '{' ? x.substring(index + 1).replaceAll("\"", "\\\\\"") : x.substring(index + 1)));
});
return String.format("{%s}", builder.deleteCharAt(builder.length() - 1).toString());
}
public static <T> Sheet<T> querySheetBySql(DataSource dataSource, String sql, Flipper flipper, Class<T> type) {
DataJdbcSource jdbcSource = (DataJdbcSource) dataSource;
//总条数
int total = jdbcSource.directQuery("select count(0) c from (" + sql + ") c", rs -> {
int result = 0;
try {
while (rs.next()) {
result = rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
});
if (total == 0) {
return new Sheet<>(0, new ArrayList<>());
}
if (flipper != null) {
sql = String.format("%s %s limit %s,%s ", sql, Utils.isEmpty(flipper.getSort()) ? "" : "order by " + flipper.getSort(), flipper.getOffset(), flipper.getLimit());
}
List<T> dataList = jdbcSource.directQuery(sql, rs -> Utils.queryList(rs, type));
return new Sheet<>(total, dataList);
}
@Comment("获取次日0点0分0秒时间戳")
public static long getNextDayZero() {
LocalDate localDate = LocalDate.now();
localDate = localDate.plusDays(1);
LocalDateTime dateTime = LocalDateTime.of(localDate.getYear(), localDate.getMonth(), localDate.getDayOfMonth(), 0, 0, 0);
return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
public static String formatTime(long time, String pattern) {
if (Utils.isEmpty(pattern)) pattern = "yyyy-MM-dd";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(new Date(time));
}
@Comment("获取字符串中某个字符的数量")
public static int strCountOfChar(String str, String code) {
int fromIndex = 0;
int count = 0;
while (true) {
int index = str.indexOf(code, fromIndex);
if (-1 != index) {
fromIndex = index + 1;
count++;
} else {
break;
}
}
return count;
}
private static Random random = new Random();
public static int randomNum(int len) {
int rs = random.nextInt(9);
if (rs == 0) rs = 1;
for (int i = 0; i < len - 1; i++) { //总长度为6
rs = rs * 10 + random.nextInt(9);
}
return rs;
}
public static String genMd5(String info) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
byte[] infoBytes = info.getBytes();
md5.update(infoBytes);
byte[] sign = md5.digest();
return byteArrayToHex(sign);
}
public static String byteArrayToHex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (byte aByte : bytes) {
String hex = Integer.toHexString(aByte & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toLowerCase());
}
return sign.toString();
}
}

View File

@@ -1,43 +0,0 @@
package net.tccn.bbs.base.bean;
import lombok.Getter;
import lombok.Setter;
import org.redkale.convert.json.JsonConvert;
import org.redkale.source.FilterBean;
import javax.persistence.Column;
import java.io.Serializable;
/**
* @author lxyer
*/
@Setter
@Getter
public class ActLogBean implements Serializable, FilterBean {
@Column(comment = "[日志id]")
private int logid;
@Column(comment = "[日志类型]")
private int cate;
@Column(comment = "[目标数据id]")
private int tid;
@Column(comment = "[用户id]")
private int userId;
@Column(comment = "[创建时间]")
private long createTime;
@Column(length = 128, comment = "[说明]")
private String remark = "";
@Column(comment = "[状态]-1删除 1正常")
private int status = 1;
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -1,58 +0,0 @@
package net.tccn.bbs.base.entity;
import lombok.Getter;
import lombok.Setter;
import org.redkale.convert.json.JsonConvert;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author lxyer
*/
@Setter
@Getter
@Cacheable(interval = 5 * 60)
@Table(catalog = "redbbs", name = "sys_actlog")
public class ActLog implements java.io.Serializable {
@Id
@Column(comment = "[日志id]")
private int logid;
@Column(comment = "[日志类型]10赞20收藏30阅读")
private short cate;
@Column(comment = "[目标数据id]")
private int tid;
@Column(comment = "[用户id]")
private int userid;
@Column(updatable = false, comment = "[创建时间]")
private long createtime;
@Column(length = 128, comment = "[说明]")
private String remark = "";
@Column(comment = "[状态]-1删除 1正常")
private short status = 10;
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
//----
public ActLog() {
}
public ActLog(int cate, int tid, int userid) {
this.cate = (short) cate;
this.tid = tid;
this.userid = userid;
}
}

View File

@@ -1,26 +0,0 @@
package net.tccn.bbs.base.entity;
import lombok.Getter;
import lombok.Setter;
/**
* 用来计数用
*
* @author: liangxianyou at 2018/11/18 20:42.
*/
@Setter
@Getter
public class Count {
private String name;
private long total;
//-------------------
@Override
public String toString() {
return "Count{" +
"name='" + name + '\'' +
", total=" + total +
'}';
}
}

View File

@@ -1,38 +0,0 @@
package net.tccn.bbs.base.entity;
import lombok.Getter;
import lombok.Setter;
import org.redkale.convert.json.JsonConvert;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author lxyer
*/
@Setter
@Getter
@Cacheable(interval = 5 * 60)
@Table(catalog = "redbbs", name = "sys_dynattr", comment = "[动态属性表]")
public class DynAttr implements java.io.Serializable {
@Id
@Column(comment = "[目标数据id]")
private int tid;
@Column(comment = "[类型]1文章, 2xx, 3...,")
private short cate;
@Column(length = 32, comment = "")
private String attr = "";
@Column(comment = "[属性值]")
private String value = "";
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -1,29 +0,0 @@
package net.tccn.bbs.base.entity;
import lombok.Getter;
import lombok.Setter;
import org.redkale.convert.json.JsonConvert;
import java.util.Map;
/**
* 存贮数据到 非关系型数据库
*
* @author: liangxianyou at 2018/11/18 8:47.
*/
@Setter
@Getter
public class VisLog {
private String ip;
private int userid;
private String ftime;
private String uri;
private long time;
private Map para;
private Map headers;
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -1,9 +0,0 @@
package net.tccn.bbs.base.iface;
/**
* 创建信息
* Created by liangxianyou at 2018/6/16 17:43.
*/
public interface C<I extends CI> {
I createInfo();
}

View File

@@ -1,7 +0,0 @@
package net.tccn.bbs.base.iface;
/**
* Created by liangxianyou at 2018/6/16 18:39.
*/
public interface CI<I extends CI> {
}

View File

@@ -1,32 +0,0 @@
package net.tccn.bbs.base.iface;
import org.redkale.net.http.RestMapping;
import org.redkale.util.Sheet;
import java.util.ArrayList;
import java.util.List;
/**
* Created by liangxianyou at 2018/6/16 17:56.
*/
public interface CService<I extends UI> {
@RestMapping(ignore = true)
default <A extends C> Sheet<I> createInfo(Sheet<A> fSheet) {
Sheet<I> sheet = new Sheet<>();
if (fSheet == null || fSheet.getTotal() < 1) {
sheet.setTotal(0);
sheet.setRows(new ArrayList<>());
} else {
int total = (int) fSheet.getTotal();
List<I> rows = new ArrayList<>(total);
fSheet.forEach(x -> rows.add((I) x.createInfo()));
sheet.setTotal(total);
sheet.setRows(rows);
}
return sheet;
}
}

View File

@@ -1,37 +0,0 @@
package net.tccn.bbs.base.iface;
import net.tccn.bbs.base.user.UserRecord;
/**
* Created by liangxianyou at 2018/6/9 13:45.
*/
public interface UI<I extends UI> {
//抽象方法
int getUserid();
UserRecord getUser();
I setUser(UserRecord user);
//默认实现方法
default String getRealname() {
return getUser() == null ? null : getUser().getRealname();
}
default String getNickname() {
return getUser() == null ? null : getUser().getNickname();
}
default String getSite() {
return getUser() == null ? "" : getUser().getSite();
}
default String getGit() {
return getUser() == null ? "" : getUser().getGit();
}
default String getAvatar() {
return getUser() == null ? null : getUser().getAvatar();
}
}

View File

@@ -1,38 +0,0 @@
package net.tccn.bbs.base.iface;
import net.tccn.bbs.base.user.UserRecord;
import org.redkale.net.http.RestMapping;
import org.redkale.source.DataSource;
import org.redkale.source.FilterExpress;
import org.redkale.source.FilterNode;
import org.redkale.util.Sheet;
import java.util.List;
/**
* Created by liangxianyou at 2018/6/16 18:25.
*/
public interface UIService<I extends UI> extends CService<I> {
DataSource getSource();
@RestMapping(ignore = true)
default Sheet<I> setIUser(Sheet<I> sheet) {
int[] userids = sheet.stream().mapToInt(I::getUserid).toArray();
List<UserRecord> users = getSource().queryList(UserRecord.class, FilterNode.create("userid", FilterExpress.IN, userids));
sheet.forEach(x -> {
UserRecord user = users.stream().filter(u -> u.getUserid() == x.getUserid()).findAny().orElse(null);
x.setUser(user);
});
return sheet;
}
@RestMapping(ignore = true)
default I setIUser(I i) {
UserRecord user = getSource().find(UserRecord.class, i.getUserid());
return (I) i.setUser(user);
}
}

View File

@@ -1,70 +0,0 @@
package net.tccn.bbs.base.kit;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Lxy at 2017/11/29 15:17.
*/
public final class LxyKit {
public static String dateFmt(long time) {
/**
* 刚刚 60秒内 60 * 1000
* x分钟前 1小时候内 60 * 60*1000
* x小时前 1天内 24 * 60*60*1000
* x天前 1周内 7 * 24*60*60*1000
* 年-月-日 1周前
*/
long now = System.currentTimeMillis();
long diff = now - time;
if (diff < 60 * 1000)
return "刚刚";
else if (diff < 60 * 60 * 1000)
return Math.floorDiv(diff, 60 * 1000) + "分钟前";
else if (diff < 24 * 60 * 60 * 1000)
return Math.floorDiv(diff, 60 * 60 * 1000) + "小时前";
else if (diff > 24 * 60 * 60 * 1000 && diff < 7 * 24 * 60 * 60 * 1000)
return Math.floorDiv(diff, 24 * 60 * 60 * 1000) + "天前";
else
return new SimpleDateFormat("yyyy-MM-dd").format(time);
}
public static String delHTMLTag(String htmlStr) {
String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式
Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
Matcher m_script = p_script.matcher(htmlStr);
htmlStr = m_script.replaceAll(""); //过滤script标签
Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
Matcher m_style = p_style.matcher(htmlStr);
htmlStr = m_style.replaceAll(""); //过滤style标签
Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
Matcher m_html = p_html.matcher(htmlStr);
htmlStr = m_html.replaceAll(""); //过滤html标签
return htmlStr.trim(); //返回文本字符串
}
public static <T> T[] listToArray(List list, T[] ts) {
for (int i = 0; i < list.size(); i++) {
ts[0] = (T) list.get(i);
}
return ts;
}
public static int[] listToArray(List list, int[] ts) {
for (int i = 0; i < list.size(); i++) {
ts[0] = (int) list.get(i);
}
return ts;
}
}

View File

@@ -1,28 +0,0 @@
package net.tccn.bbs.base.user;
import lombok.Getter;
import lombok.Setter;
import org.redkale.net.http.RestSessionid;
import org.redkale.source.FilterBean;
import org.redkale.util.Comment;
import javax.persistence.Transient;
/**
* Created by Lxy at 2017/10/1 10:40.
*/
@Setter
@Getter
public class LoginBean implements FilterBean {
private String username;
private String password;
@Transient
@Comment("会话SESSIONID")
@RestSessionid(create = true)
private String sessionid = "";
public boolean emptyUsername() {
return username == null || username.isEmpty();
}
}

View File

@@ -1,32 +0,0 @@
package net.tccn.bbs.base.user;
import lombok.Getter;
import lombok.Setter;
import org.redkale.source.FilterBean;
import javax.persistence.Column;
/**
* Created by Lxy at 2017/10/10 8:30.
*/
@Setter
@Getter
public class UserBean implements FilterBean {
@Column(length = 32, comment = "[登录名]")
private String username;
@Column(length = 32, comment = "[电话号码]")
private String phone;
@Column(length = 64, comment = "[昵称]")
private String nickname;
@Column(length = 32, comment = "[真实姓名]")
private String realname;
@Column(length = 32, comment = "[邮箱]")
private String email;
}

View File

@@ -1,54 +0,0 @@
package net.tccn.bbs.base.user;
import lombok.Getter;
import lombok.Setter;
import org.redkale.convert.json.JsonConvert;
import javax.persistence.Column;
import javax.persistence.Id;
/**
* @author lxyer
*/
@Setter
@Getter
public class UserInfo implements java.io.Serializable {
@Id
@Column(comment = "[用户id]")
private int userid;
private String username = "";
private int sex = 1;
private String password = "";
private String phone = "";
private String nickname = "";
private String avatar = "";
private String relaname = "";
private String email = "";
private int roleid = 0;
private String site = "";
private String git = "";
private long createtime;
private String sign = "";
private String city = "";
private int status = 1;
private String time = "";
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
/**
* 检查用户权限
*
* @param moduleid
* @param actionid
* @return
*/
public boolean checkAuth(int moduleid, int actionid) {
return !(moduleid == 2 && actionid == 1);
}
}

View File

@@ -1,106 +0,0 @@
package net.tccn.bbs.base.user;
import lombok.Getter;
import lombok.Setter;
import org.redkale.convert.json.JsonConvert;
import org.redkale.util.Utility;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author lxyer
*/
@Setter
@Getter
@Cacheable(interval = 5 * 60)
@Table(catalog = "redbbs", name = "sys_userrecord")
public class UserRecord implements java.io.Serializable {
@Id
@Column(comment = "[用户id]")
private int userid;
@Column(length = 32, comment = "[登录名]")
private String username = "";
@Column(length = 64, comment = "[密码]")
private String password = "";
@Column(comment = "[性别]默认 10男20女")
private short sex;
@Column(length = 32, comment = "[电话号码]")
private String phone = "";
@Column(length = 64, comment = "[昵称]")
private String nickname = "";
@Column(length = 128, comment = "[头像地址]")
private String avatar = "";
@Column(length = 32, comment = "[真实姓名]")
private String realname = "";
@Column(length = 32, comment = "[邮箱]")
private String email = "";
@Column(comment = "")
private int roleid;
@Column(length = 128, comment = "[个人博客地址]")
private String site = "";
@Column(length = 128, comment = "[码云/GitHub]")
private String git = "";
@Column(updatable = false, comment = "[创建时间]")
private long createtime;
@Column(length = 256, comment = "[签名]")
private String sign = "";
@Column(length = 64, comment = "[所在城市]")
private String city = "";
@Column(comment = "[状态]-10删除 10正常")
private short status = 10;
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
//------
public UserInfo createUserInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setUserid(userid);
userInfo.setUsername(username);
userInfo.setSex(sex);
userInfo.setPassword(password);
userInfo.setPhone(phone);
userInfo.setNickname(nickname);
userInfo.setAvatar(avatar);
userInfo.setRelaname(realname);
userInfo.setEmail(email);
userInfo.setRoleid(roleid);
userInfo.setSite(site);
userInfo.setGit(git);
userInfo.setCreatetime(createtime);
userInfo.setSign(sign);
userInfo.setCity(city);
userInfo.setStatus(getStatus());
return userInfo;
}
public String passwordForMd5() {
return md5IfNeed(password);
}
public static String md5IfNeed(String password) {
return Utility.md5Hex(password);
}
}

View File

@@ -1,181 +0,0 @@
package net.tccn.bbs.base.user;
import com.jfinal.kit.Kv;
import net.tccn.bbs.base.BaseService;
import net.tccn.bbs.base.kit.LxyKit;
import net.tccn.bbs.base.kit.RetCodes;
import org.redkale.net.http.RestMapping;
import org.redkale.net.http.RestParam;
import org.redkale.net.http.RestService;
import org.redkale.net.http.RestSessionid;
import org.redkale.service.RetResult;
import org.redkale.source.FilterExpress;
import org.redkale.source.FilterFunc;
import org.redkale.source.FilterNode;
import org.redkale.source.Flipper;
import org.redkale.util.SelectColumn;
import org.redkale.util.Sheet;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import static net.tccn.bbs.base.kit.RetCodes.*;
/**
* Created by Lxy at 2017/10/3 14:02.
*/
@RestService(automapping = true, comment = "用户服务")
public class UserService extends BaseService {
@RestMapping(auth = false, comment = "登录校验")
public RetResult<UserInfo> login(LoginBean bean) {
if (bean == null || bean.emptyUsername()) return RetCodes.retResult(RetCodes.RET_PARAMS_ILLEGAL, "参数错误");
final RetResult retResult = new RetResult();
UserRecord user = source.find(UserRecord.class, "username", bean.getUsername());
if (user == null || !Objects.equals(user.getPassword(), bean.getPassword())) {
//log(null, 0, "用户或密码错误");
return RetCodes.retResult(RetCodes.RET_USER_ACCOUNT_PWD_ILLEGAL, "用户名或密码错误");
}
sessions.setAsync(sessionExpireSeconds, bean.getSessionid(), (long) user.getUserid());
retResult.setRetcode(0);
retResult.setResult(Kv.by("token", bean.getSessionid()));
retResult.setRetinfo("登录成功.");
return retResult;
}
public UserInfo current(String sessionid) {
if (sessionid == null) return null;
long userid = 0;
try {
userid = sessions.getLong(sessionid, 0);
sessions.getAndRefresh(sessionid, sessionExpireSeconds);
} catch (Exception e) {
e.printStackTrace();
}
return userid == 0 ? null : find((int) userid);
}
@RestMapping(name = "info", comment = "用户信息")
public UserInfo find(int userid) {
UserRecord user = source.find(UserRecord.class, userid);
UserInfo bean = user.createUserInfo();
return bean;
}
@RestMapping(name = "logout", auth = false, comment = "退出登录")
public RetResult logout(@RestSessionid String sessionid) {
sessions.remove(sessionid);
return RetResult.success();
//return new HttpResult().header("Location", "/").status(302);
}
@RestMapping(name = "query", auth = false, comment = "用户数据查询")
public Sheet<UserRecord> query(Flipper flipper, @RestParam(name = "bean", comment = "过滤条件") final UserBean userBean) {
Sheet<UserRecord> users = source.querySheet(UserRecord.class, flipper, userBean);
return users;
}
@RestMapping(name = "changepwd", comment = "修改密码")
public RetResult updatePwd(@RestSessionid String sessionid, String pass, String nowpass) {
UserInfo userInfo = current(sessionid);//不会为空
if (!Objects.equals(userInfo.getPassword(), UserRecord.md5IfNeed(nowpass)))
return RetCodes.retResult(RET_USER_ACCOUNT_PWD_ILLEGAL, "密码错误");
if (pass == null || pass.length() < 6 || Objects.equals(pass, nowpass))
return RetCodes.retResult(RET_USER_PASSWORD_ILLEGAL, "密码设置无效");
source.updateColumn(UserRecord.class, userInfo.getUserid(), "password", UserRecord.md5IfNeed(pass));
return RetResult.success();
}
@RestMapping(name = "register", auth = false, comment = "用户注册")
public RetResult register(UserRecord bean) {
/*用户名、密码、邮箱*/
if (bean.getEmail() == null) return RetCodes.retResult(RET_USER_EMAIL_ILLEGAL, "邮件地址无效");
if (bean.getPassword() == null || bean.getPassword().length() < 6)
return RetCodes.retResult(RET_USER_PASSWORD_ILLEGAL, "密码设置无效");
UserRecord _user = source.find(UserRecord.class, FilterNode.create("email", bean.getEmail()));
if (_user != null) return RetCodes.retResult(RET_USER_USERNAME_EXISTS, "用户名已存在");
bean.setCreatetime(System.currentTimeMillis());
bean.setPassword(bean.passwordForMd5());
bean.setStatus((short) 10);
bean.setUsername(bean.getEmail());
bean.setAvatar("/res/images/avatar/" + new Random().nextInt(21) + ".jpg");//默认头像
int maxId = source.getNumberResult(UserRecord.class, FilterFunc.MAX, 10_0000, "userid").intValue();
if (maxId < 10_0000) maxId = 10_0000;
bean.setUserid(maxId + 1);
source.insert(bean);
//记录日志
return RetResult.success();
}
@RestMapping(name = "update", comment = "用户信息修改")
public RetResult userUpdate(UserInfo user, UserRecord bean, String[] columns) {
String nickname = bean.getNickname();
if (nickname == null && nickname.isEmpty())
return RetCodes.retResult(RET_USER_NICKNAME_ILLEGAL, "昵称无效");
nickname = nickname.replace(" ", "");
UserRecord _user = source.find(UserRecord.class, FilterNode.create("nickname", nickname));
if (_user != null && _user.getUserid() != user.getUserid())
return RetCodes.retResult(RET_USER_NICKNAME_EXISTS, "昵称已存在");
bean.setNickname(nickname);//去除昵称中的空格
source.updateColumn(bean
, FilterNode.create("userid", user.getUserid())
, SelectColumn.includes(columns)
);
return RetResult.success();
}
//最新加入
public Sheet<UserInfo> lastReg() {
Sheet<UserRecord> users = source.querySheet(UserRecord.class
, SelectColumn.includes("userid", "nickname", "avatar", "createtime")
, new Flipper().sort("createtime DESC").limit(8)
, FilterNode.create("status", 10));
Sheet<UserInfo> infos = new Sheet<>();
ArrayList<UserInfo> list = new ArrayList<>();
users.forEach(x -> {
UserInfo info = x.createUserInfo();
info.setTime(LxyKit.dateFmt(x.getCreatetime()));
list.add(info);
});
infos.setRows(list);
infos.setTotal(users.getTotal());
return infos;
}
@RestMapping(name = "usercount", auth = false, comment = "用户数据统计")
public Number userCount() {
return source.getNumberResult(UserRecord.class, FilterFunc.COUNT, "userid", FilterNode.create("status", FilterExpress.NOTEQUAL, -10));
}
@RestMapping(ignore = true, comment = "判断用户是否是管理员")
public boolean isAdmin(int userid) {
if (userid <= 0) return false;
List<Integer> userIds = source.queryColumnList("userid", UserRecord.class, FilterNode.create("roleid", 1));
for (Integer x : userIds) {
if (userid == x) {
return true;
}
}
return false;
}
}

View File

@@ -1,4 +1,4 @@
package net.tccn.bbs.base.kit;
package net.tccn.bbs.base.util;
import org.redkale.net.http.RestService;

View File

@@ -0,0 +1,352 @@
package net.tccn.bbs.base.util;
import net.tccn.bbs.base.Utils;
import org.redkale.convert.json.JsonConvert;
import javax.persistence.Id;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 2018/3/12 14:17.
*/
public class Kv<K, V> extends LinkedHashMap<K, V> {
protected static final JsonConvert convert = JsonConvert.root();
public static Kv of() {
return new Kv();
}
public static Kv of(Object k, Object v) {
return new Kv().set(k, v);
}
public static Kv filter(Map<String, String> map, String... fields) {
Kv kv = Kv.of();
if (fields == null || fields.length == 0 || map == null) {
return kv;
}
for (String field : fields) {
if (field.contains("->")) {
String[] arr = field.split("->");
kv.put(arr[1], map.get(arr[0]));
continue;
}
kv.put(field, map.get(field));
}
return kv;
}
public Kv<K, V> set(K k, V v) {
put(k, v);
return this;
}
public Kv<K, V> putAll(Kv<K, V> kv) {
kv.forEach((k, v) -> put(k, v));
return this;
}
// 将obj 属性映射到Kv 中
public static Kv toKv(Object m, String... fields) {
Kv kv = Kv.of();
if (m == null) {
return kv;
}
Stream.of(fields).forEach(field -> {
String filedT = field;
String filedS = field;
try {
if (field.contains("=")) {
String[] arr = field.split("=");
filedT = arr[0];
filedS = arr[1];
}
Method method = m.getClass().getMethod("get" + toUpperCaseFirst(filedS));
if (method != null) {
kv.set(filedT, method.invoke(m));
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
new IllegalArgumentException(String.format("Kv.toKv获取 获取参数[]失败", field), e);
}
});
return kv;
}
public static <T> List<Kv> toKv(Collection<T> datas, String... fields) {
return datas.stream().map(x -> toKv(x, fields)).collect(Collectors.toList());
}
public static Kv toKv(Object m) {
return toKv(m, Kv.of(), m.getClass());
}
private static Kv toKv(Object m, Kv kv, Class clazz) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (!method.getName().startsWith("get") || method.getParameterCount() > 0 || "getClass".equals(method.getName()))
continue;
String k = toLowerCaseFirst(method.getName().replaceFirst("get", ""));
if (!kv.containsKey(k) || Utils.isEmpty(kv.get(k))) {
try {
kv.set(k, method.invoke(m));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
for (Field field : clazz.getDeclaredFields()) {
if (field.getAnnotation(Id.class) != null) {
try {
field.setAccessible(true);
kv.set("_id", field.get(m));
break;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
Class superclass = clazz.getSuperclass();
if (superclass != null) {
kv = toKv(m, kv, superclass);
}
return kv;
}
/**
* 将字符串第一个字母转大写
*
* @param str 待转换字符串
* @return
*/
private static String toUpperCaseFirst(String str) {
Objects.requireNonNull(str);
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
/**
* 将字符串第一个字母转小写
*
* @param str 待转换字符串
* @return
*/
private static String toLowerCaseFirst(String str) {
Objects.requireNonNull(str);
return str.substring(0, 1).toLowerCase() + str.substring(1);
}
public <T> T toBean(Class<T> type) {
return toBean(this, type);
}
// 首字母大写
private static Function<String, String> upFirst = (s) -> {
return s.substring(0, 1).toUpperCase() + s.substring(1);
};
private static Predicate<Class> isNumber = (t) -> {
return t == Integer.class || t == int.class
|| t == Long.class || t == long.class
|| t == Float.class || t == float.class
|| t == Double.class || t == double.class
|| t == Short.class || t == short.class
|| t == Byte.class || t == byte.class
;
};
public static <T> T toAs(Object v, Class<T> clazz) {
if (v == null) {
return null;
} else if (v.getClass() == clazz) {
return (T) v;
} else if (clazz == String.class) {
return (T) String.valueOf(v);
}
Object v1 = v;
try {
if (v.getClass() == Long.class) {//多种数值类型的处理: Long => x
switch (clazz.getSimpleName()) {
case "int", "Integer" -> v1 = (int) (long) v;
case "short", "Short" -> v1 = (short) (long) v;
case "float", "Float" -> v1 = (float) (long) v;
case "byte", "Byte" -> v1 = (byte) (long) v;
}
} else if (v.getClass() == Double.class) {
if (isNumber.test(clazz)) {
switch (clazz.getSimpleName()) {
case "long", "Long" -> v1 = (long) (double) v;
case "int", "Integer" -> v1 = (int) (double) v;
case "short", "Short" -> v1 = (short) (double) v;
case "float", "Float" -> v1 = (float) (double) v;
case "byte", "Byte" -> v1 = (byte) (double) v;
}
} else if (clazz == String.class) {
v1 = String.valueOf(v);
}
} else if (v.getClass() == String.class) {
switch (clazz.getSimpleName()) {
case "Date" -> v1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse((String) v);
case "short", "Short" -> v1 = (short) Double.parseDouble((String) v);
case "float", "Float" -> v1 = (float) Double.parseDouble((String) v);
case "int", "Integer" -> v1 = (int) Double.parseDouble((String) v);
case "long", "Long" -> v1 = (long) Double.parseDouble((String) v);
case "double", "Double" -> v1 = Double.parseDouble((String) v);
case "byte", "Byte" -> v1 = Byte.parseByte((String) v);
}
} else if (v.getClass() == Integer.class) {
switch (clazz.getSimpleName()) {
case "long", "Long" -> v1 = (long) (int) v;
case "short", "Short" -> v1 = (short) (int) v;
case "float", "Float" -> v1 = (float) (int) v;
case "byte", "Byte" -> v1 = (byte) (int) v;
}
} else if (v.getClass() == Float.class) {
switch (clazz.getSimpleName()) {
case "long", "Long" -> v1 = (long) (float) v;
case "int", "Integer" -> v1 = (int) (float) v;
case "short", "Short" -> v1 = (short) (float) v;
case "byte", "Byte" -> v1 = (byte) (float) v;
}
} else {
v1 = v;
}
} catch (ParseException e) {
e.printStackTrace();
}
return (T) v1;
}
public static <T> T toBean(Map map, Class<T> clazz) {
//按照方法名 + 类型寻找,
//按照方法名 寻找
//+
Object obj = null;
try {
obj = clazz.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
NoSuchMethodException e) {
new IllegalArgumentException("创建对象实列失败", e); // 检查clazz是否有无参构造
}
for (String k : (Set<String>) map.keySet()) {
Object v = map.get(k);
if (v == null) continue;
//寻找method
try {
String methodName = "set" + upFirst.apply(k);
Class tClazz = null;
Method method = null;
try {
method = clazz.getMethod(methodName, tClazz = v.getClass());
} catch (NoSuchMethodException e) {
//e.printStackTrace();
}
if (method == null) {
for (Method _method : clazz.getMethods()) {
if (methodName.equals(_method.getName()) && _method.getParameterCount() == 1) {
method = _method;
tClazz = _method.getParameterTypes()[0];
}
}
}
if (method == null) {
for (Method _method : clazz.getMethods()) {
if (methodName.equalsIgnoreCase(_method.getName()) && _method.getParameterCount() == 1) {
method = _method;
tClazz = _method.getParameterTypes()[0];
}
}
}
if (method != null) {
method.invoke(obj, toAs(v, tClazz));
}
//没有方法,找属性注解
/*if (method == null) {
Field field = null;
Field[] fields = clazz.getDeclaredFields();
for (Field _field : fields) {
To to = _field.getAnnotation(To.class);
if (to != null && k.equals(to.value())) {
field = _field;
tClazz = _field.getType();
break;
}
}
if (field != null) {
field.setAccessible(true);
field.set(obj, toAs(v, tClazz));
}
}*/
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return (T) obj;
}
public String toString() {
return convert.convertTo(this);
}
public int getInt(String key) {
return toAs(get(key), int.class);
}
public int getInt(String key, int defaultValue) {
V v = get(key);
if (v == null) {
return defaultValue;
}
return toAs(v, int.class);
}
public long getLong(String key) {
return toAs(get(key), Long.class);
}
public long getLong(String key, long defaultValue) {
V v = get(key);
if (v == null) {
return defaultValue;
}
return toAs(v, long.class);
}
public String getStr(String key) {
return toAs(get(key), String.class);
}
public String getStr(String key, String defaultValue) {
V v = get(key);
if (v == null) {
return defaultValue;
}
return toAs(v, String.class);
}
}

View File

@@ -1,4 +1,4 @@
package net.tccn.bbs.base.kit;
package net.tccn.bbs.base.util;
import org.redkale.service.RetLabel;
import org.redkale.service.RetResult;

View File

@@ -1,26 +1,19 @@
package net.tccn.bbs.base;
package net.tccn.bbs.base.util;
import net.tccn.bbs.base.entity.Count;
import net.tccn.bbs.base.entity.VisLog;
import net.tccn.bbs.base.user.UserInfo;
import net.tccn.bbs.base.user.UserService;
import net.tccn.bbs.content.Content;
import net.tccn.bbs.base.BaseService;
import net.tccn.bbs.content.ContentInfo;
import net.tccn.bbs.content.ContentService;
import net.tccn.bbs.user.UserService;
import net.tccn.bbs.vislog.entity.VisLog;
import org.redkale.net.http.RestMapping;
import org.redkale.net.http.RestService;
import org.redkale.source.ColumnValue;
import org.redkale.source.FilterExpress;
import org.redkale.source.FilterNode;
import org.redkale.source.Flipper;
import org.redkale.util.Comment;
import org.redkale.util.AnyValue;
import org.redkale.util.Sheet;
import org.redkale.util.Utility;
import javax.annotation.Resource;
import java.util.*;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Function;
/**
* Created by liangxianyou at 2018/6/20 22:54.
@@ -35,6 +28,25 @@ public class TaskQueue<T extends Object> extends BaseService implements Runnable
protected static LinkedBlockingQueue queue = new LinkedBlockingQueue();
@Override
public void init(AnyValue config) {
// 独立线程用户访问行为记录到数据库
new Thread(() -> {
while (true) {
try {
T task = take();
//记录访问日志如果是访问的文章详情对文章访问数量更新
if (task instanceof VisLog) {
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public TaskQueue() {
new Thread(this).start();
}
@@ -50,32 +62,12 @@ public class TaskQueue<T extends Object> extends BaseService implements Runnable
}
@Override
@RestMapping(ignore = true, comment = "独立线程,用户访问行为记录到数据库")
@RestMapping(ignore = true, comment = "")
public void run() {
do {
try {
T task = take();
//记录访问日志如果是访问的文章详情对文章访问数量更新
if (task instanceof VisLog) {
//System.out.println(task);
ArangoService.save(task).thenAcceptAsync((_task) -> {
VisLog visLog = (VisLog) _task;
//[访问量]
String uri = visLog.getUri();
if (uri != null && uri.startsWith("/jie/detail/")) {
updateViewNum(visLog);
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (true);
}
@Comment("帖子阅读数处理")
/*@Comment("帖子阅读数处理")
private void updateViewNum(VisLog visLog) {
String aql = String.format("for d in vis_log_dev\n" +
@@ -90,11 +82,11 @@ public class TaskQueue<T extends Object> extends BaseService implements Runnable
int contentid = Integer.parseInt(uri.replace("/jie/detail/", ""));
source.updateColumn(Content.class, contentid, ColumnValue.inc("viewnum", 1));
}
}
}*/
@RestMapping(ignore = true, comment = "访问热帖数据")
public Sheet<ContentInfo> hotView(String sessionid) {
int limit = 8;
/*int limit = 8;
String cacheKey = "hotView";
Object ids = cacheSource.get(cacheKey);
if (isEmpty.test(ids)) {
@@ -141,7 +133,9 @@ public class TaskQueue<T extends Object> extends BaseService implements Runnable
} else if (!userService.isAdmin(userInfo.getUserid())) { //非管理员
node.and(FilterNode.create("status", FilterExpress.NOTEQUAL, 30).or(FilterNode.create("status", 30).and("userid", userInfo.getUserid())));
}
return contentService.contentQuery(flipper, node);
return contentService.contentQuery(flipper, node);*/
return Sheet.empty();
}
/**
@@ -166,10 +160,10 @@ public class TaskQueue<T extends Object> extends BaseService implements Runnable
});
int[] userids = LxyKit.listToArray(uids, new int[uids.size()]);
List<UserRecord> records = source.queryList(UserRecord.class, FilterNode.create("userid", FilterExpress.IN, userids));
List<UserDetail> records = source.queryList(UserDetail.class, FilterNode.create("userid", FilterExpress.IN, userids));
rows.forEach(x->{
UserRecord record = records.stream().filter(y -> (Integer) x.get("userid") == y.getUserid()).findFirst().orElse(new UserRecord());
UserDetail record = records.stream().filter(y -> (Integer) x.get("userid") == y.getUserid()).findFirst().orElse(new UserDetail());
x.put("nickname", record.getRealname());
x.put("avatar", record.getAvatar());
});