项目场景:
作业的发布,打回 。 学生端做作业
由作业的state来确定作业是否上交,批改,打回作业。
实体类的建立,还有各种成员变量的设计要满足需求
问题描述
问题:
在进行上传作业后,老师端批改作业,并作出评论,这所有的信息我全部都写在一张表里面,导致自己的思维有点混乱。这里应该把老师的批改单独建立一张表,进行存储数据。
c
这里建立实体类就是传递数据,客户端与服务端的交互数据传值就比乱,
原因分析:
提示:因为状态不同导致,有些传值就只有一些有效值存在,其它值没有传递,但是有时候,在后面又会再次使用
比如前面查询时只有id,而后面需要一个name,这时就需要单独又要去请求一遍
解决方案:
实体类:作业:进行找值,还有进行赋值,传值,就比较方便
java
package com.test.po;
import java.io.Serializable;
import java.time.LocalDateTime;
public class MyWork implements Serializable {
private int id;
private int classId;
private int student_id;
private int state; //1:已提交 2:未批改 3:已批改 4:已打回
private String answer;
private String question;
private LocalDateTime start_time;
private LocalDateTime end_time;
private int score;
private String StudentName;
private String teacher_reply;
private String workName;
public String getWorkName() {
return workName;
}
public void setWorkName(String workName) {
this.workName = workName;
}
public String getTeacher_reply() {
return teacher_reply;
}
public void setTeacher_reply(String teacher_reply) {
this.teacher_reply = teacher_reply;
}
public LocalDateTime getStart_time() {
return start_time;
}
public void setStart_time(LocalDateTime start_time) {
this.start_time = start_time;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return StudentName;
}
public void setStudentName(String studentName) {
StudentName = studentName;
}
public int getClassId() {
return classId;
}
public void setClassId(int classId) {
this.classId = classId;
}
public int getStudent_id() {
return student_id;
}
public void setStudent_id(int student_id) {
this.student_id = student_id;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public LocalDateTime getEnd_time() {
return end_time;
}
public void setEnd_time(LocalDateTime end_time) {
this.end_time = end_time;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
班级资源的下载
当学生点击下载后,弹出选择文件地址,因为进行下载文件,需要文件分片下载,并且下载文件时需要单独的线程,否则会堵塞。因为采用的长连接,最方便的就是采用一个新的socket。
package com.test.controller; import com.test.Util.SocketUtil; import com.test.common.Message; import com.test.common.MessageType; import com.test.po.MyFile; import com.test.po.MyLargerFile; import javafx.application.Platform; import java.io.*; import java.net.Socket; import java.nio.file.Files; public class MyFileRunnable implements Runnable { private Socket socket; private File file; public int state; public int flag = 0; public MyFileRunnable(Socket socket, File file) { this.socket = socket; this.file = file; } @Override public void run() { // 假设分片存储目录 File storageDirectory = new File(file.getParent(), "chunks"); while (!socket.isClosed()) { try { Message responseMessage = SocketUtil.getSocketUtil().getMessage(socket); switch (responseMessage.getMessageType()) { case MessageType.stu_download_file_start -> { MyLargerFile myLargerFile = (MyLargerFile) responseMessage.getData(); MyFile myFile = myLargerFile.getMyFile(); // 假设分片信息存储在MyFile中,包括分片总数和当前分片序号 int totalChunks = myLargerFile.getTotalSlices(); int chunkNumber = myLargerFile.getState(); // 假设这个方法存在 // 创建分片存储目录 if (!storageDirectory.exists()) { storageDirectory.mkdirs(); } // 存储分片 File chunkFile = new File(storageDirectory, "chunk_" + chunkNumber); myFile.writeFileData(chunkFile); //进行更新ui Platform.runLater(()->{ ControllerManager.stuClassIfoController.stringStuIfoPaneControllerHashMap.get(myLargerFile.getMd5()).update(myLargerFile); }); // 检查是否所有分片都已下载 if (areAllChunksDownloaded(storageDirectory, totalChunks)) { // 合并分片 mergeChunks(storageDirectory, file, totalChunks); System.out.println("文件下载完成"); return; } } } } catch (Exception e) { e.printStackTrace(); return; } } } private boolean areAllChunksDownloaded(File directory, int totalChunks) { for (int i = 1; i <= totalChunks; i++) { File chunkFile = new File(directory, "chunk_" + i); if (!chunkFile.exists()) { return false; } } return true; } private void mergeChunks(File directory, File outputFile, int totalChunks) throws IOException { try (FileOutputStream fos = new FileOutputStream(outputFile, true); BufferedOutputStream mergingStream = new BufferedOutputStream(fos)) { for (int i = 1; i <= totalChunks; i++) { File chunkFile = new File(directory, "chunk_" + i); Files.copy(chunkFile.toPath(), mergingStream); // 删除分片文件,如果需要的话 // chunkFile.delete(); } } } }
这个先进行文件分片的下载,当下载完成之后,再进行执行合并文件。并关闭这个线程。
服务端进行文件上传我也采用了多线程进行执行上传文件:
case MessageType.stu_download_file -> {
MyLargerFile myLargerFile = (MyLargerFile) requestMessage.getData();
String md5 = myLargerFile.getMd5();
MyLargerFile my= MyFileDAO.queryFile(md5);
String dir = my.getPath();
File[] files = new File(dir).listFiles();
if (files == null) {
System.out.println("文件目录不存在");
return;
}
int len = files.length;
Arrays.sort(files, (f1, f2) -> {
// 分割文件名,获取分片编号部分
String[] parts1 = f1.getName().split("\\.part");
String[] parts2 = f2.getName().split("\\.part");
// 提取并解析分片编号
int part1 = Integer.parseInt(parts1[1]);
int part2 = Integer.parseInt(parts2[1]);
// 比较分片编号
return Integer.compare(part1, part2);
});
new Thread(()->{
int index = 1;
for (File file : files) {
MyFile myFile = new MyFile();
myFile.readFileData(file);
MyLargerFile myLargerFile1 = new MyLargerFile();
myLargerFile1.setMyFile(myFile);
myLargerFile1.setState(index);
myLargerFile1.setTotalSlices(len);
myLargerFile1.setMd5(md5);
Message message = new Message();
message.setData(myLargerFile1);
message.setMessageType(MessageType.stu_download_file_start);
try {
SocketUtil.getSocketUtil().sendMessage(socket,message);
} catch (IOException e) {
throw new RuntimeException(e);
}
index++;
}
}).start();
}
在这种情况下,进行传递文件数据。然后读写文件。