refactor: 移除Hibernate依赖并重构代理对象初始化检查逻辑

feat(controller): 新增多个任务类用于合同和客户相关操作
feat(service): 新增ProxyUtils工具类替代Hibernate.isInitialized检查
refactor(controller): 重构多个控制器和皮肤类,使用ProxyUtils替代Hibernate
refactor(service): 重构服务类,移除Hibernate依赖并优化方法实现
fix(controller): 修复表格单元格初始化逻辑,确保代理对象正确加载
chore: 更新项目版本号至0.0.58-SNAPSHOT
docs: 添加MyProperties类用于管理下载路径配置
This commit is contained in:
2025-09-06 17:22:12 +08:00
parent effd7b103c
commit 3b90db0450
100 changed files with 1251 additions and 995 deletions

View File

@@ -0,0 +1,470 @@
package com.ecep.contract.controller;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import com.ecep.contract.Desktop;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import lombok.Setter;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.FormBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class OkHttpLoginController implements MessageHolder {
private static final Logger logger = LoggerFactory.getLogger(OkHttpLoginController.class);
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
@Setter
private MessageHolder holder;
@Setter
private Stage primaryStage;
@Setter
private Properties properties;
private OkHttpClient httpClient;
private WebSocket webSocket;
private String serverUrl;
private String webSocketUrl;
public OkHttpLoginController() {
this.httpClient = new OkHttpClient();
}
@Override
public void addMessage(Level level, String message) {
if (holder != null) {
holder.addMessage(level, message);
}
}
private void initServerUrls() {
String host = properties.getProperty("server.host", "localhost");
String port = properties.getProperty("server.port", "8080");
this.serverUrl = "http://" + host + ":" + port;
this.webSocketUrl = "ws://" + host + ":" + port + "/ws";
}
public void tryLogin() {
initServerUrls();
// 检查配置文件中是否保存用户名和密码
String userName = getUserName();
String password = getPassword();
if (StringUtils.hasText(userName) && StringUtils.hasText(password)) {
login(userName, password);
} else {
Platform.runLater(() -> {
showLoginDialog();
});
}
}
private String getUserName() {
return properties.getProperty("user.name", "");
}
private String getPassword() {
return properties.getProperty("user.password", "");
}
private void showLoginDialog() {
Stage stage = new Stage();
stage.initOwner(primaryStage);
stage.setTitle("系统登录");
// 创建 BorderPane 并设置边距
BorderPane borderPane = new BorderPane();
borderPane.setPadding(new Insets(20));
// 创建布局
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(15);
// 账户输入框
Label userLabel = new Label("用户名:");
TextField userField = new TextField();
{
String username = getUserName();
if (StringUtils.hasText(username)) {
userField.setText(username);
}
grid.add(userLabel, 0, 0);
grid.add(userField, 1, 0);
}
// 密码输入框
Label passwordLabel = new Label("密码:");
PasswordField passwordField = new PasswordField();
{
String password = getPassword();
if (StringUtils.hasText(password)) {
passwordField.setText(password);
}
grid.add(passwordLabel, 0, 1);
grid.add(passwordField, 1, 1);
}
// 记住密码复选框
CheckBox rememberCheckBox = new CheckBox("记住密码");
{
String property = properties.getProperty("remember.password", "false");
if (Boolean.parseBoolean(property)) {
rememberCheckBox.setSelected(true);
}
}
grid.add(rememberCheckBox, 1, 2);
// 错误消息提示
Label errorLabel = new Label();
errorLabel.setStyle("-fx-text-fill: red;");
errorLabel.setVisible(false);
grid.add(errorLabel, 0, 3);
GridPane.setColumnSpan(errorLabel, 2);
borderPane.setCenter(grid);
// 登录按钮
Button loginButton = new Button("登录");
loginButton.setDefaultButton(true);
loginButton.setPrefWidth(100);
borderPane.setBottom(loginButton);
BorderPane.setAlignment(loginButton, javafx.geometry.Pos.CENTER);
BorderPane.setMargin(loginButton, new Insets(20, 0, 0, 0));
// 登录按钮点击事件
loginButton.setOnAction(event -> {
String username = userField.getText();
String password = passwordField.getText();
boolean remember = rememberCheckBox.isSelected();
if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
errorLabel.setText("用户名和密码不能为空");
errorLabel.setVisible(true);
return;
}
errorLabel.setVisible(false);
// 保存配置
properties.setProperty("user.name", username);
if (remember) {
properties.setProperty("user.password", password);
properties.setProperty("remember.password", "true");
} else {
properties.setProperty("user.password", "");
properties.setProperty("remember.password", "false");
}
// 执行登录
login(username, password);
stage.close();
});
// 创建场景并设置到窗口
Scene scene = new Scene(borderPane, 400, 280);
stage.setScene(scene);
stage.setResizable(false);
stage.showAndWait();
}
private void login(String username, String password) {
info("正在连接服务器: " + serverUrl);
try {
// 构建表单格式的登录请求
RequestBody body = new FormBody.Builder()
.add("username", username)
.add("password", password)
.build();
Request request = new Request.Builder()
.url(serverUrl + "/login")
.post(body)
.build();
httpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Platform.runLater(() -> {
error("登录失败: 无法连接到服务器 - " + e.getMessage());
showError("登录失败", "无法连接到服务器,请检查网络连接或服务器配置。");
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
Platform.runLater(() -> {
error("登录失败: 服务器返回错误码 - " + response.code());
showError("登录失败", "用户名或密码错误,或服务器暂时不可用。");
});
return;
}
try {
// 解析登录响应
String responseBody = response.body().string();
logger.debug("登录响应: " + responseBody);
// 这里需要根据实际的响应格式解析数据
// 假设响应包含employeeId和sessionId
int employeeId = extractEmployeeId(responseBody);
int sessionId = extractSessionId(responseBody);
if (employeeId > 0 && sessionId > 0) {
Platform.runLater(() -> {
info("登录成功正在建立WebSocket连接...");
// 登录成功后建立WebSocket连接
establishWebSocketConnection(employeeId, sessionId);
});
} else {
Platform.runLater(() -> {
error("登录失败: 无效的响应数据");
showError("登录失败", "服务器返回无效的响应数据。");
});
}
} catch (Exception e) {
Platform.runLater(() -> {
error("登录失败: 解析响应失败 - " + e.getMessage());
showError("登录失败", "解析服务器响应时发生错误。");
});
}
}
});
} catch (Exception e) {
Platform.runLater(() -> {
error("登录过程中发生错误: " + e.getMessage());
showError("登录错误", e.getMessage());
});
}
}
private void establishWebSocketConnection(int employeeId, int sessionId) {
try {
// 构建WebSocket请求包含认证信息
Request request = new Request.Builder()
.url(webSocketUrl + "?employeeId=" + employeeId + "&sessionId=" + sessionId)
.build();
webSocket = httpClient.newWebSocket(request, new WebSocketListener() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
Platform.runLater(() -> {
info("WebSocket连接已建立");
// 登录成功后的处理
logined(employeeId, sessionId);
});
}
@Override
public void onMessage(WebSocket webSocket, String text) {
// 处理收到的文本消息
logger.debug("收到WebSocket消息: " + text);
// 这里可以根据需要处理从服务器接收的数据
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
// 处理收到的二进制消息
logger.debug("收到二进制WebSocket消息长度: " + bytes.size());
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
logger.debug("WebSocket连接正在关闭: 代码=" + code + ", 原因=" + reason);
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
logger.debug("WebSocket连接已关闭: 代码=" + code + ", 原因=" + reason);
// 可以在这里处理重连逻辑
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
logger.error("WebSocket连接失败: " + t.getMessage());
Platform.runLater(() -> {
error("WebSocket连接失败: " + t.getMessage());
showError("连接错误", "与服务器的WebSocket连接失败。");
});
}
});
} catch (Exception e) {
logger.error("建立WebSocket连接失败: " + e.getMessage());
Platform.runLater(() -> {
error("建立WebSocket连接失败: " + e.getMessage());
showError("连接错误", "无法建立与服务器的WebSocket连接。");
});
}
}
private void logined(int employeeId, int sessionId) {
// 设置当前登录员工信息
Desktop.instance.setActiveEmployeeId(employeeId);
Desktop.instance.setSessionId(sessionId);
// 显示主窗口
tryShowHomeWindow();
}
void tryShowHomeWindow() {
try {
while (!SpringApp.isRunning()) {
System.out.println("等待启动");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 必须要等待启动成功后才能关闭主场景,否则进程结束程序退出
HomeWindowController.show().thenRun(() -> Platform.runLater(primaryStage::close));
}
CompletableFuture<List<MacIP>> getMacAndIP() {
return CompletableFuture.supplyAsync(() -> {
List<MacIP> list = new ArrayList<>();
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface anInterface = interfaces.nextElement();
if (anInterface.isLoopback() || !anInterface.isUp()) {
continue;
}
byte[] hardwareAddress = anInterface.getHardwareAddress();
if (hardwareAddress == null) {
continue;
}
Enumeration<InetAddress> inetAddresses = anInterface.getInetAddresses();
if (!inetAddresses.hasMoreElements()) {
continue;
}
// -分割16进制表示法
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hardwareAddress.length; i++) {
sb.append(
String.format("%02X%s", hardwareAddress[i], i < hardwareAddress.length - 1 ? "-" : ""));
}
String mac = sb.toString();
while (inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
if (inetAddress.getHostAddress().contains(":")) {
continue; // 跳过IPv6地址
}
list.add(new MacIP(mac, inetAddress.getHostAddress()));
}
}
} catch (SocketException e) {
throw new RuntimeException(e);
}
return list;
});
}
// 辅助方法从响应中提取employeeId
private int extractEmployeeId(String responseBody) {
// 这里应该根据实际的响应格式进行解析
// 示例:假设响应格式是 {"employeeId": 123, "sessionId": 456}
try {
int start = responseBody.indexOf("employeeId") + 12;
int end = responseBody.indexOf(",", start);
if (end == -1) {
end = responseBody.indexOf("}", start);
}
return Integer.parseInt(responseBody.substring(start, end).trim());
} catch (Exception e) {
return -1;
}
}
// 辅助方法从响应中提取sessionId
private int extractSessionId(String responseBody) {
// 这里应该根据实际的响应格式进行解析
try {
int start = responseBody.indexOf("sessionId") + 11;
int end = responseBody.indexOf(",", start);
if (end == -1) {
end = responseBody.indexOf("}", start);
}
return Integer.parseInt(responseBody.substring(start, end).trim());
} catch (Exception e) {
return -1;
}
}
private void showError(String title, String message) {
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle(title);
alert.setHeaderText(null);
alert.setContentText(message);
alert.showAndWait();
});
}
// WebSocket消息发送方法
public void sendMessage(String message) {
if (webSocket != null) {
webSocket.send(message);
}
}
// 关闭WebSocket连接
public void closeWebSocket() {
if (webSocket != null) {
webSocket.close(1000, "正常关闭");
webSocket = null;
}
}
static class MacIP {
String mac;
String ip;
public MacIP(String mac, String ip) {
this.mac = mac;
this.ip = ip;
}
}
}