提交git

This commit is contained in:
2025-08-25 18:51:02 +08:00
commit 9dd33ed2b9
2171 changed files with 172166 additions and 0 deletions

View File

@ -0,0 +1,64 @@
package cc.uling.system.novel;
import cc.uling.common.interceptor.AccessInterceptor;
import cc.uling.common.interceptor.ExceptionInterceptor;
import cc.uling.common.utils.HttpUtils;
import cn.hutool.core.date.DateUtil;
import com.jfinal.config.Constants;
import com.jfinal.config.Interceptors;
import com.jfinal.handler.Handler;
import com.web.plugin.token.TokenManager;
import io.jboot.Jboot;
import io.jboot.aop.jfinal.JfinalHandlers;
import io.jboot.core.listener.JbootAppListener;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
@Slf4j
public class NovelAppListener implements JbootAppListener {
@Override
public void onInit() {
TokenManager.me().init();
}
@Override
public void onConstantConfig(Constants constants) {
constants.setDevMode(true);
constants.setInjectDependency(true);
constants.setInjectSuperClass(true);
constants.setMaxPostSize(100 * 1024 * 1024);// 最大支持 100M 文件上传
}
@Override
public void onInterceptorConfig(Interceptors interceptors) {
interceptors.addGlobalActionInterceptor(new AccessInterceptor());
interceptors.addGlobalActionInterceptor(new ExceptionInterceptor());
}
@Override
public void onHandlerConfig(JfinalHandlers handlers) {
JbootAppListener.super.onHandlerConfig(handlers);
handlers.add(new Handler() {
@Override
public void handle(String target, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, boolean[] booleans) {
log.info("fetch|" + HttpUtils.getIpAddress(httpServletRequest) + "|request|" + target);
next.handle(target, httpServletRequest, httpServletResponse, booleans);
}
});
}
@Override
public void onStart() {
log.info("onStart ..." + Jboot.configValue("jboot.app.mode") + "|" + DateUtil.formatDateTime(new Date()));
}
}

View File

@ -0,0 +1,10 @@
package cc.uling.system.novel;
import io.jboot.app.JbootApplication;
public class NovelApplication {
public static void main(String[] args) {
JbootApplication.run(args);
}
}

View File

@ -0,0 +1,14 @@
package cc.uling.system.novel.constants;
public interface ConfigKeys {
String pay_serve = "pay_server";
String pay_mch_no = "pay_mch_no";
String pay_mch_key = "pay_mch_key";
String pay_mch_app = "pay_mch_app";
String website = "website";
}

View File

@ -0,0 +1,258 @@
package cc.uling.system.novel.controller;
import cc.uling.common.base.BaseController;
import cc.uling.common.constant.PayOrderStatus;
import cc.uling.common.domain.AjaxResult;
import cc.uling.common.enums.SysNormalStatus;
import cc.uling.common.exception.BizException;
import cc.uling.common.utils.Encipher;
import cc.uling.common.utils.HttpUtils;
import cc.uling.system.novel.doamin.dto.LoginDTO;
import cc.uling.system.novel.doamin.vo.NovelOrderVO;
import cc.uling.system.novel.doamin.vo.NovelVO;
import cc.uling.system.novel.doamin.vo.ProductVO;
import cc.uling.system.novel.service.BizOrderService;
import cc.uling.system.novel.service.NovelReader;
import cc.uling.system.novel.utils.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jfinal.aop.Aop;
import com.jfinal.core.paragetter.Para;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.web.gen.model.Novel;
import com.web.gen.model.NovelOrder;
import com.web.gen.model.NovelUser;
import com.web.gen.service.NovelCategoryService;
import com.web.gen.service.NovelOrderService;
import com.web.gen.service.NovelService;
import com.web.gen.service.NovelUserService;
import com.web.plugin.token.LoginModel;
import com.web.plugin.token.TokenHelper;
import com.web.plugin.token.TokenInfo;
import io.jboot.db.model.Columns;
import io.jboot.web.controller.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@RequestMapping(value = "/novel/api")
public class NovelApiController extends BaseController {
public AjaxResult category() {
return AjaxResult.success(Aop.get(NovelCategoryService.class).findListByColumns(Columns.create(), "sort_num"));
}
public AjaxResult login(@Valid @Para("") LoginDTO dto) {
NovelUser user = Aop.get(NovelUserService.class).findFirstByColumns(Columns.create("email", dto.getEmail()));
if (user == null) {
return AjaxResult.error("Account not registered");
}
if (!user.getPassword().equals(dto.getPassword())) {
return AjaxResult.error("Password error");
}
String ip = HttpUtils.getIpAddress(getRequest());
TokenHelper.login(user.getId(), new LoginModel().setDevice(ip));
return AjaxResult.success(null, TokenHelper.getTokenValueNotCut());
}
public AjaxResult register(@Valid @Para("") LoginDTO dto) {
NovelUser user = Aop.get(NovelUserService.class).findFirstByColumns(Columns.create("email", dto.getEmail()));
if (user != null) {
throw new BizException("User already registered");
}
user = new NovelUser();
user.setEmail(dto.getEmail());
user.setPassword(dto.getPassword());
user.setStatus(SysNormalStatus.Normal);
user.setCreateTime(new Date());
Object idObj = Aop.get(NovelUserService.class).save(user);
if (idObj == null) {
throw BizException.SYSTEM_ERROR;
}
return AjaxResult.success();
}
public AjaxResult recommend() {
int type = getInt("type", 0);
int page = getInt("pageNum", 1);
int size = getInt("pageSize", 10);
Columns columns = Columns.create("recommend", type);
Page<Novel> novels = Aop.get(NovelService.class).paginateByColumns(page, size, columns, "sort_num");
Page<NovelVO> pages = Convert.wrap(novels, o -> new NovelVO().warp(o));
return AjaxResult.success(pages);
}
public AjaxResult search() {
String keyword = get("keyword");
Integer categoryId = getInt("categoryId");
int page = getInt("pageNum", 1);
int size = getInt("pageSize", 10);
Columns columns = Columns.create().eq("category_id", categoryId).likeAppendPercent("name", keyword);
Page<Novel> novels = Aop.get(NovelService.class).paginateByColumns(page, size, columns, "sort_num");
Page<NovelVO> pages = Convert.wrap(novels, o -> new NovelVO().warp(o));
return AjaxResult.success(pages);
}
public AjaxResult detail() {
Long id = getLong("id");
int page = getInt("page", 1);
int size = getInt("size", 200);
int chapter = getInt("chapter", 1);
Novel novel = Aop.get(NovelService.class).findById(id);
if (novel == null) {
throw BizException.NOT_FOUND;
}
boolean hadPermission = false;
int free = null == novel.getFree() ? 0 : novel.getFree();
if (free < chapter) {
TokenInfo tokenInfo = TokenHelper.getTokenInfo();
if (tokenInfo.loginId != null) {
Columns columns = Columns.create("user_id", tokenInfo.loginId).eq("novel_id", id).eq("status", PayOrderStatus.STATUS_2);
NovelOrder order = Aop.get(NovelOrderService.class).findFirstByColumns(columns);
if (order != null) {
hadPermission = true;
}
}
} else {
hadPermission = true;
}
NovelVO vo;
if (hadPermission) {
vo = Aop.get(NovelReader.class).read(page, size, novel);
} else {
vo = new NovelVO().warp(novel);
}
vo.setPermission(hadPermission);
// if (!hadPermission) {
// log.info("hadPermission|" + hadPermission + "|" + chapter + "|" + JSON.toJSONString(vo.getChapters()));
// for (int i = 0; i < vo.getContent().size(); i++) {
// if (i + 1 == chapter) {
// vo.setData(vo.getContent().get(i));
// break;
// }
// }
// throw BizException.FORBIDDEN;
// }
// vo.setContent(null);
return AjaxResult.success(vo);
}
public void createOrder() {
Long id = getLong("id");
Novel novel = Aop.get(NovelService.class).findById(id);
if (novel == null) {
throw BizException.NOT_FOUND;
}
Long userId = getLong("userId");
TokenInfo tokenInfo = TokenHelper.getTokenInfo();
if (tokenInfo.loginId == null) {
if (null == userId) {
throw new BizException("Please login");
}
tokenInfo.loginId = userId;
}
String ip = HttpUtils.getIpAddress(getRequest());
String response = Aop.get(BizOrderService.class).createOrder(novel, tokenInfo.loginId, ip);
if (response == null) {
throw BizException.SYSTEM_ERROR;
}
renderText(response);
}
public AjaxResult getOrders() {
TokenInfo tokenInfo = TokenHelper.getTokenInfo();
if (tokenInfo.loginId == null) {
return AjaxResult.error("Please login");
}
int page = getInt("pageNum", 1);
int size = getInt("pageSize", 10);
Columns columns = Columns.create("user_id", tokenInfo.loginId);
Page<NovelOrder> tmp = Aop.get(NovelOrderService.class).paginateByColumns(page, size, columns, "create_time desc");
Page<NovelOrderVO> pages = Convert.wrap(tmp, o -> new NovelOrderVO().wrap(o));
return AjaxResult.success(pages);
}
public void callback() {
String orderNo = getPara(0);
log.info("callback|" + orderNo);
if (StringUtils.isNotBlank(orderNo)) {
NovelOrder order = Aop.get(NovelOrderService.class).findFirstByColumns(Columns.create("order_no", orderNo));
if (order != null) {
if (Objects.equals(order.getStatus(), PayOrderStatus.STATUS_0) || Objects.equals(order.getStatus(), PayOrderStatus.STATUS_1)) {
order.setStatus(PayOrderStatus.STATUS_2);
Aop.get(NovelOrderService.class).update(order);
}
}
}
renderText("ok");
}
public AjaxResult listAll() {
List<Novel> list = Aop.get(Novel.class).find("select novel_novel.*,novel_novel_category.`name` as sku from novel_novel inner join novel_novel_category on novel_novel.category_id = novel_novel_category.id");
return AjaxResult.success(list.stream().map(ProductVO::new).collect(Collectors.toList()));
}
/**
* 同步订单
*
* @return
*/
public AjaxResult syncOrder(String data) {
String id = getHeader("MID");
String key = Encipher.decrypt(id);
String json = Encipher.decrypt(data, key);
log.info(" data {} ", json);
if (!JSONUtil.isTypeJSON(json)) {
return AjaxResult.error("The order format is incorrect!");
}
JSONObject object = JSONUtil.parseObj(json);
if (!object.containsKey("list")) {
return AjaxResult.error("Order list is Empty!");
}
JSONArray array = object.getJSONArray("list");
List<NovelOrder> list = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
JSONObject order = array.getJSONObject(i);
Date date = DateUtil.parseDateTime(order.getStr("createTime"));
NovelUser user = Aop.get(NovelUserService.class).getUser(order, date);
NovelOrder novelOrder = Aop.get(NovelOrder.class).findFirstByColumns(Columns.create("order_no", order.getStr("orderNo")));
JSONArray products = order.getJSONArray("products");
if (novelOrder == null && products != null && !products.isEmpty()) {
JSONObject product = products.getJSONObject(0);
novelOrder = new NovelOrder();
novelOrder.setUserId(user.getId());
novelOrder.setOrderNo(order.getStr("orderNo"));
novelOrder.setCreateTime(date);
novelOrder.setStatus(order.getInt("status"));
novelOrder.setNovelId(product.getLong("productNo"));
list.add(novelOrder);
}
}
Db.batchSave(list, list.size());
return AjaxResult.success();
}
}

