From cb2d2b5bf287f1729a951418f5fd3c3cd1ac3ef7 Mon Sep 17 00:00:00 2001
From: zhouyl <583641232@qq.com>
Date: Wed, 28 Aug 2024 15:21:48 +0800
Subject: [PATCH] =?UTF-8?q?:sparkles:=20=20=20=20CPU=E6=80=A7=E8=83=BD?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 5 +
.../system/ToolManageController.java | 3 -
.../src/main/resources/application-dev.yml | 6 +-
tp-admin/src/main/resources/application.yml | 39 ++--
.../config/ApiDecryptAutoConfiguration.java | 34 ++++
.../properties/ApiDecryptProperties.java | 36 ++++
.../framework/encrypt/ApiEncrypt.java | 20 +++
.../framework/filter/CryptoFilter.java | 112 ++++++++++++
.../filter/DecryptRequestBodyWrapper.java | 95 ++++++++++
.../filter/EncryptResponseBodyWrapper.java | 125 +++++++++++++
tp-functional/pom.xml | 5 +
.../controller/CpuInfoController.java | 169 ++++++++++++++++++
.../functional/domain/CpuInfo.java | 72 ++++++++
.../functional/mapper/CpuInfoMapper.java | 18 ++
.../functional/service/CpuInfoService.java | 16 ++
.../service/impl/CpuInfoServiceImpl.java | 21 +++
.../service/impl/ToolManageServiceImpl.java | 1 +
17 files changed, 758 insertions(+), 19 deletions(-)
create mode 100644 tp-framework/src/main/java/com/inscloudtech/framework/config/ApiDecryptAutoConfiguration.java
create mode 100644 tp-framework/src/main/java/com/inscloudtech/framework/config/properties/ApiDecryptProperties.java
create mode 100644 tp-framework/src/main/java/com/inscloudtech/framework/encrypt/ApiEncrypt.java
create mode 100644 tp-framework/src/main/java/com/inscloudtech/framework/filter/CryptoFilter.java
create mode 100644 tp-framework/src/main/java/com/inscloudtech/framework/filter/DecryptRequestBodyWrapper.java
create mode 100644 tp-framework/src/main/java/com/inscloudtech/framework/filter/EncryptResponseBodyWrapper.java
create mode 100644 tp-functional/src/main/java/com/inscloudtech/functional/controller/CpuInfoController.java
create mode 100644 tp-functional/src/main/java/com/inscloudtech/functional/domain/CpuInfo.java
create mode 100644 tp-functional/src/main/java/com/inscloudtech/functional/mapper/CpuInfoMapper.java
create mode 100644 tp-functional/src/main/java/com/inscloudtech/functional/service/CpuInfoService.java
create mode 100644 tp-functional/src/main/java/com/inscloudtech/functional/service/impl/CpuInfoServiceImpl.java
diff --git a/pom.xml b/pom.xml
index 846d37c..6d72f77 100644
--- a/pom.xml
+++ b/pom.xml
@@ -306,6 +306,11 @@
+
+ org.jsoup
+ jsoup
+ 1.15.3
+
com.inscloudtech
tp-functional
diff --git a/tp-admin/src/main/java/com/inscloudtech/web/controller/system/ToolManageController.java b/tp-admin/src/main/java/com/inscloudtech/web/controller/system/ToolManageController.java
index fd057c5..ff40b8d 100644
--- a/tp-admin/src/main/java/com/inscloudtech/web/controller/system/ToolManageController.java
+++ b/tp-admin/src/main/java/com/inscloudtech/web/controller/system/ToolManageController.java
@@ -2,7 +2,6 @@ package com.inscloudtech.web.controller.system;
import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.inscloudtech.common.annotation.Log;
import com.inscloudtech.common.annotation.RepeatSubmit;
@@ -11,7 +10,6 @@ import com.inscloudtech.common.core.domain.PageQuery;
import com.inscloudtech.common.core.domain.R;
import com.inscloudtech.common.core.page.TableDataInfo;
import com.inscloudtech.common.core.validate.AddGroup;
-import com.inscloudtech.common.core.validate.EditGroup;
import com.inscloudtech.common.enums.BusinessType;
import com.inscloudtech.common.utils.poi.ExcelUtil;
import com.inscloudtech.system.domain.ToolManage;
@@ -30,7 +28,6 @@ import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
/**
* 测试包管理
diff --git a/tp-admin/src/main/resources/application-dev.yml b/tp-admin/src/main/resources/application-dev.yml
index d29661c..9af80c3 100644
--- a/tp-admin/src/main/resources/application-dev.yml
+++ b/tp-admin/src/main/resources/application-dev.yml
@@ -5,7 +5,7 @@ spring:
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
- p6spy: true
+ p6spy: false
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
# 严格模式 匹配不到数据源则报错
@@ -17,7 +17,7 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
- url: jdbc:mysql://192.168.3.20:3306/test_platform?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
+ url: jdbc:mysql://ly:3306/test_platform?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: root
password: 123456
# 从库数据源
@@ -41,7 +41,7 @@ spring:
spring:
redis:
# 地址
- host: localhost
+ host: ly
# 端口,默认为6379
port: 6379
# 数据库索引
diff --git a/tp-admin/src/main/resources/application.yml b/tp-admin/src/main/resources/application.yml
index b2472cf..02a3d8b 100644
--- a/tp-admin/src/main/resources/application.yml
+++ b/tp-admin/src/main/resources/application.yml
@@ -135,9 +135,7 @@ security:
# swagger 文档配置
- /*/api-docs
- /*/api-docs/**
- # actuator 监控配置
- - /actuator
- - /actuator/**
+
# MyBatisPlus配置
# https://baomidou.com/config/
@@ -253,13 +251,28 @@ lock4j:
expire: 30000
--- # Actuator 监控端点的配置项
-management:
- endpoints:
- web:
- exposure:
- include: '*'
- endpoint:
- health:
- show-details: ALWAYS
- logfile:
- external-file: ./logs/sys-console.log
+#management:
+# endpoints:
+# port: -1 # 修改端口,跳过安全漏洞扫描
+# web:
+# exposure:
+# include: '*'
+# endpoint:
+# enabled-by-default: false #关闭监控
+# health:
+# show-details: ALWAYS
+# logfile:
+# external-file: ./logs/sys-console.log
+
+# api接口加密
+api-decrypt:
+ # 是否开启全局接口加密
+ enabled: true
+ # AES 加密头标识
+ headerFlag: encrypt-key
+ # 响应加密公钥 非对称算法的公私钥 如:SM2,RSA 使用者请自行更换
+ # 对应前端解密私钥 MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
+ publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJnNwrj4hi/y3CCJu868ghCG5dUj8wZK++RNlTLcXoMmdZWEQ/u02RgD5LyLAXGjLOjbMtC+/J9qofpSGTKSx/MCAwEAAQ==
+ # 请求解密私钥 非对称算法的公私钥 如:SM2,RSA 使用者请自行更换
+ # 对应前端加密公钥 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
+ privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=
diff --git a/tp-framework/src/main/java/com/inscloudtech/framework/config/ApiDecryptAutoConfiguration.java b/tp-framework/src/main/java/com/inscloudtech/framework/config/ApiDecryptAutoConfiguration.java
new file mode 100644
index 0000000..749ce28
--- /dev/null
+++ b/tp-framework/src/main/java/com/inscloudtech/framework/config/ApiDecryptAutoConfiguration.java
@@ -0,0 +1,34 @@
+package com.inscloudtech.framework.config;
+
+import com.inscloudtech.framework.config.properties.ApiDecryptProperties;
+import com.inscloudtech.framework.filter.CryptoFilter;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+
+import javax.servlet.DispatcherType;
+
+
+/**
+ * api 解密自动配置
+ *
+ * @author wdhcr
+ */
+@AutoConfiguration
+@EnableConfigurationProperties(ApiDecryptProperties.class)
+@ConditionalOnProperty(value = "api-decrypt.enabled", havingValue = "true")
+public class ApiDecryptAutoConfiguration {
+
+ @Bean
+ public FilterRegistrationBean cryptoFilterRegistration(ApiDecryptProperties properties) {
+ FilterRegistrationBean registration = new FilterRegistrationBean<>();
+ registration.setDispatcherTypes(DispatcherType.REQUEST);
+ registration.setFilter(new CryptoFilter(properties));
+ registration.addUrlPatterns("/*");
+ registration.setName("cryptoFilter");
+ registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
+ return registration;
+ }
+}
diff --git a/tp-framework/src/main/java/com/inscloudtech/framework/config/properties/ApiDecryptProperties.java b/tp-framework/src/main/java/com/inscloudtech/framework/config/properties/ApiDecryptProperties.java
new file mode 100644
index 0000000..3c52b9f
--- /dev/null
+++ b/tp-framework/src/main/java/com/inscloudtech/framework/config/properties/ApiDecryptProperties.java
@@ -0,0 +1,36 @@
+package com.inscloudtech.framework.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * api解密属性配置类
+ * @author wdhcr
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "api-decrypt")
+public class ApiDecryptProperties {
+
+ /**
+ * 加密开关
+ */
+ private Boolean enabled;
+
+ /**
+ * 头部标识
+ */
+ private String headerFlag;
+
+ /**
+ * 响应加密公钥
+ */
+ private String publicKey;
+
+ /**
+ * 请求解密私钥
+ */
+ private String privateKey;
+
+}
diff --git a/tp-framework/src/main/java/com/inscloudtech/framework/encrypt/ApiEncrypt.java b/tp-framework/src/main/java/com/inscloudtech/framework/encrypt/ApiEncrypt.java
new file mode 100644
index 0000000..11ec157
--- /dev/null
+++ b/tp-framework/src/main/java/com/inscloudtech/framework/encrypt/ApiEncrypt.java
@@ -0,0 +1,20 @@
+package com.inscloudtech.framework.encrypt;
+
+import java.lang.annotation.*;
+
+/**
+ * 强制加密注解
+ *
+ * @author Michelle.Chung
+ */
+@Documented
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ApiEncrypt {
+
+ /**
+ * 响应加密忽略,默认不加密,为 true 时加密
+ */
+ boolean response() default false;
+
+}
diff --git a/tp-framework/src/main/java/com/inscloudtech/framework/filter/CryptoFilter.java b/tp-framework/src/main/java/com/inscloudtech/framework/filter/CryptoFilter.java
new file mode 100644
index 0000000..16a41c9
--- /dev/null
+++ b/tp-framework/src/main/java/com/inscloudtech/framework/filter/CryptoFilter.java
@@ -0,0 +1,112 @@
+package com.inscloudtech.framework.filter;
+
+import cn.hutool.core.util.ObjectUtil;
+
+import com.inscloudtech.common.exception.ServiceException;
+import com.inscloudtech.common.utils.StringUtils;
+import com.inscloudtech.common.utils.spring.SpringUtils;
+import com.inscloudtech.framework.config.properties.ApiDecryptProperties;
+import com.inscloudtech.framework.encrypt.ApiEncrypt;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerExceptionResolver;
+import org.springframework.web.servlet.HandlerExecutionChain;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+
+/**
+ * Crypto 过滤器
+ *
+ * @author wdhcr
+ */
+public class CryptoFilter implements Filter {
+ private final ApiDecryptProperties properties;
+
+ public CryptoFilter(ApiDecryptProperties properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest servletRequest = (HttpServletRequest) request;
+ HttpServletResponse servletResponse = (HttpServletResponse) response;
+ // 获取加密注解
+ ApiEncrypt apiEncrypt = this.getApiEncryptAnnotation(servletRequest);
+ boolean responseFlag = apiEncrypt != null && apiEncrypt.response();
+ ServletRequest requestWrapper = null;
+ ServletResponse responseWrapper = null;
+ EncryptResponseBodyWrapper responseBodyWrapper = null;
+
+ // 是否为 put 或者 post 请求
+ if (HttpMethod.PUT.matches(servletRequest.getMethod()) || HttpMethod.POST.matches(servletRequest.getMethod())) {
+ // 是否存在加密标头
+ String headerValue = servletRequest.getHeader(properties.getHeaderFlag());
+ if (StringUtils.isNotBlank(headerValue)) {
+ // 请求解密
+ requestWrapper = new DecryptRequestBodyWrapper(servletRequest, properties.getPrivateKey(), properties.getHeaderFlag());
+ } else {
+ // 是否有注解,有就报错,没有放行
+ if (ObjectUtil.isNotNull(apiEncrypt)) {
+ HandlerExceptionResolver exceptionResolver = SpringUtils.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);
+ exceptionResolver.resolveException(
+ servletRequest, servletResponse, null,
+ new ServiceException("没有访问权限,请联系管理员授权", HttpStatus.FORBIDDEN.value()));
+ return;
+ }
+ }
+ }
+
+ // 判断是否响应加密
+ if (responseFlag) {
+ responseBodyWrapper = new EncryptResponseBodyWrapper(servletResponse);
+ responseWrapper = responseBodyWrapper;
+ }
+
+ chain.doFilter(
+ ObjectUtil.defaultIfNull(requestWrapper, request),
+ ObjectUtil.defaultIfNull(responseWrapper, response));
+
+ if (responseFlag) {
+ servletResponse.reset();
+ // 对原始内容加密
+ String encryptContent = responseBodyWrapper.getEncryptContent(
+ servletResponse, properties.getPublicKey(), properties.getHeaderFlag());
+ // 对加密后的内容写出
+ servletResponse.getWriter().write(encryptContent);
+ }
+ }
+
+ /**
+ * 获取 ApiEncrypt 注解
+ */
+ private ApiEncrypt getApiEncryptAnnotation(HttpServletRequest servletRequest) {
+ RequestMappingHandlerMapping handlerMapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
+ // 获取注解
+ try {
+ HandlerExecutionChain mappingHandler = handlerMapping.getHandler(servletRequest);
+ if (ObjectUtil.isNotNull(mappingHandler)) {
+ Object handler = mappingHandler.getHandler();
+ if (ObjectUtil.isNotNull(handler)) {
+ // 从handler获取注解
+ if (handler instanceof HandlerMethod) {
+ HandlerMethod handlerMethod = (HandlerMethod)handler;
+ return handlerMethod.getMethodAnnotation(ApiEncrypt.class);
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public void destroy() {
+ }
+}
diff --git a/tp-framework/src/main/java/com/inscloudtech/framework/filter/DecryptRequestBodyWrapper.java b/tp-framework/src/main/java/com/inscloudtech/framework/filter/DecryptRequestBodyWrapper.java
new file mode 100644
index 0000000..d74800b
--- /dev/null
+++ b/tp-framework/src/main/java/com/inscloudtech/framework/filter/DecryptRequestBodyWrapper.java
@@ -0,0 +1,95 @@
+package com.inscloudtech.framework.filter;
+
+import cn.hutool.core.io.IoUtil;
+
+import com.inscloudtech.common.constant.Constants;
+import com.inscloudtech.common.utils.EncryptUtils;
+import org.springframework.http.MediaType;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 解密请求参数工具类
+ *
+ * @author wdhcr
+ */
+public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper {
+
+ private final byte[] body;
+
+ public DecryptRequestBodyWrapper(HttpServletRequest request, String privateKey, String headerFlag) throws IOException {
+ super(request);
+ // 获取 AES 密码 采用 RSA 加密
+ String headerRsa = request.getHeader(headerFlag);
+ String decryptAes = EncryptUtils.decryptByRsa(headerRsa, privateKey);
+ // 解密 AES 密码
+ String aesPassword = EncryptUtils.decryptByBase64(decryptAes);
+ request.setCharacterEncoding(Constants.UTF8);
+ byte[] readBytes = IoUtil.readBytes(request.getInputStream(), false);
+ String requestBody = new String(readBytes, StandardCharsets.UTF_8);
+ // 解密 body 采用 AES 加密
+ String decryptBody = EncryptUtils.decryptByAes(requestBody, aesPassword);
+ body = decryptBody.getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public BufferedReader getReader() {
+ return new BufferedReader(new InputStreamReader(getInputStream()));
+ }
+
+
+ @Override
+ public int getContentLength() {
+ return body.length;
+ }
+
+ @Override
+ public long getContentLengthLong() {
+ return body.length;
+ }
+
+ @Override
+ public String getContentType() {
+ return MediaType.APPLICATION_JSON_VALUE;
+ }
+
+
+ @Override
+ public ServletInputStream getInputStream() {
+ final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+ return new ServletInputStream() {
+ @Override
+ public int read() {
+ return bais.read();
+ }
+
+ @Override
+ public int available() {
+ return body.length;
+ }
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+
+ }
+ };
+ }
+}
diff --git a/tp-framework/src/main/java/com/inscloudtech/framework/filter/EncryptResponseBodyWrapper.java b/tp-framework/src/main/java/com/inscloudtech/framework/filter/EncryptResponseBodyWrapper.java
new file mode 100644
index 0000000..d4b5f14
--- /dev/null
+++ b/tp-framework/src/main/java/com/inscloudtech/framework/filter/EncryptResponseBodyWrapper.java
@@ -0,0 +1,125 @@
+package com.inscloudtech.framework.filter;
+
+import cn.hutool.core.util.RandomUtil;
+import com.inscloudtech.common.utils.EncryptUtils;
+
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 加密响应参数包装类
+ *
+ * @author Michelle.Chung
+ */
+public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper {
+
+ private final ByteArrayOutputStream byteArrayOutputStream;
+ private final ServletOutputStream servletOutputStream;
+ private final PrintWriter printWriter;
+
+ public EncryptResponseBodyWrapper(HttpServletResponse response) throws IOException {
+ super(response);
+ this.byteArrayOutputStream = new ByteArrayOutputStream();
+ this.servletOutputStream = this.getOutputStream();
+ this.printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));
+ }
+
+ @Override
+ public PrintWriter getWriter() {
+ return printWriter;
+ }
+
+ @Override
+ public void flushBuffer() throws IOException {
+ if (servletOutputStream != null) {
+ servletOutputStream.flush();
+ }
+ if (printWriter != null) {
+ printWriter.flush();
+ }
+ }
+
+ @Override
+ public void reset() {
+ byteArrayOutputStream.reset();
+ }
+
+ public byte[] getResponseData() throws IOException {
+ flushBuffer();
+ return byteArrayOutputStream.toByteArray();
+ }
+
+ public String getContent() throws IOException {
+ flushBuffer();
+ return byteArrayOutputStream.toString();
+ }
+
+ /**
+ * 获取加密内容
+ *
+ * @param servletResponse response
+ * @param publicKey RSA公钥 (用于加密 AES 秘钥)
+ * @param headerFlag 请求头标志
+ * @return 加密内容
+ * @throws IOException
+ */
+ public String getEncryptContent(HttpServletResponse servletResponse, String publicKey, String headerFlag) throws IOException {
+ // 生成秘钥
+ String aesPassword = RandomUtil.randomString(32);
+ // 秘钥使用 Base64 编码
+ String encryptAes = EncryptUtils.encryptByBase64(aesPassword);
+ // Rsa 公钥加密 Base64 编码
+ String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey);
+
+ // 设置响应头
+ servletResponse.addHeader("Access-Control-Expose-Headers", headerFlag);
+ servletResponse.setHeader(headerFlag, encryptPassword);
+ servletResponse.setHeader("Access-Control-Allow-Origin", "*");
+ servletResponse.setHeader("Access-Control-Allow-Methods", "*");
+ servletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());
+
+ // 获取原始内容
+ String originalBody = this.getContent();
+ // 对内容进行加密
+ return EncryptUtils.encryptByAes(originalBody, aesPassword);
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ return new ServletOutputStream() {
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ byteArrayOutputStream.write(b);
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ byteArrayOutputStream.write(b);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ byteArrayOutputStream.write(b, off, len);
+ }
+ };
+ }
+
+}
diff --git a/tp-functional/pom.xml b/tp-functional/pom.xml
index d452827..2818b58 100644
--- a/tp-functional/pom.xml
+++ b/tp-functional/pom.xml
@@ -15,6 +15,11 @@
com.inscloudtech
tp-common
+
+
+ org.jsoup
+ jsoup
+
diff --git a/tp-functional/src/main/java/com/inscloudtech/functional/controller/CpuInfoController.java b/tp-functional/src/main/java/com/inscloudtech/functional/controller/CpuInfoController.java
new file mode 100644
index 0000000..1901fef
--- /dev/null
+++ b/tp-functional/src/main/java/com/inscloudtech/functional/controller/CpuInfoController.java
@@ -0,0 +1,169 @@
+package com.inscloudtech.functional.controller;
+
+/***/
+
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.inscloudtech.common.annotation.Log;
+import com.inscloudtech.common.annotation.RepeatSubmit;
+import com.inscloudtech.common.core.domain.PageQuery;
+import com.inscloudtech.common.core.domain.R;
+import com.inscloudtech.common.core.page.TableDataInfo;
+import com.inscloudtech.common.enums.BusinessType;
+import com.inscloudtech.functional.domain.CpuInfo;
+import com.inscloudtech.functional.service.CpuInfoService;
+import lombok.RequiredArgsConstructor;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * CPU性能数据库
+ *
+ * @author zfcf
+ * @date 2024-08-28
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/functional/info")
+public class CpuInfoController {
+
+ private final CpuInfoService cpuInfoService;
+
+ /**
+ * 分页查询
+ * @param
+ * @param
+ * @return
+ */
+ @GetMapping("/page" )
+ public TableDataInfo getCpuInfoPage(PageQuery pageQuery, CpuInfo cpuInfo) {
+ Page page = new Page();
+ page.setSize(pageQuery.getPageSize());
+ page.setCurrent(pageQuery.getPageNum());
+ Page result = cpuInfoService.page(page, Wrappers.query(cpuInfo));
+ TableDataInfo dataInfo = new TableDataInfo();
+ dataInfo.setTotal(result.getTotal());
+ dataInfo.setRows(result.getRecords());
+ return dataInfo;
+ }
+
+
+ /**
+ * 通过id查询cpu信息
+ * @param id id
+ * @return R
+ */
+ @GetMapping("/{id}" )
+ public R getById(@PathVariable("id" ) Long id) {
+ return R.ok(cpuInfoService.getById(id));
+ }
+
+ /**
+ * 新增cpu信息
+ * @param
+ * @return R
+ */
+ @Log(title = "cpu信息", businessType = BusinessType.EXPORT)
+ @RepeatSubmit()
+ @PostMapping
+ public R save(@RequestBody CpuInfo cpuInfo) {
+ return R.ok(cpuInfoService.save(cpuInfo));
+ }
+
+ /**
+ * 修改cpu信息
+ * @param
+ * @return R
+ */
+ @Log(title = "cpu信息", businessType = BusinessType.EXPORT)
+ @RepeatSubmit()
+ @PutMapping
+ public R updateById(@RequestBody CpuInfo cpuInfo) {
+ return R.ok(cpuInfoService.updateById(cpuInfo));
+ }
+
+ /**
+ * 通过id删除cpu信息
+ * @param id id
+ * @return R
+ */
+ @DeleteMapping("/{id}" )
+ public R removeById(@PathVariable Long id) {
+ return R.ok(cpuInfoService.removeById(id));
+ }
+
+ @GetMapping("/updateOtherInfo" )
+ public void updateOtherInfo() {
+ List list = cpuInfoService.list();
+ int i = 0;
+ for (CpuInfo info : list) {
+ updateByURL(info);
+ System.out.println(i++);
+ try {
+ cpuInfoService.updateById(info);
+ }catch (Exception e){
+ System.out.println("e.getMessage() = " + e.getMessage());
+ }
+ }
+
+
+ }
+
+ static String url = "https://cpu.bmcx.com/{}__cpu/";
+
+ public static void main(String[] args) {
+ CpuInfo info = new CpuInfo();
+ info.setId("5493");
+ updateByURL(info);
+ }
+
+ static void updateByURL(CpuInfo cpuInfo){
+
+ String id = cpuInfo.getId();
+ String _url = StrUtil.format(url,id);
+ String html = HttpUtil.get(_url);
+ Document document = Jsoup.parse(html);
+ Element mainContent = document.getElementById("main_content");
+ Elements tables = mainContent.getElementsByTag("table");
+ Elements tds = tables.get(1).getElementsByTag("td");
+ for(int i = 0; i < tds.size(); i++){
+ if (i < 6) {
+ continue;
+ }
+
+ Element td = tds.get(i);
+ if(i + 1 == tds.size()){
+ break;
+ }
+ Element valTd = tds.get(i + 1);
+ String field = td.text();
+ String val = valTd.text();
+ if(field.equals("TDP")){
+ cpuInfo.setTdp(val);
+ }else if(field.equals("插槽类型")){
+ cpuInfo.setSocketType(val);
+ }else if(field.equals("核心数")){
+ cpuInfo.setCoreCount(val);
+ }else if(field.equals("线程数")){
+ cpuInfo.setThreadCount(val);
+ }else if(field.equals("主频")){
+ cpuInfo.setBaseFrequency(val);
+ }else if(field.equals("睿频")){
+ cpuInfo.setBoostFrequency(val);
+ }else if(field.equals("发布时间")){
+ cpuInfo.setReleaseDate(val);
+ }
+ }
+// System.out.println("cpuInfo = " + cpuInfo);
+ }
+
+
+}
diff --git a/tp-functional/src/main/java/com/inscloudtech/functional/domain/CpuInfo.java b/tp-functional/src/main/java/com/inscloudtech/functional/domain/CpuInfo.java
new file mode 100644
index 0000000..c9547ed
--- /dev/null
+++ b/tp-functional/src/main/java/com/inscloudtech/functional/domain/CpuInfo.java
@@ -0,0 +1,72 @@
+package com.inscloudtech.functional.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+/**
+ * cpu信息对象 cpu_info
+ *
+ * @author zfcf
+ * @date 2024-08-28
+ */
+@Data
+@TableName("cpu_info")
+public class CpuInfo {
+
+ private static final long serialVersionUID=1L;
+
+ /**
+ * 主键
+ */
+ @TableId(value = "id")
+ private String id;
+ /**
+ * 性能排名
+ */
+ private String paiMing;
+ /**
+ * 名称
+ */
+ @TableField(condition = SqlCondition.LIKE)
+ private String mingCheng;
+ /**
+ *
+ */
+ private String baiFenBi;
+ /**
+ *得分
+ */
+ private String shuZhi;
+ /**
+ * TDP
+ */
+ private String tdp;
+ /**
+ * 插槽类型
+ */
+ private String socketType;
+ /**
+ * 核心数
+ */
+ private String coreCount;
+ /**
+ * 线程数
+ */
+ private String threadCount;
+ /**
+ * 主频
+ */
+ private String baseFrequency;
+ /**
+ * 睿频
+ */
+ private String boostFrequency;
+ /**
+ * 发布时间
+ */
+ private String releaseDate;
+
+}
+
diff --git a/tp-functional/src/main/java/com/inscloudtech/functional/mapper/CpuInfoMapper.java b/tp-functional/src/main/java/com/inscloudtech/functional/mapper/CpuInfoMapper.java
new file mode 100644
index 0000000..934bef5
--- /dev/null
+++ b/tp-functional/src/main/java/com/inscloudtech/functional/mapper/CpuInfoMapper.java
@@ -0,0 +1,18 @@
+package com.inscloudtech.functional.mapper;
+
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.inscloudtech.functional.domain.CpuInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * cpu信息
+ *
+ * @author zfcf
+ * @date 2024-08-28
+ */
+@Mapper
+public interface CpuInfoMapper extends BaseMapper {
+
+}
diff --git a/tp-functional/src/main/java/com/inscloudtech/functional/service/CpuInfoService.java b/tp-functional/src/main/java/com/inscloudtech/functional/service/CpuInfoService.java
new file mode 100644
index 0000000..fdb50b0
--- /dev/null
+++ b/tp-functional/src/main/java/com/inscloudtech/functional/service/CpuInfoService.java
@@ -0,0 +1,16 @@
+package com.inscloudtech.functional.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.inscloudtech.functional.domain.CpuInfo;
+
+
+/**
+ * cpu信息Service接口
+ * @author zfcf
+ * @date 2024-08-28
+ */
+public interface CpuInfoService extends IService {
+
+}
+
diff --git a/tp-functional/src/main/java/com/inscloudtech/functional/service/impl/CpuInfoServiceImpl.java b/tp-functional/src/main/java/com/inscloudtech/functional/service/impl/CpuInfoServiceImpl.java
new file mode 100644
index 0000000..a7342d7
--- /dev/null
+++ b/tp-functional/src/main/java/com/inscloudtech/functional/service/impl/CpuInfoServiceImpl.java
@@ -0,0 +1,21 @@
+package com.inscloudtech.functional.service.impl;
+
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import com.inscloudtech.functional.domain.CpuInfo;
+import com.inscloudtech.functional.mapper.CpuInfoMapper;
+import com.inscloudtech.functional.service.CpuInfoService;
+import org.springframework.stereotype.Service;
+
+/**
+ * cpu信息
+ *
+ * @author zfcf
+ * @date 2024-08-28
+ */
+@Service
+public class CpuInfoServiceImpl extends ServiceImpl implements CpuInfoService {
+
+}
diff --git a/tp-system/src/main/java/com/inscloudtech/system/service/impl/ToolManageServiceImpl.java b/tp-system/src/main/java/com/inscloudtech/system/service/impl/ToolManageServiceImpl.java
index e745f6f..5e4f170 100644
--- a/tp-system/src/main/java/com/inscloudtech/system/service/impl/ToolManageServiceImpl.java
+++ b/tp-system/src/main/java/com/inscloudtech/system/service/impl/ToolManageServiceImpl.java
@@ -61,6 +61,7 @@ public class ToolManageServiceImpl implements IToolManageService {
@Override
public TableDataInfo queryPageList(ToolManage bo, PageQuery pageQuery) {
LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ lqw.orderByDesc(ToolManage::getCreateTime);
Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}