日志功能
This commit is contained in:
parent
57616bce02
commit
0022bd1b3a
|
|
@ -59,7 +59,7 @@ public class SysLogsVo {
|
|||
* 操作时间
|
||||
*/
|
||||
@ApiModelProperty(value = "操作时间")
|
||||
private String operaTime;
|
||||
private String operTime;
|
||||
/**
|
||||
* 操作详情
|
||||
*/
|
||||
|
|
@ -79,7 +79,7 @@ public class SysLogsVo {
|
|||
*请求路径
|
||||
*/
|
||||
@ApiModelProperty(value = "操作页面路径URI")
|
||||
private String operaUri;
|
||||
private String operUri;
|
||||
/**
|
||||
* 日志类型 1 业务日志 0 系统日志 2异常日志
|
||||
*/
|
||||
|
|
@ -146,6 +146,7 @@ public class SysLogsVo {
|
|||
|
||||
//日志类型 1 业务日志 0 系统日志 2异常日志
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 越权记录
|
||||
* @param loginUser
|
||||
|
|
@ -170,8 +171,8 @@ public class SysLogsVo {
|
|||
vo.setFailureReason("操作未授权");
|
||||
vo.setGrade("高");
|
||||
vo.setErrType("越权访问");
|
||||
vo.setOperaUri(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
|
||||
vo.setOperaTime(DateUtils.getTime());
|
||||
vo.setOperUri(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
|
||||
vo.setOperTime(DateUtils.getTime());
|
||||
vo.setLogType(2);
|
||||
//
|
||||
if (StringUtils.isNotBlank(loginUser.getUsername())){
|
||||
|
|
|
|||
|
|
@ -71,13 +71,13 @@ public class SysRecordLogService
|
|||
sysLogsVo.setOperaUserName(username);
|
||||
sysLogsVo.setIp(IpUtils.getIpAddr());
|
||||
sysLogsVo.setModel("系统登陆");
|
||||
sysLogsVo.setOperaTime(DateUtils.getTime());
|
||||
sysLogsVo.setOperTime(DateUtils.getTime());
|
||||
sysLogsVo.setMethodType(SystemGlobal.POST);
|
||||
sysLogsVo.setMethod("login()");
|
||||
sysLogsVo.setParams("{\"username\":\""+username+"\"}");
|
||||
sysLogsVo.setOperateDetail("用户登陆系统");
|
||||
sysLogsVo.setOperType("登陆");
|
||||
sysLogsVo.setOperaUri("/login");
|
||||
sysLogsVo.setOperUri("/login");
|
||||
sysLogsVo.setLogType(0);
|
||||
if (StringUtils.isNotEmpty(result)){
|
||||
sysLogsVo.setResult(result);
|
||||
|
|
@ -111,17 +111,17 @@ public class SysRecordLogService
|
|||
SysLogsVo sysLogsVo = new SysLogsVo();
|
||||
sysLogsVo.setGrade("高");
|
||||
String uuid= UUID.randomUUID().toString().replace("-","").toUpperCase();
|
||||
sysLogsVo.setOperType("登陆");
|
||||
sysLogsVo.setOperaUri("/login");
|
||||
sysLogsVo.setOperType("登录");
|
||||
sysLogsVo.setOperUri("/login");
|
||||
sysLogsVo.setLogType(2);
|
||||
sysLogsVo.setResult(OperaResult.SUCCESS);
|
||||
if (StringUtils.isNotEmpty(userId)){
|
||||
sysLogsVo.setUserId(userId);
|
||||
}
|
||||
sysLogsVo.setResultData("用户登陆成功");
|
||||
sysLogsVo.setTitle("系统登陆");
|
||||
sysLogsVo.setModel("系统登陆");
|
||||
sysLogsVo.setOperaTime(DateUtils.getTime());
|
||||
sysLogsVo.setResultData("用户登录成功");
|
||||
sysLogsVo.setTitle("系统登录");
|
||||
sysLogsVo.setModel("系统登录");
|
||||
sysLogsVo.setOperTime(DateUtils.getTime());
|
||||
sysLogsVo.setMethodType(SystemGlobal.POST);
|
||||
sysLogsVo.setMethod("login()");
|
||||
sysLogsVo.setLogId(uuid);
|
||||
|
|
@ -157,13 +157,13 @@ public class SysRecordLogService
|
|||
if (StringUtils.isNotEmpty(userId)){
|
||||
sysLogsVo.setUserId(userId);
|
||||
}
|
||||
sysLogsVo.setOperaTime(DateUtils.getTime());
|
||||
sysLogsVo.setOperTime(DateUtils.getTime());
|
||||
sysLogsVo.setMethodType(SystemGlobal.POST);
|
||||
sysLogsVo.setMethod("logout()");
|
||||
sysLogsVo.setParams("{\"username\":\""+username+"\"}");
|
||||
sysLogsVo.setOperateDetail("用户退出登录");
|
||||
sysLogsVo.setOperType("登出");
|
||||
sysLogsVo.setOperaUri("/logout");
|
||||
sysLogsVo.setOperUri("/logout");
|
||||
if (StringUtils.isNotEmpty(result)){
|
||||
sysLogsVo.setResult(result);
|
||||
}else{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@
|
|||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.30</version>
|
||||
</dependency>
|
||||
<!-- SpringCloud Loadbalancer -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
package com.bonus.common.core.utils;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.sql.Blob;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* @author HeiZi
|
||||
*/
|
||||
public class StringHelper {
|
||||
|
||||
private static final String HEX_STRING = "0123456789ABCDEF";
|
||||
|
||||
public static String replaceAll(String str, String oldStr, String newStr) {
|
||||
return str.replaceAll(oldStr, newStr);
|
||||
}
|
||||
|
||||
public static boolean contains(String s1, String s2) {
|
||||
if (isEmpty(s1)) {
|
||||
return false;
|
||||
}
|
||||
return s1.contains(s2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 集合转数组
|
||||
*
|
||||
* @param list
|
||||
* @param separator
|
||||
* @return
|
||||
*/
|
||||
public static String listToString(List<String> list, char separator) {
|
||||
return StringUtils.join(list.toArray(), separator);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* blob中文乱码转码
|
||||
* @return
|
||||
*/
|
||||
public static String blobToStrings(Blob b) {
|
||||
try {
|
||||
if(b == null) {
|
||||
return null;
|
||||
}
|
||||
String content = new String(b.getBytes((long) 1, (int) b.length()), "UTF-8");
|
||||
return content;
|
||||
} catch (SQLException | UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* blob中文乱码转码
|
||||
*
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
public static String blobToString(String content) {
|
||||
try {
|
||||
return new String(content.getBytes("ISO_8859_1"), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* unicode转字符串
|
||||
*
|
||||
* @param unicode
|
||||
* @return
|
||||
*/
|
||||
public static String unicodeToString(String unicode) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String[] hex = unicode.split("\\\\u");
|
||||
for (int i = 1; i < hex.length; i++) {
|
||||
int index = Integer.parseInt(hex[i], 16);
|
||||
sb.append((char) index);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* * 含有unicode 的字符串转一般字符串 * @param unicodeStr 混有 Unicode 的字符串
|
||||
* * @return
|
||||
*/
|
||||
public static String unicodeStr2String(String unicodeStr) {
|
||||
int length = unicodeStr.length();
|
||||
int count = 0;
|
||||
// 正则匹配条件,可匹配“\\u”1到4位,一般是4位可直接使用 String regex = "\\\\u[a-f0-9A-F]{4}";
|
||||
String regex = "\\\\u[a-f0-9A-F]{1,4}";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(unicodeStr);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
while (matcher.find()) {
|
||||
String oldChar = matcher.group();
|
||||
String newChar = unicode2String(oldChar);
|
||||
int index = matcher.start();
|
||||
sb.append(unicodeStr.substring(count, index));
|
||||
sb.append(newChar);
|
||||
count = index + oldChar.length();
|
||||
}
|
||||
sb.append(unicodeStr.substring(count, length));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* unicode 转字符串
|
||||
* 全为 Unicode 的字符串
|
||||
* @param unicode
|
||||
* @return
|
||||
*/
|
||||
public static String unicode2String(String unicode) {
|
||||
StringBuffer string = new StringBuffer();
|
||||
String[] hex = unicode.split("\\\\u");
|
||||
|
||||
for (int i = 1; i < hex.length; i++) {
|
||||
// 转换出每一个代码点
|
||||
int data = Integer.parseInt(hex[i], 16);
|
||||
// 追加成string
|
||||
string.append((char) data);
|
||||
}
|
||||
|
||||
return string.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串编码成16进制数字,适用于所有字符(包括中文)
|
||||
*/
|
||||
public static String encode(String str) {
|
||||
// 根据默认编码获取字节数组
|
||||
byte[] bytes = str.getBytes();
|
||||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||||
// 将字节数组中每个字节拆解成2位16进制整数
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
sb.append(HEX_STRING.charAt((bytes[i] & 0xf0) >> 4));
|
||||
sb.append(HEX_STRING.charAt((bytes[i] & 0x0f) >> 0));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String decode(String bytes) {
|
||||
int num=2;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / num);
|
||||
// 将每2位16进制整数组装成一个字节
|
||||
for (int i = 0; i < bytes.length(); i += num){
|
||||
baos.write((HEX_STRING.indexOf(bytes.charAt(i)) << 4 | HEX_STRING.indexOf(bytes.charAt(i + 1))));
|
||||
}
|
||||
|
||||
return new String(baos.toByteArray());
|
||||
}
|
||||
|
||||
public static String fillPrefixZero(int v, int len) {
|
||||
String vStr = v + "";
|
||||
StringBuilder tst=new StringBuilder("0");
|
||||
while (vStr.length() < len) {
|
||||
vStr =tst.append(vStr).toString();
|
||||
}
|
||||
return vStr;
|
||||
}
|
||||
|
||||
public static boolean isEmpty(String str) {
|
||||
return str == null || "".equals(str.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串 不为空
|
||||
*/
|
||||
public static boolean isNotEmpty(String str) {
|
||||
return !isEmpty(str);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,329 @@
|
|||
package com.bonus.common.core.utils;
|
||||
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
* @Auther: ccw
|
||||
* @Date: 2021/07/22/9:57
|
||||
* @description:
|
||||
*/
|
||||
public class WordUtils {
|
||||
|
||||
public static String pdf_fix="pdf";
|
||||
|
||||
public static String doc_fix="doc";
|
||||
|
||||
public static String docx_fix="docx";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static Configuration configuration = null;
|
||||
|
||||
static {
|
||||
configuration = new Configuration(Configuration.VERSION_2_3_30);
|
||||
configuration.setDefaultEncoding("utf-8");
|
||||
configuration.setClassForTemplateLoading(WordUtils.class, "/download/");
|
||||
|
||||
}
|
||||
|
||||
private WordUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws IOException {
|
||||
Template freemarkerTemplate = configuration.getTemplate(ftlFile);
|
||||
File file = null;
|
||||
InputStream fin = null;
|
||||
ServletOutputStream out = null;
|
||||
try {
|
||||
// 调用工具类的createDoc方法生成Word文档
|
||||
file = createDoc(map, freemarkerTemplate);
|
||||
fin = new FileInputStream(file);
|
||||
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("application/msword");
|
||||
// 设置浏览器以下载的方式处理该文件名
|
||||
String fileName = title + ".docx";
|
||||
response.setHeader("Content-Disposition", "attachment;filename="
|
||||
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
|
||||
|
||||
out = response.getOutputStream();
|
||||
byte[] buffer = new byte[512];
|
||||
int bytesToRead = -1;
|
||||
// 通过循环将读入的Word文件的内容输出到浏览器中
|
||||
while ((bytesToRead = fin.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesToRead);
|
||||
}
|
||||
} finally {
|
||||
if (fin != null) {fin.close();}
|
||||
if (out != null) {out.close();}
|
||||
// 删除临时文件
|
||||
if (file != null) {file.delete();}
|
||||
}
|
||||
}
|
||||
|
||||
private static File createDoc(Map<?, ?> dataMap, Template template) {
|
||||
String name = "sellPlan.doc";
|
||||
File f = new File(name);
|
||||
Template t = template;
|
||||
try {
|
||||
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
|
||||
Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
|
||||
t.process(dataMap, w);
|
||||
w.close();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
public static void exportMillCertificateWord2(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile, String path) throws IOException {
|
||||
Template freemarkerTemplate = configuration.getTemplate(ftlFile);
|
||||
File file = null;
|
||||
InputStream fin = null;
|
||||
OutputStream out = null;
|
||||
String uploadPath = path + "word" + File.separator;
|
||||
try {
|
||||
// 调用工具类的createDoc方法生成Word文档
|
||||
file = createDoc(map, freemarkerTemplate);
|
||||
fin = new FileInputStream(file);
|
||||
|
||||
File file2 = new File(uploadPath);
|
||||
// 生成文件夹
|
||||
if (!file2.exists()) {
|
||||
file2.mkdirs();
|
||||
}
|
||||
String fileName = uploadPath + File.separator + title + ".doc";
|
||||
out = new FileOutputStream(new File(fileName));
|
||||
byte[] buffer = new byte[512];
|
||||
int bytesToRead = -1;
|
||||
// 通过循环将读入的Word文件的内容输出到浏览器中
|
||||
while ((bytesToRead = fin.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesToRead);
|
||||
}
|
||||
} finally {
|
||||
if (fin != null) {fin.close();}
|
||||
if (out != null) {out.close();}
|
||||
// 删除临时文件
|
||||
if (file != null) {file.delete();}
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportPdf(HttpServletRequest request, HttpServletResponse response, String titleName, String fileName) throws IOException {
|
||||
File file = null;
|
||||
InputStream fin = null;
|
||||
ServletOutputStream out = null;
|
||||
try {
|
||||
file = new File(fileName);
|
||||
fin = new FileInputStream(file);
|
||||
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("application/pdf");
|
||||
// 设置浏览器以下载的方式处理该文件名
|
||||
response.setHeader("Content-Disposition", "attachment;filename="
|
||||
.concat(String.valueOf(URLEncoder.encode(titleName, "UTF-8"))));
|
||||
out = response.getOutputStream();
|
||||
// 缓冲区
|
||||
byte[] buffer = new byte[512];
|
||||
int bytesToRead = -1;
|
||||
// 通过循环将读入的pdf文件的内容输出到浏览器中
|
||||
while ((bytesToRead = fin.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesToRead);
|
||||
}
|
||||
} finally {
|
||||
if (fin != null) {fin.close();}
|
||||
if (out != null) {out.close();}
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportFile(HttpServletRequest request, HttpServletResponse response, String fileName, byte[] decode) throws IOException {
|
||||
InputStream fin = null;
|
||||
ServletOutputStream out = null;
|
||||
try {
|
||||
fin = new ByteArrayInputStream(decode);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
String subfix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
|
||||
if(Objects.equals(subfix,pdf_fix)){
|
||||
response.setContentType("application/pdf");
|
||||
}else if(Objects.equals(subfix,doc_fix) || Objects.equals(subfix,docx_fix)){
|
||||
response.setContentType("application/msword");
|
||||
}
|
||||
// 设置浏览器以下载的方式处理该文件名
|
||||
response.setHeader("Content-Disposition", "attachment;filename="
|
||||
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
|
||||
out = response.getOutputStream();
|
||||
// 缓冲区
|
||||
byte[] buffer = new byte[512];
|
||||
int bytesToRead = -1;
|
||||
// 通过循环将读入的pdf文件的内容输出到浏览器中
|
||||
while ((bytesToRead = fin.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesToRead);
|
||||
}
|
||||
} finally {
|
||||
if (fin != null) {fin.close();}
|
||||
if (out != null) {out.close();}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param outputDir 要下载的文件的绝对路径
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void fileDown(String outputDir,String fileName, HttpServletResponse response) throws IOException {
|
||||
File file = null;
|
||||
FileInputStream is = null;
|
||||
try {
|
||||
response.setContentType("text/html;charset=utf-8");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setHeader("content-disposition", "attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\"");
|
||||
file = new File(outputDir);
|
||||
is = new FileInputStream(file);
|
||||
ServletOutputStream os = response.getOutputStream();
|
||||
IOUtils.copy(is, os);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
if (file != null) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
* @author cw chen
|
||||
* @description 下载word文件
|
||||
* @Param request
|
||||
* @Param response
|
||||
* @Param titleName
|
||||
* @Param fileName
|
||||
* @date 2023-04-17 11:07
|
||||
*/
|
||||
public static void exportWord(HttpServletRequest request, HttpServletResponse response, String titleName, String fileName) throws IOException {
|
||||
File file = null;
|
||||
InputStream fin = null;
|
||||
ServletOutputStream out = null;
|
||||
try {
|
||||
file = new File(fileName);
|
||||
fin = new FileInputStream(file);
|
||||
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("application/msword");
|
||||
// 设置浏览器以下载的方式处理该文件名
|
||||
response.setHeader("Content-Disposition", "attachment;filename="
|
||||
.concat(String.valueOf(URLEncoder.encode(titleName, "UTF-8"))));
|
||||
out = response.getOutputStream();
|
||||
// 缓冲区
|
||||
byte[] buffer = new byte[512];
|
||||
int bytesToRead = -1;
|
||||
// 通过循环将读入的pdf文件的内容输出到浏览器中
|
||||
while ((bytesToRead = fin.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesToRead);
|
||||
}
|
||||
} finally {
|
||||
if (fin != null) {fin.close();}
|
||||
if (out != null) {out.close();}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @author cw chen
|
||||
* @description 下载word文件
|
||||
* @Param request
|
||||
* @Param response
|
||||
* @Param titleName
|
||||
* @Param fileName
|
||||
* @date 2023-04-17 11:07
|
||||
*/
|
||||
public static void exportVideo(HttpServletRequest request, HttpServletResponse response, String titleName, String fileName) throws IOException {
|
||||
File file = null;
|
||||
InputStream fin = null;
|
||||
ServletOutputStream out = null;
|
||||
try {
|
||||
file = new File(fileName);
|
||||
fin = new FileInputStream(file);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("video/mp4");
|
||||
// 设置浏览器以下载的方式处理该文件名
|
||||
response.setHeader("Content-Disposition", "attachment;filename="
|
||||
.concat(String.valueOf(URLEncoder.encode(titleName, "UTF-8"))));
|
||||
out = response.getOutputStream();
|
||||
// 缓冲区
|
||||
byte[] buffer = new byte[512];
|
||||
int bytesToRead = -1;
|
||||
// 通过循环将读入的pdf文件的内容输出到浏览器中
|
||||
while ((bytesToRead = fin.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesToRead);
|
||||
}
|
||||
} finally {
|
||||
if (fin != null) {
|
||||
fin.close();
|
||||
}
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
String filePath = "F:\\File\\guest.txt";
|
||||
Path path = Paths.get(filePath);
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "GBK"))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
// 处理每一行的内容
|
||||
System.out.println(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
// 处理每一行的内容
|
||||
System.out.println(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
byte[] data = Files.readAllBytes(path);
|
||||
String result = new String(data, "GBK-8");
|
||||
System.out.println(result);
|
||||
FileInputStream fis = new FileInputStream(filePath);
|
||||
InputStreamReader isr = new InputStreamReader(fis);
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
String strTmp = "";
|
||||
while((strTmp = br.readLine())!=null){
|
||||
System.out.println(strTmp);
|
||||
}
|
||||
br.close();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ package com.bonus.common.core.utils.global;
|
|||
* 全局变量
|
||||
*/
|
||||
public class SystemGlobal {
|
||||
public final static String TEXT_FIX=".text";
|
||||
/**
|
||||
* true
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ public class LogAspect
|
|||
{
|
||||
// *========数据库日志=========*//
|
||||
SysLogsVo sysLogsVo=new SysLogsVo();
|
||||
sysLogsVo.setOperaTime(DateUtils.getTime());
|
||||
sysLogsVo.setOperTime(DateUtils.getTime());
|
||||
String uuid= UUID.randomUUID().toString().replace("-","").toUpperCase();
|
||||
sysLogsVo.setLogId(uuid);
|
||||
if(jsonResult!=null){
|
||||
|
|
@ -135,7 +135,7 @@ public class LogAspect
|
|||
if (userId!=null && userId!=0L) {
|
||||
sysLogsVo.setUserId(userId.toString());
|
||||
}
|
||||
sysLogsVo.setOperaUri(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
|
||||
sysLogsVo.setOperUri(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
|
||||
sysLogsVo.setTimes(System.currentTimeMillis() - TIME_THREADLOCAL.get()+"");
|
||||
|
||||
// 处理设置注解上的参数
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ public class AuthLogic
|
|||
vo.setModel(result.get("module"));
|
||||
vo.setTitle(result.get("title"));
|
||||
vo.setOperateDetail(result.get("detail"));
|
||||
vo.setOperaTime(DateUtils.getTime());
|
||||
vo.setOperTime(DateUtils.getTime());
|
||||
vo.setOperType(result.get("bussType"));
|
||||
vo.setResultData(result.get("resultData"));
|
||||
vo.setTimes("0");
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
import com.bonus.common.security.annotation.EnableCustomConfig;
|
||||
import com.bonus.common.security.annotation.EnableRyFeignClients;
|
||||
import com.bonus.common.swagger.annotation.EnableCustomSwagger2;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
|
||||
/**
|
||||
* 系统模块
|
||||
|
|
@ -14,7 +15,7 @@ import com.bonus.common.swagger.annotation.EnableCustomSwagger2;
|
|||
@EnableCustomConfig
|
||||
@EnableCustomSwagger2
|
||||
@EnableRyFeignClients
|
||||
@SpringBootApplication
|
||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
||||
public class BonusSystemApplication
|
||||
{
|
||||
public static void main(String[] args)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.bonus.system.controller;
|
|||
|
||||
import com.bonus.common.core.domain.R;
|
||||
//import com.bonus.common.core.utils.WordUtils;
|
||||
import com.bonus.common.core.utils.WordUtils;
|
||||
import com.bonus.common.core.web.controller.BaseController;
|
||||
import com.bonus.common.core.web.domain.AjaxResult;
|
||||
import com.bonus.common.core.web.page.TableDataInfo;
|
||||
|
|
@ -10,6 +11,7 @@ import com.bonus.common.log.enums.OperaType;
|
|||
import com.bonus.common.core.utils.global.SystemGlobal;
|
||||
import com.bonus.system.api.domain.SysLogsVo;
|
||||
//import com.bonus.system.service.ExportSqlService;
|
||||
import com.bonus.system.service.ExportSqlService;
|
||||
import com.bonus.system.service.ISysLogService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
|
@ -37,6 +39,16 @@ public class SysLogController extends BaseController {
|
|||
|
||||
@Resource(name = "ISysLogService")
|
||||
private ISysLogService service;
|
||||
|
||||
/**
|
||||
* 存储的路径
|
||||
*/
|
||||
@Value("${sql.filePath}")
|
||||
private String filePath;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ExportSqlService exportSqlService;
|
||||
// /**
|
||||
// * 存储的路径
|
||||
// */
|
||||
|
|
@ -131,13 +143,13 @@ public class SysLogController extends BaseController {
|
|||
@GetMapping("downloadSysLogs")
|
||||
@SysLog(title = "审计日志", module = "审计日志->系统日志", grade = OperaType.COPY_LOG, details = "系统日志备份", type = "系统日志")
|
||||
public void downloadSysLogs(HttpServletRequest request, HttpServletResponse response) {
|
||||
// try {
|
||||
// String dateTimeNow=exportSqlService.export("0");
|
||||
// String path=filePath + ExportSqlService.TABLE_NAME + dateTimeNow+ SystemGlobal.TEXT_FIX;
|
||||
// WordUtils.fileDown(path, "sys_log"+ dateTimeNow+".sql",response);
|
||||
// } catch (Exception e) {
|
||||
// logger.error("文件下载失败", e);
|
||||
// }
|
||||
try {
|
||||
String dateTimeNow=exportSqlService.export("0");
|
||||
String path=filePath + ExportSqlService.TABLE_NAME + dateTimeNow+ SystemGlobal.TEXT_FIX;
|
||||
WordUtils.fileDown(path, "sys_log"+ dateTimeNow+".sql",response);
|
||||
} catch (Exception e) {
|
||||
logger.error("文件下载失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
package com.bonus.system.service;
|
||||
|
||||
|
||||
import com.bonus.common.core.utils.DateUtils;
|
||||
import com.bonus.common.core.utils.global.SystemGlobal;
|
||||
import com.bonus.system.api.domain.SysLogsVo;
|
||||
import com.bonus.system.mapper.SysLogMapper;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
*/
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class ExportSqlService {
|
||||
|
||||
public static String TABLE_NAME="sys_logs";
|
||||
/**
|
||||
* 存储的路径
|
||||
*/
|
||||
@Value("${sql.filePath}")
|
||||
private String filePath;
|
||||
|
||||
@Resource(name = "SysLogMapper")
|
||||
private SysLogMapper mapper;
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public String export(String logType ) {
|
||||
|
||||
|
||||
|
||||
String dateTimeNow= DateUtils.dateTimeNow();
|
||||
String path=filePath + TABLE_NAME + dateTimeNow;
|
||||
List<SysLogsVo> list=mapper.getLogsLists(logType);
|
||||
// 创建文件并写入
|
||||
try {
|
||||
FileWriter writer = new FileWriter(path+ SystemGlobal.TEXT_FIX);
|
||||
list.forEach(logs->{
|
||||
try {
|
||||
// 根据你的表结构生成你需要的SQL行
|
||||
String rowSql = "INSERT INTO sys_logs (log_id, opera_user_name,ip,user_id,model" +
|
||||
",oper_time,method,params,operate_detail,oper_type,oper_uri,log_type,result,times,failure_reason,grade,err_type,method_type,title) VALUES ('"
|
||||
+ isNotNull(logs.getLogId())+ "', '"
|
||||
+isNotNull(logs.getOperaUserName())+ "', '"
|
||||
+isNotNull(logs.getIp() )+ "', '"
|
||||
+ isNotNull( logs.getUserId()) + "', '"
|
||||
+ isNotNull( logs.getModel() )+ "', '"
|
||||
+ isNotNull( logs.getOperTime() ) + "', '"
|
||||
+isNotNull( logs.getMethod())+ "', '"
|
||||
+ isNotNull(logs.getParams()) + "', '"
|
||||
+isNotNull( logs.getOperateDetail()) + "', '"
|
||||
+isNotNull(logs.getOperType() )+ "', '"
|
||||
+isNotNull( logs.getOperUri()) + "', '"
|
||||
+isNotNull(logs.getLogType() )+ "', '"
|
||||
+ isNotNull(logs.getFailureReason())+ "', '"
|
||||
+isNotNull(logs.getTimes()) + "', '"
|
||||
+ isNotNull(logs.getFailureReason()) + "', '"
|
||||
+isNotNull( logs.getGrade()) + "', '"
|
||||
+isNotNull(logs.getErrType()) + "', '"
|
||||
+ isNotNull(logs.getMethod()) + "', '"+
|
||||
isNotNull(logs.getTitle())+ "');";
|
||||
writer.write(rowSql + System.lineSeparator());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}catch (Exception e){
|
||||
log.error(e.toString(),e);
|
||||
}
|
||||
|
||||
return dateTimeNow;
|
||||
}
|
||||
|
||||
public String isNotNull(Object object){
|
||||
if(object==null){
|
||||
return "";
|
||||
}
|
||||
return object.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ public class SysLogServiceImpl implements ISysLogService {
|
|||
// }
|
||||
//如果是异常日志
|
||||
if(SystemGlobal.LOG_ERR.equals(sysLog.getErrType()) && StringUtils.isEmpty(sysLog.getModel())) {
|
||||
SysLogsVo sysLog1=mapper.getModule(sysLog.getOperaUri());
|
||||
SysLogsVo sysLog1=mapper.getModule(sysLog.getOperUri());
|
||||
if(sysLog1!=null){
|
||||
sysLog.setModel(sysLog1.getModel());
|
||||
sysLog.setOperateDetail(sysLog1.getOperateDetail());
|
||||
|
|
@ -82,7 +82,7 @@ public class SysLogServiceImpl implements ISysLogService {
|
|||
String module=mapper.getModuleName(sysLog);
|
||||
sysLog.setLogType(2);
|
||||
sysLog.setResult("失败");
|
||||
sysLog.setOperaTime(DateUtils.getTime());
|
||||
sysLog.setOperTime(DateUtils.getTime());
|
||||
sysLog.setModel(module);
|
||||
LoginUser user= SecurityUtils.getLoginUser();
|
||||
sysLog.setUserId(String.valueOf(user.getUserid()));
|
||||
|
|
@ -103,14 +103,13 @@ public class SysLogServiceImpl implements ISysLogService {
|
|||
@Override
|
||||
public List<SysLogsVo> getSystemLogs(SysLogsVo dto) {
|
||||
try{
|
||||
//// weiweiw
|
||||
// if (StringUtils.isEmpty(dto.getOperaTime())) {
|
||||
// dto.setStartTime(DateTimeHelper.getNowDay());
|
||||
// dto.setEndTime(DateTimeHelper.getNowDay());
|
||||
// }else {
|
||||
// dto.setStartTime(dto.getOperTime().split(" - ")[0].trim());
|
||||
// dto.setEndTime(dto.getOperTime().split(" - ")[1].trim());
|
||||
// }
|
||||
if (StringUtils.isEmpty(dto.getOperTime())) {
|
||||
dto.setStartTime(DateUtils.dateTimeNow());
|
||||
dto.setEndTime(DateUtils.dateTimeNow());
|
||||
}else {
|
||||
dto.setStartTime(dto.getOperTime().split(" - ")[0].trim());
|
||||
dto.setEndTime(dto.getOperTime().split(" - ")[1].trim());
|
||||
}
|
||||
return mapper.getSystemLogs(dto);
|
||||
}catch (Exception e){
|
||||
log.error(e.toString(),e);
|
||||
|
|
|
|||
|
|
@ -1,74 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="logs/bonus-system" />
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<configuration>
|
||||
<springProperty name="logFile" source="log.file"/>
|
||||
<springProperty name="rootlevel" source="log.level.root"/>
|
||||
<springProperty name="mylevel" source="log.level.my"/>
|
||||
<springProperty name="maxFileSize" source="log.maxsize"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统日志输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/info.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/error.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
<pattern>%d [%thread] %-5level %logger{50} -[%file:%line]- %msg%n
|
||||
</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="adminLog"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${logFile}</file>
|
||||
<encoder>
|
||||
<pattern>%d [%thread] %-5level -[%file:%line]- %msg%n
|
||||
</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${logFile}.%d{yyyy-MM-dd}.%i</fileNamePattern>
|
||||
<maxFileSize>30MB</maxFileSize>
|
||||
<!-- 每产生一个日志文件,该日志文件的保存期限为15天 -->
|
||||
<maxHistory>15</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<appender name="errorLog"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${logFile}.error</file>
|
||||
<encoder>
|
||||
<pattern>%d [%thread] %-5level %logger{36} -[%file:%line]- %msg%n
|
||||
</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${logFile}.error.%d{yyyy-MM-dd}.%i</fileNamePattern>
|
||||
<maxFileSize>30MB</maxFileSize>
|
||||
<!-- 每产生一个日志文件,该日志文件的保存期限为15天 -->
|
||||
<maxHistory>15</maxHistory>
|
||||
</rollingPolicy>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<level>error</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 系统模块日志级别控制 -->
|
||||
<logger name="com.bonus" level="info" />
|
||||
<!-- Spring日志级别控制 -->
|
||||
<logger name="org.springframework" level="warn" />
|
||||
<appender name="sqlLog"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${logFile}.sql</file>
|
||||
<encoder>
|
||||
<pattern>%d [%thread] %msg%n
|
||||
</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${logFile}.sql.%d{yyyy-MM-dd}.%i</fileNamePattern>
|
||||
<maxFileSize>30MB</maxFileSize>
|
||||
<!-- 每产生一个日志文件,该日志文件的保存期限为15天 -->
|
||||
<maxHistory>15</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="file_info" />
|
||||
<appender-ref ref="file_error" />
|
||||
<logger name="adminLogger" level="${mylevel}" additivity="true">
|
||||
<appender-ref ref="adminLog"/>
|
||||
</logger>
|
||||
|
||||
<logger name="com.bonus.system" level="DEBUG" additivity="true">
|
||||
<appender-ref ref="sqlLog"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.scheduling.quartz" level="error" additivity="true">
|
||||
<appender-ref ref="adminLog"/>
|
||||
</logger>
|
||||
|
||||
<root level="${rootlevel}">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="errorLog"/>
|
||||
</root>
|
||||
</configuration>
|
||||
|
||||
</configuration>
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
method_type,title,result_data
|
||||
)values (
|
||||
#{logId},#{operaUserName},#{ip},#{userId},
|
||||
#{model},#{operaTime},#{method},#{params},
|
||||
#{operateDetail},#{operaType},#{operaUri},
|
||||
#{model},#{operTime},#{method},#{params},
|
||||
#{operateDetail},#{operaType},#{operUri},
|
||||
#{logType},#{result},#{times},
|
||||
#{failureReason},#{grade},#{errType},
|
||||
#{methodType},#{title},#{resultData}
|
||||
|
|
@ -69,12 +69,25 @@
|
|||
update sys_logs_set set capacity=#{capacity}
|
||||
</update>
|
||||
<select id="getSystemLogs" resultType="com.bonus.system.api.domain.SysLogsVo">
|
||||
SELECT log_id,opera_user_name operaUserName,ip,user_id userId,model,
|
||||
oper_time operTime,method,params,
|
||||
operate_detail operateDetail,oper_type operType,oper_uri operUri,
|
||||
log_type logType,failure_reason failureReason,grade,
|
||||
err_type errType,method_type methodType,times
|
||||
from sys_logs
|
||||
SELECT
|
||||
log_id,
|
||||
opera_user_name operaUserName,
|
||||
ip,
|
||||
user_id userId,
|
||||
model,
|
||||
oper_time operTime,
|
||||
method,
|
||||
params,
|
||||
operate_detail operateDetail,
|
||||
oper_type operType,
|
||||
oper_uri operUri,
|
||||
log_type logType,
|
||||
result,
|
||||
grade,
|
||||
err_type errType,
|
||||
method_type methodType,
|
||||
times
|
||||
from sys_logs
|
||||
where log_type=#{logType}
|
||||
<if test="operaUserName!=null and operaUserName!=''">
|
||||
and opera_user_name LIKE concat('%',#{operaUserName},'%')
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
method_type,title,result_data
|
||||
)values (
|
||||
#{logId},#{operaUserName},#{ip},#{userId},
|
||||
#{model},#{operaTime},#{method},#{params},
|
||||
#{operateDetail},#{operType},#{operaUri},
|
||||
#{model},#{operTime},#{method},#{params},
|
||||
#{operateDetail},#{operType},#{operUri},
|
||||
#{logType},#{result},#{times},
|
||||
#{failureReason},#{grade},#{errType},
|
||||
#{methodType},#{title},#{resultData}
|
||||
|
|
|
|||
Loading…
Reference in New Issue