View File

@ -0,0 +1,22 @@
package cc.uling.system.novel.doamin.dto;
import cc.uling.common.constant.SysConsts;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
@Setter
@Getter
public class LoginDTO {
@Email(message = SysConsts.SPLITTER + "Email format error")
@NotBlank(message = SysConsts.SPLITTER + "Email cannot be empty")
private String email;
@Size(min = 5, message = "Password length cannot be less than 5 characters")
@NotBlank(message = SysConsts.SPLITTER + "Login password cannot be empty")
private String password;
}

View File

@ -0,0 +1,46 @@
package cc.uling.system.novel.doamin.vo;
import cn.hutool.core.date.DateUtil;
import com.jfinal.aop.Aop;
import com.web.gen.model.Novel;
import com.web.gen.model.NovelOrder;
import com.web.gen.service.NovelService;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class NovelOrderVO {
private Long id;
private Long userId;
private String orderNo;
private Long novelId;
private String novelName;
private int status;
private String createTime;
public NovelOrderVO wrap(NovelOrder order) {
setId(order.getId());
setUserId(order.getUserId());
setOrderNo(order.getOrderNo());
setNovelId(order.getNovelId());
setStatus(order.getStatus());
if (null != order.getCreateTime()) {
setCreateTime(DateUtil.formatDateTime(order.getCreateTime()));
}
if (null != novelId) {
Novel novel = Aop.get(NovelService.class).findById(novelId);
if (null != novel) {
setNovelName(novel.getName());
}
}
return this;
}
}

View File

@ -0,0 +1,68 @@
package cc.uling.system.novel.doamin.vo;
import com.jfinal.aop.Aop;
import com.web.gen.model.Novel;
import com.web.gen.model.NovelCategory;
import com.web.gen.service.NovelCategoryService;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@Setter
@Getter
public class NovelVO {
private Long id;
private String name;
private String img;
private String author;
private BigDecimal score;
private boolean permission;
private String remark;
private BigDecimal price;
private Long categoryId;
private String categoryName;
private List<String> chapters;
private List<Map<String, String>> content;
private Map<String, String> data;
private String text;
private boolean hasNext;
public NovelVO warp(Novel novel) {
setId(novel.getId());
setName(novel.getName());
setAuthor(novel.getAuthor());
setScore(novel.getScore());
setRemark(novel.getRemark());
setPrice(novel.getMoney());
setCategoryId(novel.getCategoryId());
if (null != categoryId) {
NovelCategory category = Aop.get(NovelCategoryService.class).findById(categoryId);
if (null != category) {
setCategoryName(category.getName());
}
}
this.img = novel.getImg();
this.hasNext = false;
return this;
}
}

View File

@ -0,0 +1,32 @@
package cc.uling.system.novel.doamin.vo;
import com.web.gen.model.Novel;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ProductVO {
private Long productId;
private String sku;
private String price;
private String name;
private String url;
private Integer active;
public ProductVO(Novel novel) {
this.productId = novel.getId();
this.name = novel.getName();
this.sku = novel.getStr("sku");
this.price = novel.getMoney().toString();
this.url = "/detail/" + novel.getId();
this.active = 1;
}
}

View File

