Files
contract-manager/client/src/main/java/com/ecep/contract/Desktop.java
songqq b03b5385a5 refactor(service): 修改IEntityService泛型为VO类型并优化缓存策略
重构所有注解@CacheConfig的Service类,将IEntityService泛型从实体类改为VO类
实现实体与VO之间的转换逻辑,使用VO替代实体进行缓存以避免序列化问题
更新相关依赖组件和测试用例,确保功能完整性和系统兼容性
优化Redis缓存配置,清理旧缓存数据并验证新缓存策略有效性
2025-09-28 18:19:00 +08:00

310 lines
11 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ecep.contract;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.controller.HomeWindowController;
import com.ecep.contract.controller.OkHttpLoginController;
import com.ecep.contract.task.TaskMonitorCenter;
import com.ecep.contract.util.HibernateProxyUtils;
import com.ecep.contract.util.TextMessageHolder;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CurrentEmployee;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import lombok.Getter;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
/**
* JavaFx 应用程序
*
* @author ecep
* Created by ecep on 2017/05/08.
*/
public class Desktop extends Application {
public static final Logger logger = LoggerFactory.getLogger(Desktop.class);
public static Desktop instance;
public static void shutdown() {
if (logger.isDebugEnabled()) {
logger.debug("shutdown");
}
if (instance != null) {
try {
instance.stop();
} catch (Throwable e) {
logger.error("shutdown error", e);
}
}
}
private ScheduledExecutorService scheduledExecutorService = null;
private final TaskMonitorCenter taskMonitorCenter = new TaskMonitorCenter();
private final SimpleStringProperty sessionId = new SimpleStringProperty("");
@Getter
private final CurrentEmployee activeEmployee = new CurrentEmployee();
@Getter
private OkHttpClient httpClient;
public void setActiveEmployeeId(int activeEmployeeId) {
activeEmployee.getId().set(activeEmployeeId);
}
public int getActiveEmployeeId() {
return activeEmployee.getId().get();
}
public String getSessionId() {
return sessionId.get();
}
public void setSessionId(String sessionId) {
this.sessionId.set(sessionId);
}
public ScheduledExecutorService getExecutorService() {
if (scheduledExecutorService == null) {
scheduledExecutorService = Executors.newScheduledThreadPool(3);
}
return scheduledExecutorService;
}
public TaskMonitorCenter getTaskMonitorCenter() {
return taskMonitorCenter;
}
@Override
public void start(Stage primaryStage) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("start");
}
if (instance != null) {
logger.error("Desktop already started");
}
instance = this;
URL resource = getClass().getResource("/ui/start_lamp.fxml");
FXMLLoader loader = new FXMLLoader(resource);
primaryStage.setTitle("CMS");
primaryStage.initStyle(StageStyle.TRANSPARENT);
Parent root = loader.load();
Scene scene = new Scene(root);
scene.getStylesheets().add("/ui/start_lamp.css");
primaryStage.setScene(scene);
primaryStage.setOnShown(e -> {
System.out.println("primaryStage#OnShown");
});
primaryStage.show();
System.out.println("Desktop.start -> primaryStage.show()");
try {
startSpringApp(primaryStage, root, loader);
} catch (Exception e) {
UITools.showExceptionAndWait("启动失败", e);
}
}
public CompletableFuture<Void> runAsync(Runnable runnable) {
return CompletableFuture.runAsync(runnable, getExecutorService());
}
private void startSpringApp(Stage primaryStage, Parent root, FXMLLoader loader) {
logger.debug("startSpringApp");
// 更新窗口标题
Node titleNode = root.lookup("#title");
if (titleNode != null) {
primaryStage.setTitle(((Text) titleNode).getText());
}
Node lookup = root.lookup("#logBox");
if (!(lookup instanceof VBox logBox)) {
throw new RuntimeException("启动界面加载失败, #logger 类型错误");
}
ScrollPane logPane = (ScrollPane) root.lookup("#logPane");
logBox.getChildren().clear();
TextMessageHolder holder = new TextMessageHolder() {
@Override
public void addTextMessage(Text text) {
Platform.runLater(() -> {
logBox.getChildren().add(text);
logPane.layout();
logPane.setVvalue(1.0);
});
}
};
holder.info("启动中,请稍后...");
runAsync(() -> {
try {
//
holder.info("读取配置文件...");
Properties properties = new Properties();
File configFile = new File("config.properties");
if (configFile.exists()) {
holder.info("读取配置文件 " + configFile.getAbsolutePath() + "...");
try (FileInputStream input = new FileInputStream(configFile)) {
properties.load(input);
holder.info("配置文件读取成功.");
} catch (IOException e) {
holder.error("读取失败:" + e.getMessage());
logger.error(e.getMessage(), e);
return;
}
} else {
logger.warn("配置文件{}不存在", configFile.getAbsolutePath());
}
HibernateProxyUtils.useProxy(false);
runAsync(() -> {
SpringApp.launch(properties, holder);
ConfigurableListableBeanFactory beanFactory = SpringApp.context.getBeanFactory();
beanFactory.registerSingleton("scheduledExecutorService", getExecutorService());
beanFactory.registerSingleton("taskMonitorCenter", taskMonitorCenter);
});
try {
initHttpClient();
OkHttpLoginController controller = new OkHttpLoginController();
controller.setHttpClient(this.httpClient);
controller.setHolder(holder);
controller.setPrimaryStage(primaryStage);
MyProperties myProperties = new MyProperties();
myProperties.loadFromProperties(properties);
controller.setProperties(myProperties);
while (true) {
try {
controller.tryLogin().get();
holder.info("登录成功");
try {
while (!SpringApp.isRunning()) {
System.out.println("等待启动");
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
// 必须要等待启动成功后才能关闭主场景,否则进程结束程序退出
HomeWindowController.show().thenRun(() -> Platform.runLater(primaryStage::close));
break;
} catch (Exception ex) {
holder.error(ex.getMessage());
Thread.sleep(3000);
}
}
} catch (Exception e) {
holder.error("登录失败:" + e.getMessage());
logger.error(e.getMessage(), e);
}
} catch (Exception e) {
holder.error(e.getMessage());
logger.error(e.getMessage(), e);
}
});
System.out.println("Desktop.startSpringApp.");
}
private void initHttpClient() {
this.httpClient = new OkHttpClient().newBuilder().cookieJar(new CookieJar() {
private final List<Cookie> cookies = new java.util.ArrayList<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
// 保存服务器返回的Cookie如JSESSIONID
this.cookies.addAll(cookies);
System.out.println("保存Cookie: " + cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
// 请求时自动携带Cookie
return cookies;
}
}).build();
}
@Override
public void stop() throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("stop");
}
CompletableFuture<Void> future = BaseController.shutdown();
future.orTimeout(5, TimeUnit.SECONDS);
future.exceptionally(e -> {
logger.error(e.getMessage(), e);
return null;
});
future.thenRun(() -> {
SpringApp.shutdown();
try {
shutdownExecutorService();
super.stop();
if (logger.isDebugEnabled()) {
logger.debug("stopped");
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
});
}
private void shutdownExecutorService() {
List<Runnable> runnableList = scheduledExecutorService.shutdownNow();
for (Runnable runnable : runnableList) {
if (logger.isDebugEnabled()) {
logger.debug("shutdown runnable = {}", runnable);
}
if (runnable instanceof FutureTask<?> future) {
if (logger.isDebugEnabled()) {
logger.debug("runnable as future, isCancelled() = {}, isDone() = {}", future.isCancelled(),
future.isDone());
}
if (future.cancel(true)) {
if (logger.isDebugEnabled()) {
logger.debug("runnable as future canceled");
}
}
}
}
scheduledExecutorService.close();
}
}