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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user