@ -0,0 +1,240 @@
package cc.uling.system.novel.service;
import cc.uling.common.constant.PayOrderStatus;
import cc.uling.system.novel.constants.ConfigKeys;
import com.alibaba.fastjson.JSON;
import com.jfinal.aop.Aop;
import com.web.gen.model.Novel;
import com.web.gen.model.NovelOrder;
import com.web.gen.service.NovelConfigService;
import com.web.gen.service.NovelOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
@Slf4j
public class BizOrderService {
public String createOrder(Novel novel, Object userId, String clientIp) {
String response = null;
NovelOrder order = new NovelOrder();
order.setNovelId(novel.getId());
order.setUserId(Long.parseLong(userId.toString()));
order.setOrderNo(UUID.randomUUID().toString());
order.setStatus(PayOrderStatus.STATUS_0);
order.setCreateTime(new Date());
Object idObj = Aop.get(NovelOrderService.class).save(order);
if (idObj != null) {
String appId = Aop.get(NovelConfigService.class).findByKey(ConfigKeys.pay_mch_app);
String mchNo = Aop.get(NovelConfigService.class).findByKey(ConfigKeys.pay_mch_no);
String mchKey = Aop.get(NovelConfigService.class).findByKey(ConfigKeys.pay_mch_key);
String notifyUrl = Aop.get(NovelConfigService.class).findByKey(ConfigKeys.website);
String payUrl = Aop.get(NovelConfigService.class).findByKey(ConfigKeys.pay_serve);
response = create(order, novel, appId, mchNo, mchKey, clientIp, notifyUrl, payUrl);
if (StringUtils.isNotBlank(response)) {
order.setStatus(PayOrderStatus.STATUS_1);
Aop.get(NovelOrderService.class).update(order);
}
}
return response;
}
public String create(NovelOrder order, Novel novel, String appId, String mchNo, String mchKey, String clientIP, String notifyUrl, String payUrl) {
String postResponse = null;
try {
// Example 2: POST request
Map<String, Object> postParams = new HashMap<>();
postParams.put("amount", novel.getMoney().multiply(new BigDecimal(100))); //Transaction amount
postParams.put("currency", "USD"); //Transaction currency
postParams.put("appId", appId); //Merchant Application ID
postParams.put("merNo", mchNo); //Merchant ID
postParams.put("merOrderNo", System.currentTimeMillis()); //Merchant Order Number
postParams.put("clientIp", clientIP); //Payer's transaction IP
postParams.put("notifyUrl", notifyUrl + "/novel/api/" + order.getOrderNo()); //Asynchronous callback URL for transactions
postParams.put("payMode", 1); //Payment mode, 0-checkout
List<Map<String, Object>> products = new ArrayList<>();
Map<String, Object> product = new HashMap<>();
product.put("productName", novel.getName()); //Product name
product.put("productUrl", "https://x.xxx.com"); //Product sales link URL
product.put("price", novel.getMoney());
product.put("sku", novel.getName());
product.put("quantity", "1");
products.add(product);
postParams.put("products", products);
String jsonBody = JSON.toJSONString(postParams);
postResponse = sendPostRequest(payUrl, "/api/expanded/transactions/create", mchNo, mchKey, null, jsonBody);
System.out.println("POST Response: " + postResponse);
} catch (Exception e) {
e.printStackTrace();
}
return postResponse;
}
public static String sendPostRequest(String baseUrl, String endpoint, String mchNo, String mchKey, Map<String, String> params, String jsonBody) throws Exception {
if (null == params) {
params = new HashMap<>();
}
// Add common parameters
params.putAll(getCommonParams());
// Generate signature
String sign = generateSign(params, jsonBody, mchKey);
params.put("sign", sign);
// Build query string
String queryString = buildQueryString(params);
String url = baseUrl + endpoint + "?" + queryString;
log.info("requestUrl: " + url);
// Create connection
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("POST");
addCommonHeaders(conn, mchNo);
// Set JSON content
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json");
try (OutputStream os = conn.getOutputStream()) {
byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
// Get response
return getResponse(conn);
}
/**
* Get common parameters (timestamp and nonce)
*/
private static Map<String, String> getCommonParams() {
Map<String, String> params = new HashMap<>();
params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000)); // Timestamp in seconds
params.put("nonce", UUID.randomUUID().toString().replace("-", "")); // Random string
return params;
}
/**
* Add common request headers
*/
private static void addCommonHeaders(HttpURLConnection conn, String mchNo) {
conn.setRequestProperty("X-Signature-Method", "MD5");
conn.setRequestProperty("X-Merchant-No", mchNo);
conn.setRequestProperty("Accept", "application/json");
}
/**
* Generate signature
*/
public static String generateSign(Map<String, String> data,
String jsonBody, String secret) throws Exception {
Map<String, String> params = new HashMap<>(data);
StringBuilder sb = new StringBuilder();
// 1. Include request body. If the request has JSON body, include the entire JSON string as a parameter value
if (StringUtils.isNotBlank(jsonBody)) {
params.put("body", jsonBody);
}
// 2. Sort all parameters alphabetically by parameter name (ASCII order)
List<String> keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
for (String key : keys) {
if (!"sign".equals(key)) { // Exclude existing sign parameters
sb.append(key).append("=").append(params.get(key)).append("&");
}
}
// 3. Splicing Merchant Key
sb.append("key=").append(secret);
// System.out.println("Sort parameters:" + sb.toString());
// 4. Calculate MD5
MessageDigest md = MessageDigest.getInstance("MD5");
System.out.println("unSign:" + sb.toString());
byte[] digest = md.digest(sb.toString().getBytes(StandardCharsets.UTF_8));
// 5. Convert MD5 result to lowercase
StringBuilder hexString = new StringBuilder();
for (byte b : digest) {
String hex = Integer.toHexString(0xff & b); // 将字节转换为两位十六进制数
if (hex.length() == 1) { // 如果转换后的十六进制数只有一位前面补0
hexString.append('0');
}
hexString.append(hex);
}
// 返回小写的十六进制字符串
return hexString.toString().toLowerCase();
}
/**
* Build query string
*/
private static String buildQueryString(Map<String, String> params) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(entry.getKey()).append("=").append(entry.getValue());
}
return sb.toString();
}
/**
* Get response content
*/
private static String getResponse(HttpURLConnection conn) throws Exception {
StringBuilder response = new StringBuilder();
int status = conn.getResponseCode();
if (null != conn.getInputStream()) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
return response.toString();
}
} else if (null != conn.getErrorStream()) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8))) {
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
throw new RuntimeException("HTTP error code: " + status + ", response: " + response);
}
}
log.info("url:" + conn.getURL() + "|status:" + status + "|response:" + response.toString());
return response.toString();
}
}

View File

