【新增】浏览器、mysql、文件夹判分,监控管理后台接口

This commit is contained in:
YOHO\20373
2025-05-05 00:01:11 +08:00
parent 3a0886b94a
commit a789277819
55 changed files with 3146 additions and 376 deletions

View File

@@ -7,6 +7,9 @@ import org.springframework.web.bind.annotation.RestController;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.module.judgement.controller.service.mysql.IMysqlServerice;
import java.io.IOException;
import java.sql.SQLException;
@RestController
@RequestMapping("/tool/Mysql")
public class MysqlController {
@@ -16,12 +19,14 @@ public class MysqlController {
@Autowired
private IMysqlServerice mysqlServerice;
/**
* Mysql判分
* @return 得分
*/
@PostMapping("/run_judgement")
public CommonResult run_C_code() {
public CommonResult run_C_code() throws SQLException, IOException {
return CommonResult.success(mysqlServerice.Judgement());
}

View File

@@ -20,22 +20,14 @@ public class WindowsFileController {
@Autowired
private IFileServerice fileServerice;
/**
* 得出文件操作考点
* @return 得分
*/
// @PostMapping("/get_filePoint")
//todo 后期需要素材文件和答案文件的 父目录 如D:/exam/3/shucai,D:/exam/3/win
public CommonResult get_file_point() throws IOException {
return CommonResult.success(fileServerice.get_file_point());
}
/**
* 文件操作题判分
* @return 判分
*/
@PostMapping("/run_file")
@PostMapping("/run_judgement")
public CommonResult run_file_point() throws IOException {
//"权值得分比重"
return CommonResult.success(fileServerice.run_file_point());

View File

@@ -4,8 +4,10 @@ import org.springframework.stereotype.Service;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import pc.exam.pp.module.judgement.controller.utils.brower.BookmarkChecker;
import pc.exam.pp.module.judgement.controller.utils.brower.BookmarkDeleter;
import pc.exam.pp.module.judgement.controller.utils.file.GetDifferencesBetweenFolders;
import pc.exam.pp.module.exam.utils.file.GetDifferencesBetweenFolders;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -14,6 +16,7 @@ import java.util.Map;
@Service
public class BrowserServericeImpl implements IBrowserServerice {
static String answerLogPath = "answerLogBrower.txt"; // 文件路径
//考生试题文件夹
static final String BASE_DIR = "D:/exam/4/";
//谷歌浏览器
@@ -51,6 +54,12 @@ public class BrowserServericeImpl implements IBrowserServerice {
//根据路径,得到考生答题文件集合
Map<String, String> stuFiles = GetDifferencesBetweenFolders.listFilesAndFoldersWithAttributes(Paths.get(BASE_DIR));
// 输出学生提交的内容
appendToFile(answerLogPath,"=== 学生提交内容stu 目录) ===");
stuFiles.forEach((key, value) -> appendToFile(answerLogPath,key + " -> " + value));
appendToFile(answerLogPath,"=== 学生提交内容得分点 ===");
// 对比学生提交内容与试题得分点
//这里指挥判断存在文件夹的得分点
Integer studentScore = compareStuAndTestFiles(answerList, stuFiles);
@@ -96,13 +105,29 @@ public class BrowserServericeImpl implements IBrowserServerice {
// 如果正确,则累加总分
if (isCorrect) {
totalScore += currentScore;
System.out.println(answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
appendToFile(answerLogPath,"考点"+answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
}else {
System.out.println(answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
appendToFile(answerLogPath,"考点"+answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
}
}
//返回累加的得分点
return totalScore;
}
/**
* 将指定内容追加写入到指定文件中。
*
* @param filePath 文件路径
* @param content 要写入的内容
*/
public static void appendToFile(String filePath, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
writer.write(content);
writer.newLine(); // 可选:添加换行符
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -2,8 +2,10 @@ package pc.exam.pp.module.judgement.controller.service.file;
import org.springframework.stereotype.Service;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import pc.exam.pp.module.judgement.controller.utils.file.GetDifferencesBetweenFolders;
import pc.exam.pp.module.exam.utils.file.GetDifferencesBetweenFolders;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -17,41 +19,7 @@ import java.util.stream.Collectors;
@Service
public class FileServericeImpl implements IFileServerice {
static final String BASE_DIR = "D:/exam/3/";
@Override
public List<ExamQuestionAnswer> get_file_point() throws IOException {
List<ExamQuestionAnswer> answerList = new ArrayList<>();
AtomicInteger sortCounter = new AtomicInteger(1); // 计数器
String path1 = BASE_DIR + "shucai";
String path2 = BASE_DIR + "win";
// 获取 shucai 和 win 文件夹的差异
Map<String, String> differences = GetDifferencesBetweenFolders.getDifferencesBetweenFolders(path1, path2);
List<ExamQuestionAnswer> formattedDifferences = differences.entrySet().stream()
.map(entry -> {
String key = entry.getKey();
String value = entry.getValue();
ExamQuestionAnswer answer = new ExamQuestionAnswer();
answer.setContent(key); // 设置文件路径
answer.setScoreRate("1");
//这里设置answer的排序按照循环次数来
answer.setSort(String.valueOf(sortCounter.getAndIncrement())); // 按顺序设置排序值
if (value.startsWith("仅存在于 "+path1)) {
answer.setContentIn("考察删除");
} else if (value.startsWith("仅存在于 "+path2)) {
answer.setContentIn("考察名称");
} else if (value.startsWith("属性不同")) {
answer.setContentIn("考察属性");
// answer.setContent(key + " -> " + value.split(" vs ")[1]); // 设置属性信息
}
return answer;
})
.sorted(Comparator.comparingInt(answer -> Integer.parseInt(answer.getSort()))) // 按 sort 排序
.collect(Collectors.toList());
answerList.addAll(formattedDifferences);
return answerList;
}
static String answerLogPath = "answerLogFile.txt"; // 文件路径
@Override
public String run_file_point() throws IOException {
@@ -68,9 +36,12 @@ public class FileServericeImpl implements IFileServerice {
Map<String, String> stuFiles = GetDifferencesBetweenFolders.listFilesAndFoldersWithAttributes(Paths.get( stuPath));
// 输出学生提交的内容
System.out.println("\n=== 学生提交内容stu 目录) ===");
stuFiles.forEach((key, value) -> System.out.println(key + " -> " + value));
System.out.println("\n=== 学生提交内容得分点 ===");
appendToFile(answerLogPath,"=== 学生提交内容stu 目录) ===");
stuFiles.forEach((key, value) -> appendToFile(answerLogPath,key + " -> " + value));
appendToFile(answerLogPath,"=== 学生提交内容得分点 ===");
// 对比学生提交内容与试题得分点
Integer studentScore = compareStuAndTestFiles(answerList, stuFiles);
@@ -113,14 +84,28 @@ public class FileServericeImpl implements IFileServerice {
// 如果正确,则累加总分
if (isCorrect) {
totalScore += currentScore;
System.out.println(answer.getContent() + " -> " + answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
appendToFile(answerLogPath,answer.getContent() + " -> " + answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
}else {
System.out.println(answer.getContent() + " -> " + answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
appendToFile(answerLogPath,answer.getContent() + " -> " + answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
}
}
//返回累加的总分
return totalScore;
}
/**
* 将指定内容追加写入到指定文件中。
*
* @param filePath 文件路径
* @param content 要写入的内容
*/
public static void appendToFile(String filePath, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
writer.write(content);
writer.newLine(); // 可选:添加换行符
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -9,7 +9,7 @@ import java.util.List;
public interface IFileServerice {
List<ExamQuestionAnswer> get_file_point() throws IOException;
String run_file_point() throws IOException;

View File

@@ -1,8 +1,18 @@
package pc.exam.pp.module.judgement.controller.service.mysql;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public interface IMysqlServerice {
int Judgement();
AtomicInteger Judgement() throws IOException, SQLException;
}

View File

@@ -29,11 +29,14 @@ public class MySQLExporterUtil {
}
try (Connection conn = DriverManager.getConnection(jdbcUrl, user, password);
FileWriter writer = new FileWriter(outputFile)) {
// 连接数据库
switchDatabase(conn);
// 导出表结构
exportTables(conn, writer);
// 导出视图结构
exportViews(conn, writer);
// 导出存储过程
exportProcedures(conn, writer);
System.out.println("导出成功!文件路径: " + outputFile);
} catch (Exception e) {
e.printStackTrace();
@@ -119,5 +122,23 @@ public class MySQLExporterUtil {
}
}
private void exportProcedures(Connection conn, FileWriter writer) throws SQLException, IOException {
DatabaseMetaData meta = conn.getMetaData();
try (ResultSet procedures = meta.getProcedures(databaseName, null, "%")) {
while (procedures.next()) {
String procedureName = procedures.getString("PROCEDURE_NAME");
writer.write(getCreateProcedureSQL(conn, procedureName) + ";\n\n");
}
}
}
private String getCreateProcedureSQL(Connection conn, String procedureName) throws SQLException {
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SHOW CREATE PROCEDURE " + procedureName)) {
if (rs.next()) {
return rs.getString("Create Procedure");
}
return "";
}
}
}

View File

@@ -4,6 +4,10 @@ import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.MalformedInputException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -16,13 +20,38 @@ public class SqlFileProcessor {
public static Map<String, List<String>> processSqlFile(String filePath) throws IOException {
List<String> sqlStatements = readSQLFromFile(filePath);
//查找语句
List<String> selectStatements = new ArrayList<>();
//删除语句
List<String> delStatements = new ArrayList<>();
//视图
List<String> viewStatements = new ArrayList<>();
//其他(建表,新增。修改)
List<String> otherStatements = new ArrayList<>();
//触发器
List<String> triggerStatements = new ArrayList<>();
//存储过程
List<String> procedureStatements = new ArrayList<>();
for (String sql : sqlStatements) {
if (sql.trim().toUpperCase().startsWith("SELECT")) {
selectStatements.add(sql);
} else {
}else if ( sql.toUpperCase().contains("TRIGGER")) {
triggerStatements.add(sql);
}
else if ( sql.toUpperCase().contains("PROCEDURE")) {
procedureStatements.add(sql);
}
else if (sql.trim().toUpperCase().startsWith("DELETE")){
delStatements.add(sql);
}else if (sql.trim().replaceAll("\\s+", " ").matches("(?i)^CREATE( OR REPLACE)?( ALGORITHM\\s*=\\s*\\w+)?( DEFINER\\s*=\\s*[`\"'\\w@%\\.]+)?( SQL SECURITY \\w+)? VIEW\\b.*")) {
// 把视图语句加到 viewStatements 集合里
viewStatements.add(sql);
}
else
{
otherStatements.add(sql);
}
}
@@ -30,44 +59,61 @@ public class SqlFileProcessor {
Map<String, List<String>> result = new HashMap<>();
result.put("SELECT", selectStatements);
result.put("OTHER", otherStatements);
result.put("TRIGGER", triggerStatements);
result.put("PROCEDURE", procedureStatements);
result.put("VIEW", viewStatements);
result.put("DELETE", delStatements);
return result;
}
private static List<String> readSQLFromFile(String filePath) throws IOException {
List<String> sqlStatements = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"))) {
StringBuilder sqlStatement = new StringBuilder();
String line;
boolean insideBlockComment = false;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.contains("/*")) {
insideBlockComment = true;
line = line.split("/\\*")[0].trim();
}
if (line.contains("*/")) {
insideBlockComment = false;
line = line.split("\\*/")[1].trim();
}
List<String> lines = readFileAutoCharset(filePath);
List<String> sqlList = parseSql(lines);
if (line.startsWith("--") || line.isEmpty() || insideBlockComment) {
continue;
}
sqlStatement.append(line).append(" ");
if (line.endsWith(";")) {
sqlStatements.add(sqlStatement.toString().trim());
sqlStatement.setLength(0);
}
for (String sql : sqlList) {
System.out.println(sql);
}
if (sqlStatement.length() > 0) {
sqlStatements.add(sqlStatement.toString().trim());
}
return sqlList;
}
// 自动识别 UTF-8 or GBK
private static List<String> readFileAutoCharset(String filePath) throws IOException {
try {
// 优先尝试 UTF-8
return Files.readAllLines(Paths.get(filePath), Charset.forName("UTF-8"));
} catch (MalformedInputException e) {
// 如果UTF-8失败再尝试GBK
System.out.println("文件不是UTF-8编码尝试使用GBK编码读取...");
return Files.readAllLines(Paths.get(filePath), Charset.forName("GBK"));
}
return sqlStatements;
}
// 解析SQL去掉注释只保留SQL语句
private static List<String> parseSql(List<String> lines) {
List<String> sqlList = new ArrayList<>();
StringBuilder currentSql = new StringBuilder();
for (String line : lines) {
line = line.trim();
if (line.startsWith("--")) {
// 遇到新的注释(比如 -- 1.先把之前的SQL收进去
if (currentSql.length() > 0) {
sqlList.add(currentSql.toString().trim());
currentSql.setLength(0);
}
continue; // 注释行不用管
}
// 累加 SQL 内容
currentSql.append(line).append("\n");
}
if (currentSql.length() > 0) {
sqlList.add(currentSql.toString().trim());
}
return sqlList;
}
}

View File

@@ -1,91 +0,0 @@
package pc.exam.pp.module.judgement.controller.utils.file;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 获取文件夹差异工具类
*/
public class GetDifferencesBetweenFolders {
// 获取两个文件夹的差异
public static Map<String, String> getDifferencesBetweenFolders( String folder1, String folder2) throws IOException {
Path path1 = Paths.get(folder1);
Path path2 = Paths.get( folder2);
Map<String, String> files1 = listFilesAndFoldersWithAttributes(path1);
Map<String, String> files2 = listFilesAndFoldersWithAttributes(path2);
Map<String, String> differences = new LinkedHashMap<>();
// 找出仅存在于 folder1 的文件
for (String file : files1.keySet()) {
if (!files2.containsKey(file)) {
differences.put(file, "仅存在于 " + folder1);
} else {
String file1Attributes = files1.get(file);
String file2Attributes = files2.get(file);
if (!file1Attributes.equals(file2Attributes)) {
differences.put(file, "属性不同: " + file1Attributes + " vs " + file2Attributes);
}
}
}
// 找出仅存在于 folder2 的文件
for (String file : files2.keySet()) {
if (!files1.containsKey(file)) {
differences.put(file, "仅存在于 " + folder2);
}
}
return differences;
}
// 列出文件夹下的所有文件及其属性
public static Map<String, String> listFilesAndFoldersWithAttributes(Path folder) throws IOException {
if (!Files.exists(folder)) return Collections.emptyMap();
try (Stream<Path> stream = Files.walk(folder)) {
return stream.collect(Collectors.toMap(
path -> folder.relativize(path).toString(),
GetDifferencesBetweenFolders::getFileAttributes,
(a, b) -> a,
LinkedHashMap::new
));
}
}
// 在 getFileAttributes 方法中,只返回文件的属性,如果是文件夹则返回特殊标识
static String getFileAttributes(Path path) {
try {
if (Files.isDirectory(path)) {
return "文件夹"; // 特别标记为文件夹
} else {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
boolean isHidden = Files.isHidden(path);
boolean isReadable = Files.isReadable(path);
boolean isWritable = Files.isWritable(path);
return String.format("大小: %dB, 隐藏: %b, 可读: %b, 可写: %b",
attrs.size(), isHidden, isReadable, isWritable);
}
} catch (IOException e) {
return "无法获取属性";
}
}
}

View File

@@ -0,0 +1,39 @@
package pc.exam.pp.module.judgement.domain;
public class SqlExecutionResult {
private String sqlStatement;
private String backupFile;
private boolean isValid;
public SqlExecutionResult(String sqlStatement, String backupFile) {
this.sqlStatement = sqlStatement;
this.backupFile = backupFile;
this.isValid = false; // 默认执行完后再判断
}
public String getSqlStatement() {
return sqlStatement;
}
public String getBackupFile() {
return backupFile;
}
public boolean isValid() {
return isValid;
}
public void setValid(boolean valid) {
isValid = valid;
}
@Override
public String toString() {
return "SqlExecutionResult{" +
"sqlStatement='" + sqlStatement + '\'' +
", backupFile='" + backupFile + '\'' +
", isValid=" + isValid +
'}';
}
}