@ -0,0 +1,135 @@
package cc.uling.system.novel.service;
import cc.uling.common.exception.BizException;
import cc.uling.system.novel.doamin.vo.NovelVO;
import com.alibaba.fastjson.JSON;
import com.jfinal.kit.PathKit;
import com.web.gen.model.Novel;
import io.jboot.aop.annotation.Bean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Bean
@Slf4j
public class NovelReader {
// private static final String regex = "(第[\\d一二三四五六七八九十零百千万]+[章节卷集部篇回]|(?i)(chapter|volume|section)[\\s\\-]?[\\dIVXLCDM]+[.:\\-]).*";
private static final String regex = "(第[\\d一二三四五六七八九十零百千万]\\s[^<]+(?=<br\\s*/?>))";
// private static final String regex = "(Chapter|Volume|Section|Part)\\s[\\dIVXLCDM]+[^<]+(?=<br\\s*/?>)";
public NovelVO read(int page, int size, Novel novel) {
NovelVO vo = new NovelVO().warp(novel);
if (StringUtils.isEmpty(novel.getPath())) {
novel.setPath(PathKit.getWebRootPath());
}
String filePath = novel.getPath() + File.separator + novel.getCode() + ".txt";
if (!new File(filePath).exists()) {
log.warn(filePath + "|文件不存在");
throw BizException.NOT_FOUND;
}
readFile(vo, page, size, filePath);
// log.info("read|" + novelText.substring(0, 100));
// if (StringUtils.isNotBlank(novelText)) {
// List<String> chapters = getChapters(novelText);
// List<Map<String, String>> data = getChapterContent(novelText, chapters);
// vo.setChapters(chapters);
// vo.setContent(data);
// } else {
// log.warn(filePath + "|读取文本失败");
// }
// if (vo.getData() == null) {
// vo.setText(novelText);
// }
return vo;
}
public String readLargeFile(String filePath) {
String content = null;
try (RandomAccessFile file = new RandomAccessFile(filePath, "r"); FileChannel channel = file.getChannel()) {
long fileSize = channel.size();
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
byte[] bytes = new byte[(int) fileSize];
buffer.get(bytes);
content = new String(bytes, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
return content;
}
public String readFile(NovelVO vo, int page, int size, String filePath) {
int start = (page - 1) * size;
int end = start + size;
StringBuilder content = new StringBuilder();
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
int lineCount = 0;
int total = 0;
String line;
while ((line = br.readLine()) != null) {
lineCount++;
if (lineCount >= start && lineCount < end) {
total++;
content.append(line).append("<br />"); // 换行转HTML换行
} else if (lineCount >= end) {
break;
}
}
log.info(" total {} {}", total, size);
vo.setHasNext(total >= size);
} catch (Exception e) {
e.printStackTrace();
}
vo.setText(content.toString());
return content.toString();
}
public List<Map<String, String>> getChapterContent(String novelText, List<String> chapters) {
List<Map<String, String>> contents = new ArrayList<>();
String[] parts = novelText.split(regex, -1); // 按章节标题分割文本
for (int i = 1; i < parts.length; i++) {
String chapterTitle = chapters.get(i - 1);
String chapterContent = parts[i].trim();
Map<String, String> contentMap = new HashMap<>();
contentMap.put(chapterTitle, chapterContent);
contents.add(contentMap);
}
return contents;
}
public List<String> getChapters(String novelText) {
// String novelText = "第一章 引言\n这是第一章内容...\nChapter 1: Start\n这是英文第一章内容...";
// String regex = "^(第[一二三四五六七八九十零百千万\\d]+[章节卷集部篇]|(Chapter|CHAPTER|Volume|SECTION)\\s[\\dIVXLCDM]+[.:\\-]).*";
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(novelText);
List<String> chapters = new ArrayList<>();
while (matcher.find()) {
chapters.add(matcher.group()); // 提取章节标题
}
return chapters;
}
public static void main(String[] args) {
// String path = "/Users/chenzigui/Workspaces/czg/txt/aaa.txt";
Novel novel = new Novel();
novel.setPath("/Users/zcjian/Desktop/file/txt/");
novel.setCode("TXT1915396480701698048");
NovelVO vo = new NovelReader().read(2, 200, novel);
log.info(" vo {}", vo);
}
}

View File

@ -0,0 +1,28 @@
package cc.uling.system.novel.utils;
import cc.uling.common.listener.IConvert;
import com.jfinal.plugin.activerecord.Page;
import java.util.ArrayList;
import java.util.List;
public class Convert {
public static <T, O> Page<O> wrap(Page<T> tmp, IConvert<O, T> fun) {
List<O> list = new ArrayList<>();
Page<O> pages = new Page<>();
pages.setPageNumber(tmp.getPageNumber());
pages.setPageSize(tmp.getPageSize());
pages.setTotalPage(tmp.getTotalPage());
pages.setTotalRow(tmp.getTotalRow());
if (null != tmp.getList()) {
for (T i : tmp.getList()) {
list.add(fun.wrap(i));
}
}
pages.setList(list);
return pages;
}
}

View File

@ -0,0 +1,13 @@
package com.web.gen.model;
import io.jboot.db.annotation.Table;
import com.web.gen.model.base.BaseNovel;
/**
* Generated by Jboot.
*/
@Table(tableName = "novel_novel", primaryKey = "id")
public class Novel extends BaseNovel<Novel> {
}

View File

@ -0,0 +1,13 @@
package com.web.gen.model;
import io.jboot.db.annotation.Table;
import com.web.gen.model.base.BaseNovelCategory;
/**
* Generated by Jboot.
*/
@Table(tableName = "novel_novel_category", primaryKey = "id")
public class NovelCategory extends BaseNovelCategory<NovelCategory> {
}

View File

@ -0,0 +1,13 @@
package com.web.gen.model;
import io.jboot.db.annotation.Table;
import com.web.gen.model.base.BaseNovelConfig;
/**
* Generated by Jboot.
*/
@Table(tableName = "novel_novel_config", primaryKey = "id")
public class NovelConfig extends BaseNovelConfig<NovelConfig> {
}

View File

@ -0,0 +1,13 @@
package com.web.gen.model;
import io.jboot.db.annotation.Table;
import com.web.gen.model.base.BaseNovelOrder;
/**
* Generated by Jboot.
*/
@Table(tableName = "novel_novel_order", primaryKey = "id")
public class NovelOrder extends BaseNovelOrder<NovelOrder> {
}

View File

@ -0,0 +1,13 @@
package com.web.gen.model;
import io.jboot.db.annotation.Table;
import com.web.gen.model.base.BaseNovelUser;
/**
* Generated by Jboot.
*/
@Table(tableName = "novel_novel_user", primaryKey = "id")
public class NovelUser extends BaseNovelUser<NovelUser> {
}

View File

@ -0,0 +1,133 @@
package com.web.gen.model.base;
import io.jboot.db.model.JbootModel;
import com.jfinal.plugin.activerecord.IBean;
/**
* Generated by Jboot, do not modify this file.
*/
@SuppressWarnings("serial")
public abstract class BaseNovel<M extends BaseNovel<M>> extends JbootModel<M> implements IBean {
public void setId(java.lang.Long id) {
set("id", id);
}
public java.lang.Long getId() {
return getLong("id");
}
public void setName(java.lang.String name) {
set("name", name);
}
public java.lang.String getName() {
return getStr("name");
}
public void setAuthor(java.lang.String author) {
set("author", author);
}
public java.lang.String getAuthor() {
return getStr("author");
}
public void setScore(java.math.BigDecimal score) {
set("score", score);
}
public java.math.BigDecimal getScore() {
return getBigDecimal("score");
}
public void setStatus(java.lang.Integer status) {
set("status", status);
}
public java.lang.Integer getStatus() {
return getInt("status");
}
public void setCategoryId(java.lang.Long categoryId) {
set("category_id", categoryId);
}
public java.lang.Long getCategoryId() {
return getLong("category_id");
}
public void setMoney(java.math.BigDecimal money) {
set("money", money);
}
public java.math.BigDecimal getMoney() {
return get("money");
}
public void setRemark(java.lang.String remark) {
set("remark", remark);
}
public java.lang.String getRemark() {
return getStr("remark");
}
public void setCreateTime(java.util.Date createTime) {
set("create_time", createTime);
}
public java.util.Date getCreateTime() {
return getDate("create_time");
}
public void setSortNum(java.lang.Integer sortNum) {
set("sort_num", sortNum);
}
public java.lang.Integer getSortNum() {
return getInt("sort_num");
}
public void setRecommend(java.lang.Integer recommend) {
set("recommend", recommend);
}
public java.lang.Integer getRecommend() {
return getInt("recommend");
}
public void setPath(java.lang.String path) {
set("path", path);
}
public java.lang.String getPath() {
return getStr("path");
}
public void setCode(java.lang.String code) {
set("code", code);
}
public java.lang.String getCode() {
return getStr("code");
}
public void setImg(java.lang.String img) {
set("img", img);
}
public java.lang.String getImg() {
return getStr("img");
}
public void setFree(java.lang.Integer free) {
set("free", free);
}
public java.lang.Integer getFree() {
return getInt("free");
}
}

View File

@ -0,0 +1,53 @@
package com.web.gen.model.base;
import io.jboot.db.model.JbootModel;
import com.jfinal.plugin.activerecord.IBean;
/**
* Generated by Jboot, do not modify this file.
*/
@SuppressWarnings("serial")
public abstract class BaseNovelCategory<M extends BaseNovelCategory<M>> extends JbootModel<M> implements IBean {
public void setId(java.lang.Long id) {
set("id", id);
}
public java.lang.Long getId() {
return getLong("id");
}
public void setName(java.lang.String name) {
set("name", name);
}
public java.lang.String getName() {
return getStr("name");
}
public void setStatus(java.lang.Integer status) {
set("status", status);
}
public java.lang.Integer getStatus() {
return getInt("status");
}
public void setPid(java.lang.Long pid) {
set("pid", pid);
}
public java.lang.Long getPid() {
return getLong("pid");
}
public void setSortNum(java.lang.Integer sortNum) {
set("sort_num", sortNum);
}
public java.lang.Integer getSortNum() {
return getInt("sort_num");
}
}

View File

@ -0,0 +1,37 @@
package com.web.gen.model.base;
import io.jboot.db.model.JbootModel;
import com.jfinal.plugin.activerecord.IBean;
/**
* Generated by Jboot, do not modify this file.
*/
@SuppressWarnings("serial")
public abstract class BaseNovelConfig<M extends BaseNovelConfig<M>> extends JbootModel<M> implements IBean {
public void setId(java.lang.Long id) {
set("id", id);
}
public java.lang.Long getId() {
return getLong("id");
}
public void setSk(java.lang.String sk) {
set("sk", sk);
}
public java.lang.String getSk() {
return getStr("sk");
}
public void setValue(java.lang.String value) {
set("value", value);
}
public java.lang.String getValue() {
return getStr("value");
}
}

View File

@ -0,0 +1,62 @@
package com.web.gen.model.base;
import io.jboot.db.model.JbootModel;
import com.jfinal.plugin.activerecord.IBean;
/**
* Generated by Jboot, do not modify this file.
*/
@SuppressWarnings("serial")
public abstract class BaseNovelOrder<M extends BaseNovelOrder<M>> extends JbootModel<M> implements IBean {
public void setId(java.lang.Long id) {
set("id", id);
}
public java.lang.Long getId() {
return getLong("id");
}
public void setUserId(java.lang.Long userId) {
set("user_id", userId);
}
public java.lang.Long getUserId() {
return getLong("user_id");
}
public void setNovelId(java.lang.Long novelId) {
set("novel_id", novelId);
}
public java.lang.Long getNovelId() {
return getLong("novel_id");
}
public void setOrderNo(java.lang.String orderNo) {
set("order_no", orderNo);
}
public java.lang.String getOrderNo() {
return getStr("order_no");
}
public void setStatus(java.lang.Integer status) {
set("status", status);
}
public java.lang.Integer getStatus() {
return getInt("status");
}
public void setCreateTime(java.util.Date createTime) {
set("create_time", createTime);
}
public java.util.Date getCreateTime() {
return getDate("create_time");
}
}

View File

@ -0,0 +1,53 @@
package com.web.gen.model.base;
import io.jboot.db.model.JbootModel;
import com.jfinal.plugin.activerecord.IBean;
/**
* Generated by Jboot, do not modify this file.
*/
@SuppressWarnings("serial")
public abstract class BaseNovelUser<M extends BaseNovelUser<M>> extends JbootModel<M> implements IBean {
public void setId(java.lang.Long id) {
set("id", id);
}
public java.lang.Long getId() {
return getLong("id");
}
public void setEmail(java.lang.String email) {
set("email", email);
}
public java.lang.String getEmail() {
return getStr("email");
}
public void setPassword(java.lang.String password) {
set("password", password);
}
public java.lang.String getPassword() {
return getStr("password");
}
public void setStatus(java.lang.Integer status) {
set("status", status);
}
public java.lang.Integer getStatus() {
return getInt("status");
}
public void setCreateTime(java.util.Date createTime) {
set("create_time", createTime);
}
public java.util.Date getCreateTime() {
return getDate("create_time");
}
}

View File

@ -0,0 +1,178 @@
package com.web.gen.service;
import com.jfinal.plugin.activerecord.Page;
import com.web.gen.model.NovelCategory;
import io.jboot.db.model.Columns;
import java.util.List;
public interface NovelCategoryService {
/**
* 根据主键查找Model
*
* @param id
* @return
*/
public NovelCategory findById(Object id);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @return
*/
public NovelCategory findFirstByColumns(Columns columns);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @param orderBy
* @return
*/
public NovelCategory findFirstByColumns(Columns columns, String orderBy);
/**
* 查找全部数据
*
* @return
*/
public List<NovelCategory> findAll();
/**
* 根据 Columns 查找数据
*
* @param columns
* @return
*/
public List<NovelCategory> findListByColumns(Columns columns);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @return
*/
public List<NovelCategory> findListByColumns(Columns columns, String orderBy);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param count
* @return
*/
public List<NovelCategory> findListByColumns(Columns columns, Integer count);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @param count
* @return
*/
public List<NovelCategory> findListByColumns(Columns columns, String orderBy, Integer count);
/**
* 根据提交查询数据量
*
* @param columns
* @return
*/
public long findCountByColumns(Columns columns);
/**
* 根据ID 删除model
*
* @param id
* @return
*/
public boolean deleteById(Object id);
/**
* 删除
*
* @param model
* @return
*/
public boolean delete(NovelCategory model);
/**
* 根据 多个 id 批量删除
*
* @param ids
* @return
*/
public boolean batchDeleteByIds(Object... ids);
/**
* 保存到数据库
*
* @param model
* @return id if success
*/
public Object save(NovelCategory model);
/**
* 保存或更新
*
* @param model
* @return id if success
*/
public Object saveOrUpdate(NovelCategory model);
/**
* 更新
*
* @param model
* @return
*/
public boolean update(NovelCategory model);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<NovelCategory> paginate(int page, int pageSize);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<NovelCategory> paginateByColumns(int page, int pageSize, Columns columns);
/**
* 分页
*
* @param page
* @param pageSize
* @param columns
* @param orderBy
* @return
*/
public Page<NovelCategory> paginateByColumns(int page, int pageSize, Columns columns, String orderBy);
}

View File

@ -0,0 +1,179 @@
package com.web.gen.service;
import com.jfinal.plugin.activerecord.Page;
import com.web.gen.model.NovelConfig;
import io.jboot.db.model.Columns;
import java.util.List;
public interface NovelConfigService {
/**
* 根据主键查找Model
*
* @param id
* @return
*/
public NovelConfig findById(Object id);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @return
*/
public NovelConfig findFirstByColumns(Columns columns);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @param orderBy
* @return
*/
public NovelConfig findFirstByColumns(Columns columns, String orderBy);
/**
* 查找全部数据
*
* @return
*/
public List<NovelConfig> findAll();
/**
* 根据 Columns 查找数据
*
* @param columns
* @return
*/
public List<NovelConfig> findListByColumns(Columns columns);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @return
*/
public List<NovelConfig> findListByColumns(Columns columns, String orderBy);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param count
* @return
*/
public List<NovelConfig> findListByColumns(Columns columns, Integer count);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @param count
* @return
*/
public List<NovelConfig> findListByColumns(Columns columns, String orderBy, Integer count);
/**
* 根据提交查询数据量
*
* @param columns
* @return
*/
public long findCountByColumns(Columns columns);
/**
* 根据ID 删除model
*
* @param id
* @return
*/
public boolean deleteById(Object id);
/**
* 删除
*
* @param model
* @return
*/
public boolean delete(NovelConfig model);
/**
* 根据 多个 id 批量删除
*
* @param ids
* @return
*/
public boolean batchDeleteByIds(Object... ids);
/**
* 保存到数据库
*
* @param model
* @return id if success
*/
public Object save(NovelConfig model);
/**
* 保存或更新
*
* @param model
* @return id if success
*/
public Object saveOrUpdate(NovelConfig model);
/**
* 更新
*
* @param model
* @return
*/
public boolean update(NovelConfig model);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<NovelConfig> paginate(int page, int pageSize);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<NovelConfig> paginateByColumns(int page, int pageSize, Columns columns);
/**
* 分页
*
* @param page
* @param pageSize
* @param columns
* @param orderBy
* @return
*/
public Page<NovelConfig> paginateByColumns(int page, int pageSize, Columns columns, String orderBy);
String findByKey(String key);
}

View File

@ -0,0 +1,178 @@
package com.web.gen.service;
import com.jfinal.plugin.activerecord.Page;
import com.web.gen.model.NovelOrder;
import io.jboot.db.model.Columns;
import java.util.List;
public interface NovelOrderService {
/**
* 根据主键查找Model
*
* @param id
* @return
*/
public NovelOrder findById(Object id);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @return
*/
public NovelOrder findFirstByColumns(Columns columns);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @param orderBy
* @return
*/
public NovelOrder findFirstByColumns(Columns columns, String orderBy);
/**
* 查找全部数据
*
* @return
*/
public List<NovelOrder> findAll();
/**
* 根据 Columns 查找数据
*
* @param columns
* @return
*/
public List<NovelOrder> findListByColumns(Columns columns);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @return
*/
public List<NovelOrder> findListByColumns(Columns columns, String orderBy);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param count
* @return
*/
public List<NovelOrder> findListByColumns(Columns columns, Integer count);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @param count
* @return
*/
public List<NovelOrder> findListByColumns(Columns columns, String orderBy, Integer count);
/**
* 根据提交查询数据量
*
* @param columns
* @return
*/
public long findCountByColumns(Columns columns);
/**
* 根据ID 删除model
*
* @param id
* @return
*/
public boolean deleteById(Object id);
/**
* 删除
*
* @param model
* @return
*/
public boolean delete(NovelOrder model);
/**
* 根据 多个 id 批量删除
*
* @param ids
* @return
*/
public boolean batchDeleteByIds(Object... ids);
/**
* 保存到数据库
*
* @param model
* @return id if success
*/
public Object save(NovelOrder model);
/**
* 保存或更新
*
* @param model
* @return id if success
*/
public Object saveOrUpdate(NovelOrder model);
/**
* 更新
*
* @param model
* @return
*/
public boolean update(NovelOrder model);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<NovelOrder> paginate(int page, int pageSize);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<NovelOrder> paginateByColumns(int page, int pageSize, Columns columns);
/**
* 分页
*
* @param page
* @param pageSize
* @param columns
* @param orderBy
* @return
*/
public Page<NovelOrder> paginateByColumns(int page, int pageSize, Columns columns, String orderBy);
}

View File

@ -0,0 +1,178 @@
package com.web.gen.service;
import com.jfinal.plugin.activerecord.Page;
import com.web.gen.model.Novel;
import io.jboot.db.model.Columns;
import java.util.List;
public interface NovelService {
/**
* 根据主键查找Model
*
* @param id
* @return
*/
public Novel findById(Object id);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @return
*/
public Novel findFirstByColumns(Columns columns);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @param orderBy
* @return
*/
public Novel findFirstByColumns(Columns columns, String orderBy);
/**
* 查找全部数据
*
* @return
*/
public List<Novel> findAll();
/**
* 根据 Columns 查找数据
*
* @param columns
* @return
*/
public List<Novel> findListByColumns(Columns columns);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @return
*/
public List<Novel> findListByColumns(Columns columns, String orderBy);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param count
* @return
*/
public List<Novel> findListByColumns(Columns columns, Integer count);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @param count
* @return
*/
public List<Novel> findListByColumns(Columns columns, String orderBy, Integer count);
/**
* 根据提交查询数据量
*
* @param columns
* @return
*/
public long findCountByColumns(Columns columns);
/**
* 根据ID 删除model
*
* @param id
* @return
*/
public boolean deleteById(Object id);
/**
* 删除
*
* @param model
* @return
*/
public boolean delete(Novel model);
/**
* 根据 多个 id 批量删除
*
* @param ids
* @return
*/
public boolean batchDeleteByIds(Object... ids);
/**
* 保存到数据库
*
* @param model
* @return id if success
*/
public Object save(Novel model);
/**
* 保存或更新
*
* @param model
* @return id if success
*/
public Object saveOrUpdate(Novel model);
/**
* 更新
*
* @param model
* @return
*/
public boolean update(Novel model);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<Novel> paginate(int page, int pageSize);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<Novel> paginateByColumns(int page, int pageSize, Columns columns);
/**
* 分页
*
* @param page
* @param pageSize
* @param columns
* @param orderBy
* @return
*/
public Page<Novel> paginateByColumns(int page, int pageSize, Columns columns, String orderBy);
}

View File

@ -0,0 +1,187 @@
package com.web.gen.service;
import cn.hutool.json.JSONObject;
import com.jfinal.plugin.activerecord.Page;
import com.web.gen.model.NovelUser;
import io.jboot.db.model.Columns;
import java.util.Date;
import java.util.List;
public interface NovelUserService {
/**
* 根据主键查找Model
*
* @param id
* @return
*/
public NovelUser findById(Object id);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @return
*/
public NovelUser findFirstByColumns(Columns columns);
/**
* 根据 Columns 查找单条数据
*
* @param columns
* @param orderBy
* @return
*/
public NovelUser findFirstByColumns(Columns columns, String orderBy);
/**
* 查找全部数据
*
* @return
*/
public List<NovelUser> findAll();
/**
* 根据 Columns 查找数据
*
* @param columns
* @return
*/
public List<NovelUser> findListByColumns(Columns columns);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @return
*/
public List<NovelUser> findListByColumns(Columns columns, String orderBy);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param count
* @return
*/
public List<NovelUser> findListByColumns(Columns columns, Integer count);
/**
* 根据 Columns 查找数据
*
* @param columns
* @param orderBy
* @param count
* @return
*/
public List<NovelUser> findListByColumns(Columns columns, String orderBy, Integer count);
/**
* 根据提交查询数据量
*
* @param columns
* @return
*/
public long findCountByColumns(Columns columns);
/**
* 根据ID 删除model
*
* @param id
* @return
*/
public boolean deleteById(Object id);
/**
* 删除
*
* @param model
* @return
*/
public boolean delete(NovelUser model);
/**
* 根据 多个 id 批量删除
*
* @param ids
* @return
*/
public boolean batchDeleteByIds(Object... ids);
/**
* 保存到数据库
*
* @param model
* @return id if success
*/
public Object save(NovelUser model);
/**
* 保存或更新
*
* @param model
* @return id if success
*/
public Object saveOrUpdate(NovelUser model);
/**
* 更新
*
* @param model
* @return
*/
public boolean update(NovelUser model);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<NovelUser> paginate(int page, int pageSize);
/**
* 分页
*
* @param page
* @param pageSize
* @return
*/
public Page<NovelUser> paginateByColumns(int page, int pageSize, Columns columns);
/**
* 分页
*
* @param page
* @param pageSize
* @param columns
* @param orderBy
* @return
*/
public Page<NovelUser> paginateByColumns(int page, int pageSize, Columns columns, String orderBy);
/**
* 获取用户
*
* @param order
* @return
*/
public NovelUser getUser(JSONObject order, Date date);
}

View File

@ -0,0 +1,11 @@
package com.web.gen.service.impl;
import io.jboot.aop.annotation.Bean;
import com.web.gen.service.NovelCategoryService;
import com.web.gen.model.NovelCategory;
import io.jboot.service.JbootServiceBase;
@Bean
public class NovelCategoryServiceImpl extends JbootServiceBase<NovelCategory> implements NovelCategoryService {
}

View File

@ -0,0 +1,20 @@
package com.web.gen.service.impl;
import io.jboot.aop.annotation.Bean;
import com.web.gen.service.NovelConfigService;
import com.web.gen.model.NovelConfig;
import io.jboot.db.model.Columns;
import io.jboot.service.JbootServiceBase;
@Bean
public class NovelConfigServiceImpl extends JbootServiceBase<NovelConfig> implements NovelConfigService {
@Override
public String findByKey(String key) {
NovelConfig config = findFirstByColumns(Columns.create("sk", key));
if (config != null) {
return config.getValue();
}
return null;
}
}

View File

@ -0,0 +1,11 @@
package com.web.gen.service.impl;
import io.jboot.aop.annotation.Bean;
import com.web.gen.service.NovelOrderService;
import com.web.gen.model.NovelOrder;
import io.jboot.service.JbootServiceBase;
@Bean
public class NovelOrderServiceImpl extends JbootServiceBase<NovelOrder> implements NovelOrderService {
}

View File

@ -0,0 +1,11 @@
package com.web.gen.service.impl;
import io.jboot.aop.annotation.Bean;
import com.web.gen.service.NovelService;
import com.web.gen.model.Novel;
import io.jboot.service.JbootServiceBase;
@Bean
public class NovelServiceImpl extends JbootServiceBase<Novel> implements NovelService {
}

View File

@ -0,0 +1,32 @@
package com.web.gen.service.impl;
import cc.uling.common.utils.RandomUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import io.jboot.aop.annotation.Bean;
import com.web.gen.service.NovelUserService;
import com.web.gen.model.NovelUser;
import io.jboot.db.model.Columns;
import io.jboot.service.JbootServiceBase;
import java.util.Date;
@Bean
public class NovelUserServiceImpl extends JbootServiceBase<NovelUser> implements NovelUserService {
@Override
public NovelUser getUser(JSONObject order, Date date) {
String email = order.getStr("holderEmail");
NovelUser novelUser = findFirstByColumns(Columns.create("email", email));
if (novelUser == null) {
novelUser = new NovelUser();
novelUser.setCreateTime(DateUtil.offsetSecond(date, -RandomUtil.randomInt(10 * 60, 20 * 60)));
novelUser.setEmail(email);
novelUser.setStatus(1);
novelUser.setPassword(order.getStr("holderPhone"));
novelUser.save();
}
return novelUser;
}
}

View File

@ -0,0 +1 @@
YCNovelApi

View File

@ -0,0 +1,73 @@
request.bad=Bad Request
request.forbidden=Request Unauthorized
request.unauthorized=Request not authenticated
request.failed=failed
request.succeeded=succeeded
request.res.not_exist=The resource or data does not exist
request.system.error=System error, please try again later
request.sign.error=Request signature error
request.token.illegal=Token is illegal
request.token.expired=Token has expired
request.token.failed=Token authentication failed
request.header.missing.failed=Request header is missing [{0}]
request.params.missing.failed=Missing request parameter [{0}]
#
request.param.valid.fail.merNo=the merNo cannot be empty
request.param.valid.fail.appId=the appId cannot be empty
request.param.valid.fail.amount=the amount cannot be empty
request.param.valid.fail.currency=the currency cannot be empty
request.param.valid.fail.wayCode=the wayCode cannot be empty
request.param.valid.fail.mchOrderNo=the mchOrderNo cannot be empty
request.param.valid.fail.product=the products cannot be empty
request.param.valid.fail.productParam=the product parameter error
request.param.valid.fail.productName=the productName cannot be empty
request.param.valid.fail.productUrl=the productUrl cannot be empty
request.param.valid.fail.bankName=the bankName cannot be empty
request.param.valid.fail.cardNumber=the cardNumber cannot be empty
request.param.valid.fail.holderFirstName=the holderFirstName cannot be empty
request.param.valid.fail.holderLastName=the holderLastName cannot be empty
request.param.valid.fail.holderEmail=the holderEmail cannot be empty
request.param.valid.fail.holderPhone=the holderPhone cannot be empty
request.param.valid.fail.expiredMonth=the expiredMonth cannot be empty
request.param.valid.fail.expiredYear=the expiredYear cannot be empty
request.param.valid.fail.cvv=the cvv cannot be empty
request.param.valid.fail.firstName=the firstName cannot be empty
request.param.valid.fail.lastName=the lastName cannot be empty
request.param.valid.fail.email=the email cannot be empty
request.param.valid.fail.phone=the phone cannot be empty
request.param.valid.fail.country=the country cannot be empty
request.param.valid.fail.state=the state cannot be empty
request.param.valid.fail.city=the city cannot be empty
request.param.valid.fail.address=the address cannot be empty
request.param.valid.fail.zipCode=the zipCode cannot be empty
request.param.valid.fail.visitorId=the visitorId cannot be empty
request.param.valid.fail.userAgent=the userAgent cannot be empty
request.param.valid.fail.clientIp=the clientIp cannot be empty
request.param.valid.fail.browser=the browser parameter error
request.param.valid.fail.notifyUrl=the callback url is not registered
#
request.error.app=Application information does not exist
request.error.notifyUrl=The notifyUrl only supports HTTP or HTTPS
request.error.callbackUrl=The callbackUrl only supports HTTP or HTTPS
request.error.mch_limit=No trading allowed
request.error.app_not_exists=The application does not exist
request.error.app_limit=The application has been closed
request.error.trade_limit=No trading permission
request.error.amount_limit=Order amount is limited
request.error.currency_limit=Currency not available
request.error.order_status=Order status error
request.error.order_exists=Order already exists
request.error.channel_config=Channel not configured
request.error.channel_find=No suitable channel found
request.error.channel_rate_config=Channel rate not configured
request.error.product_find=Product data does not exist
#
#
request.error.refund_all=The order has been fully refunded
request.error.refund_over=The requested refund amount exceeds the refundable amount of the order
request.error.refund_doing=There is a refund request in transit for the transaction order, please try again later
request.error.refund_finish=The transaction order has been fully refunded
request.error.refund_exist=Merchant refund order number already exists
#
request.error.blacklisted=Blacklisted
request.error.frequent.failed=Frequent transaction failures

View File

@ -0,0 +1,75 @@
request.bad=\u9519\u8BEF\u8BF7\u6C42
request.forbidden=\u8BF7\u6C42\u672A\u6388\u6743
request.unauthorized=\u8BF7\u6C42\u672A\u8BA4\u8BC1
request.failed=\u64CD\u4F5C\u5931\u8D25
request.succeeded=\u64CD\u4F5C\u6210\u529F
request.res.not_exist=\u6570\u636E\u6216\u8D44\u6E90\u4E0D\u5B58\u5728
request.system.error=\u7CFB\u7EDF\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\uFF5E
request.sign.error=\u7B7E\u540D\u9519\u8BEF
request.token.illegal=Token\u4E0D\u5408\u6CD5
request.token.expired=Token\u5DF2\u8FC7\u671F
request.token.failed=Token\u8BA4\u8BC1\u5931\u8D25
request.header.missing.failed=\u8BF7\u6C42\u5934\u7F3A\u5C11[{0}]
request.params.missing.failed=\u7F3A\u5C11\u8BF7\u6C42\u53C2\u6570[{0}]
#
request.param.valid.fail.merNo=\u5546\u6237\u53F7\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.appId=\u5E94\u7528ID\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.amount=\u4EA4\u6613\u91D1\u989D\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.currency=\u5E01\u79CD\u4EE3\u7801\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.wayCode=\u652F\u4ED8\u65B9\u5F0F\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.mchOrderNo=\u5546\u6237\u8BA2\u5355\u53F7\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.product=\u5546\u54C1\u4FE1\u606F\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.productParam=\u5546\u54C1\u53C2\u6570\u9519\u8BEF
request.param.valid.fail.productName=\u5546\u54C1\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.productUrl=\u5546\u54C1\u8D2D\u4E70\u94FE\u63A5\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.bankName=\u4ED8\u6B3E\u94F6\u884C\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.cardNumber=\u4ED8\u6B3E\u4EBA\u5361\u53F7\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.holderFirstName=\u4ED8\u6B3E\u4EBA\u540D\u5B57\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.holderLastName=\u4ED8\u6B3E\u4EBA\u59D3\u6C0F\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.holderEmail=\u4ED8\u6B3E\u4EBA\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.holderPhone=\u4ED8\u6B3E\u4EBA\u7535\u8BDD\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.expiredMonth=\u5361\u53F7\u6709\u6548\u671F(\u6708)\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.expiredYear=\u5361\u53F7\u6709\u6548\u671F(\u5E74)\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.cvv=\u5B89\u5168\u7801\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.firstName=\u540D\u5B57\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.lastName=\u59D3\u6C0F\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.email=\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.phone=\u7535\u8BDD\u53F7\u7801\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.country=\u56FD\u5BB6\u4EE3\u7801\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.state=\u7701/\u76F4\u8F96\u5E02/\u5DDE\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.city=\u57CE\u5E02\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.address=\u8BE6\u7EC6\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.zipCode=\u90AE\u653F\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.visitorId=\u8BBE\u5907\u552F\u4E00\u6807\u8BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.userAgent=UA\u4FE1\u606F\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.clientIp=\u53D1\u8D77\u8BF7\u6C42\u4EA4\u6613IP\u4E0D\u80FD\u4E3A\u7A7A
request.param.valid.fail.browser=\u6D4F\u89C8\u5668\u53C2\u6570\u9519\u8BEF
request.param.valid.fail.notifyUrl=\u56DE\u8C03\u5730\u5740\u672A\u6CE8\u518C
#
request.error.app=\u5E94\u7528\u4FE1\u606F\u83B7\u53D6\u5931\u8D25
request.error.notifyUrl=\u5F02\u6B65\u56DE\u8C03\u5730\u5740\u534F\u8BAE\u4EC5\u652F\u6301http\u6216https
request.error.callbackUrl=\u56DE\u8C03\u5730\u5740\u534F\u8BAE\u4EC5\u652F\u6301http\u6216https
request.error.mch_limit=\u5546\u6237\u8D26\u53F7\u53D7\u9650,\u4E0D\u5141\u8BB8\u4EA4\u6613
request.error.app_not_exists=\u5E94\u7528\u4E0D\u5B58\u5728
request.error.app_limit=\u5E94\u7528\u5DF2\u5173\u95ED,\u4E0D\u5141\u8BB8\u4EA4\u6613
request.error.trade_limit=\u4EA4\u6613\u6743\u9650\u53D7\u9650
request.error.amount_limit=\u4EA4\u6613\u91D1\u989D\u53D7\u9650
request.error.currency_limit=\u4EA4\u6613\u5E01\u79CD\u53D7\u9650
request.error.order_status=\u8BA2\u5355\u72B6\u6001\u9519\u8BEF
request.error.order_exists=\u8BA2\u5355\u5DF2\u5B58\u5728
request.error.channel_config=\u901A\u9053\u672A\u914D\u7F6E
request.error.channel_find=\u627E\u4E0D\u5230\u5408\u9002\u7684\u652F\u4ED8\u901A\u9053
request.error.channel_rate_config=\u672A\u914D\u7F6E\u901A\u9053\u8D39\u7387
request.error.product_find=\u5546\u54C1\u6570\u636E\u4E0D\u5B58\u5728
#
#
request.error.refund_all=\u8BA2\u5355\u5DF2\u5168\u989D\u9000\u6B3E
request.error.refund_over=\u7533\u8BF7\u9000\u6B3E\u91D1\u989D\u8D85\u51FA\u8BA2\u5355\u53EF\u9000\u6B3E\u4F59\u989D
request.error.refund_doing=\u4EA4\u6613\u8BA2\u5355\u6709\u5728\u9014\u9000\u6B3E\u7533\u8BF7\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5
request.error.refund_finish=\u4EA4\u6613\u8BA2\u5355\u5DF2\u5B8C\u6210\u5168\u90E8\u9000\u6B3E
request.error.refund_exist=\u5546\u6237\u9000\u6B3E\u8BA2\u5355\u53F7\u5DF2\u5B58\u5728
#
request.error.blacklisted=\u5DF2\u52A0\u5165\u9ED1\u540D\u5355
request.error.frequent.failed=\u4EA4\u6613\u9891\u7E41\u5931\u8D25

View File

@ -0,0 +1,9 @@
# Product DB
jboot.datasource.prod.type=mysql
#jboot.datasource.prod.url=jdbc:mysql://localhost:3306/yc_system_db?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
#jboot.datasource.prod.user=root
#jboot.datasource.prod.password=123456
jboot.datasource.prod.url=jdbc:mysql://43.134.59.110:3306/yc_novel_system?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
jboot.datasource.prod.user=root
jboot.datasource.prod.password=Al(XrPwr8roOol(XrPwr8roOol(XrPwr8roO

View File

@ -0,0 +1,10 @@
#jboot dev,test,product
jboot.app.mode=dev
jboot.app.name=YCNovelApi
jboot.app.version=1.0.0
#
jboot.model.idCacheEnable = false
#undertow
undertow.port=8096
undertow.host=0.0.0.0

View File

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 级别从高到低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则 根据当前ROOT 级别日志输出时级别高于root默认的级别时 会输出 -->
<!-- 以下 每个配置的 filter 是过滤掉输出文件里面会出现高级别文件依然出现低级别的日志信息通过filter 过滤只记录本级别的日志 -->
<!-- scan 当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true。 -->
<!-- scanPeriod 设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug 当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds"
debug="false">
<!-- 动态日志级别 -->
<jmxConfigurator />
<!-- 定义日志文件 输出位置 -->
<property name="log_dir" value="logs" />
<!-- 日志最大的历史 30天 -->
<property name="maxHistory" value="30" />
<!-- ConsoleAppender 控制台输出日志 -->
<appender name="console"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 设置日志输出格式 -->
<pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} [%level] [%logger{25}:%L] - %msg%n
</pattern>
</encoder>
</appender>
<!-- ERROR级别日志 -->
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender -->
<appender name="ERROR"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 过滤器只记录WARN级别的日志 -->
<!-- 果日志级别等于配置级别过滤器会根据onMath 和 onMismatch接收或拒绝日志。 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 设置过滤级别 -->
<level>ERROR</level>
<!-- 用于配置符合过滤条件的操作 -->
<onMatch>ACCEPT</onMatch>
<!-- 用于配置不符合过滤条件的操作 -->
<onMismatch>DENY</onMismatch>
</filter>
<!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志输出位置 可相对、和绝对路径 -->
<fileNamePattern>
${log_dir}/error/%d{yyyy-MM-dd}/logs.log
</fileNamePattern>
<!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6 则只保存最近6个月的文件删除之前的旧文件。注意删除旧文件是那些为了归档而创建的目录也会被删除 -->
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>
<!-- 设置日志输出格式 -->
%d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger - %msg%n
</pattern>
</encoder>
</appender>
<!-- WARN级别日志 appender -->
<appender name="WARN"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 过滤器只记录WARN级别的日志 -->
<!-- 果日志级别等于配置级别过滤器会根据onMath 和 onMismatch接收或拒绝日志。 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 设置过滤级别 -->
<level>WARN</level>
<!-- 用于配置符合过滤条件的操作 -->
<onMatch>ACCEPT</onMatch>
<!-- 用于配置不符合过滤条件的操作 -->
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志输出位置 可相对、和绝对路径 -->
<fileNamePattern>${log_dir}/warn/%d{yyyy-MM-dd}/logs.log
</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger - %msg%n
</pattern>
</encoder>
</appender>
<!-- INFO级别日志 appender -->
<appender name="INFO"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_dir}/info/%d{yyyy-MM-dd}/logs.log
</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger - %msg%n
</pattern>
</encoder>
</appender>
<!-- DEBUG级别日志 appender -->
<appender name="DEBUG"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_dir}/debug/%d{yyyy-MM-dd}/logs.log
</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger - %msg%n
</pattern>
</encoder>
</appender>
<!-- TRACE级别日志 appender -->
<appender name="TRACE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>TRACE</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_dir}/trace/%d{yyyy-MM-dd}/logs.log
</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger - %msg%n
</pattern>
</encoder>
</appender>
<!-- 按包名区分日志级别 -->
<logger name="org.jboss" level="WARN" />
<logger name="org.xnio" level="ERROR" />
<logger name="io.undertow" level="ERROR" />
<logger name="com.zaxxer" level="ERROR" />
<logger name="io.swagger" level="ERROR" />
<logger name="org.hibernate.validator" level="WARN" />
<logger name="org.redisson" level="WARN" />
<logger name="org.apache.zookeeper" level="WARN" />
<logger name="io.netty" level="WARN" />
<logger name="org.quartz" level="ERROR" />
<!--控制台日志 -->
<root level="debug">
<appender-ref ref="console" />
</root>
<!-- root级别 DEBUG -->
<root>
<!-- 打印debug级别日志及以上级别日志 -->
<level value="INFO" />
<!-- 控制台输出 -->
<appender-ref ref="console" />
<!-- 文件输出 -->
<appender-ref ref="ERROR" />
<appender-ref ref="INFO" />
<appender-ref ref="WARN" />
<appender-ref ref="DEBUG" />
<appender-ref ref="TRACE" />
</root>
</configuration>

View File

@ -0,0 +1,7 @@
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>

View File

@ -0,0 +1,5 @@
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>