java項(xiàng)目中常用指標(biāo)UV?PV?QPS?TPS含義以及統(tǒng)計(jì)方法
引言
在現(xiàn)代Web應(yīng)用中,性能和用戶體驗(yàn)是成功的關(guān)鍵。為了確保應(yīng)用程序的高效運(yùn)行,開發(fā)者需要對(duì)應(yīng)用的各項(xiàng)指標(biāo)進(jìn)行監(jiān)控和分析。
這些為系統(tǒng)優(yōu)化提供數(shù)據(jù)支撐。同時(shí)還可以具備以下功能:
- 優(yōu)化用戶體驗(yàn):了解用戶行為模式,從而優(yōu)化頁(yè)面加載速度和交互體驗(yàn)。
- 提升系統(tǒng)性能:識(shí)別性能瓶頸,優(yōu)化資源分配,確保系統(tǒng)穩(wěn)定性。
- 支持業(yè)務(wù)決策:通過(guò)數(shù)據(jù)分析支持產(chǎn)品改進(jìn)和市場(chǎng)策略。
UV(Unique Visitors)
UV(Unique Visitors)表示在特定時(shí)間段內(nèi)訪問(wèn)網(wǎng)站的獨(dú)立訪客數(shù)量。通常通過(guò)用戶的唯一標(biāo)識(shí)(如cookie、用戶ID或IP地址)進(jìn)行區(qū)分,以避免重復(fù)計(jì)算。幫助了解網(wǎng)站的覆蓋范圍和吸引力。
Java埋點(diǎn)統(tǒng)計(jì)方法
在Java后端中,我們可以使用過(guò)濾器或攔截器來(lái)埋點(diǎn)統(tǒng)計(jì)UV,并結(jié)合Redis進(jìn)行去重統(tǒng)計(jì)。
使用過(guò)濾器或攔截器
- 過(guò)濾器:用于在請(qǐng)求到達(dá)Servlet之前或響應(yīng)返回客戶端之前進(jìn)行處理。
- 攔截器:用于在Spring MVC中攔截請(qǐng)求,提供類似AOP的功能。
結(jié)合Redis進(jìn)行去重統(tǒng)計(jì)
Redis的Set數(shù)據(jù)結(jié)構(gòu)天然支持去重,可以用來(lái)存儲(chǔ)每天的獨(dú)立訪客標(biāo)識(shí)。通過(guò)設(shè)置過(guò)期時(shí)間,可以實(shí)現(xiàn)按天統(tǒng)計(jì)。
示例代碼
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import redis.clients.jedis.Jedis;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
@Component
public class UVInterceptor implements HandlerInterceptor {
private Jedis jedis;
public UVInterceptor() {
this.jedis = new Jedis("localhost", 6379); // 初始化Redis連接
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uniqueId = getUniqueIdFromRequest(request);
String key = "UV:" + LocalDate.now(); // 按日期存儲(chǔ)UV
jedis.sadd(key, uniqueId); // 使用Set進(jìn)行去重
jedis.expire(key, 86400); // 設(shè)置過(guò)期時(shí)間為一天
return true;
}
private String getUniqueIdFromRequest(HttpServletRequest request) {
// 示例中使用IP地址,可以替換為cookie或用戶ID
return request.getRemoteAddr();
}
}在Spring應(yīng)用中,需要將攔截器注冊(cè)到攔截器鏈中:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UVInterceptor uvInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(uvInterceptor).addPathPatterns("/**");
}
}通過(guò)這種方式,我們可以在每次請(qǐng)求時(shí)記錄獨(dú)立訪客,并利用Redis的Set特性實(shí)現(xiàn)去重和按天統(tǒng)計(jì)。
PV(Page Views)
PV(Page Views)表示頁(yè)面瀏覽量,即網(wǎng)站頁(yè)面被加載或重新加載的次數(shù)。它是衡量用戶對(duì)網(wǎng)站內(nèi)容興趣的重要指標(biāo)。
Java埋點(diǎn)統(tǒng)計(jì)方法
在Java后端中,可以使用AOP(Aspect-Oriented Programming)來(lái)記錄頁(yè)面訪問(wèn),并將數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)或緩存中進(jìn)行分析。
使用AOP進(jìn)行頁(yè)面訪問(wèn)記錄
AOP允許在方法執(zhí)行的不同階段插入自定義邏輯,非常適合用于記錄頁(yè)面訪問(wèn)。
數(shù)據(jù)存儲(chǔ)與分析
PV數(shù)據(jù)可以存儲(chǔ)在數(shù)據(jù)庫(kù)或Redis中,便于后續(xù)的統(tǒng)計(jì)分析。
示例代碼
- 定義AOP切面
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
@Aspect
@Component
public class PageViewAspect {
private Jedis jedis;
public PageViewAspect() {
this.jedis = new Jedis("localhost", 6379); // 初始化Redis連接
}
@After("execution(* com.example.controller..*(..))")
public void logPageView(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
String key = "PV:" + methodName + ":" + LocalDate.now();
jedis.incr(key); // 增加PV計(jì)數(shù)
jedis.expire(key, 86400); // 設(shè)置過(guò)期時(shí)間為一天
}
}- 配置AOP
確保Spring AOP配置正確,通常在Spring Boot中無(wú)需額外配置,Spring會(huì)自動(dòng)掃描并應(yīng)用切面。
<!-- Spring Boot中的pom.xml通常已包含AOP依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>通過(guò)這種方式,我們可以在每次方法執(zhí)行后記錄PV,并利用Redis進(jìn)行高效的計(jì)數(shù)和存儲(chǔ)。這樣便于后續(xù)的統(tǒng)計(jì)和分析。
QPS(Queries Per Second)
QPS(Queries Per Second)表示每秒處理的請(qǐng)求數(shù)量。它是衡量系統(tǒng)性能和負(fù)載能力的重要指標(biāo)。
- 用途:評(píng)估系統(tǒng)的負(fù)載能力和響應(yīng)效率,幫助在高并發(fā)場(chǎng)景下進(jìn)行性能調(diào)優(yōu)。
Java后端統(tǒng)計(jì)方法
使用計(jì)數(shù)器和時(shí)間窗口
- 計(jì)數(shù)器:記錄在固定時(shí)間窗口內(nèi)的請(qǐng)求數(shù)量。
- 時(shí)間窗口:通常設(shè)置為1秒,用于計(jì)算QPS。
實(shí)時(shí)監(jiān)控與報(bào)警機(jī)制
通過(guò)實(shí)時(shí)監(jiān)控QPS,可以迅速發(fā)現(xiàn)系統(tǒng)性能瓶頸或異常,并觸發(fā)報(bào)警機(jī)制。
示例代碼
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class QPSCounter {
private AtomicInteger requestCount = new AtomicInteger(0);
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public QPSCounter() {
// 每秒打印一次QPS
scheduler.scheduleAtFixedRate(() -> {
int qps = requestCount.getAndSet(0);
System.out.println("Current QPS: " + qps);
// 這里可以添加報(bào)警邏輯
if (qps > 1000) {
System.out.println("QPS exceeds threshold!");
}
}, 0, 1, TimeUnit.SECONDS);
}
public void recordRequest() {
requestCount.incrementAndGet();
}
public static void main(String[] args) {
QPSCounter qpsCounter = new QPSCounter();
// 模擬請(qǐng)求
for (int i = 0; i < 5000; i++) {
qpsCounter.recordRequest();
try {
Thread.sleep(1); // 模擬請(qǐng)求間隔
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}- 計(jì)數(shù)器:使用
AtomicInteger確保線程安全。 - 時(shí)間窗口:通過(guò)
ScheduledExecutorService每秒重置計(jì)數(shù)器并打印QPS。 - 報(bào)警機(jī)制:簡(jiǎn)單的閾值檢測(cè),可根據(jù)需求進(jìn)行擴(kuò)展。
TPS(Transactions Per Second)
TPS(Transactions Per Second)表示每秒處理的事務(wù)數(shù)量。它是評(píng)估系統(tǒng)處理能力和效率的重要指標(biāo)。
- 用途:用于評(píng)估事務(wù)密集型應(yīng)用的性能,特別是在金融、支付等領(lǐng)域。
Java后端統(tǒng)計(jì)方法
使用線程池和事務(wù)管理
- 線程池:高效管理并發(fā)事務(wù),減少線程創(chuàng)建和銷毀的開銷。
- 事務(wù)管理:確保事務(wù)的一致性和完整性,通常使用Spring的事務(wù)管理功能。
性能優(yōu)化與瓶頸分析
- 優(yōu)化線程池配置:根據(jù)系統(tǒng)資源和負(fù)載調(diào)整線程池大小。
- 數(shù)據(jù)庫(kù)優(yōu)化:使用索引、優(yōu)化查詢等方法提升數(shù)據(jù)庫(kù)性能。
- 異步處理:將非關(guān)鍵任務(wù)異步化,減少事務(wù)執(zhí)行時(shí)間。
示例代碼
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.concurrent.Executor;
@Service
public class TPSCounter {
@Autowired
private JdbcTemplate jdbcTemplate;
private Executor executor;
@PostConstruct
public void init() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(50);
taskExecutor.setQueueCapacity(100);
taskExecutor.initialize();
this.executor = taskExecutor;
}
@Async
@Transactional
public void processTransaction(String transactionData) {
// 模擬事務(wù)處理
jdbcTemplate.update("INSERT INTO transactions (data) VALUES (?)", transactionData);
// 其他業(yè)務(wù)邏輯
}
public void simulateTransactions(int numberOfTransactions) {
for (int i = 0; i < numberOfTransactions; i++) {
processTransaction("Transaction " + i);
}
}
public static void main(String[] args) {
TPSCounter tpsCounter = new TPSCounter();
tpsCounter.simulateTransactions(1000);
}
}- 線程池:使用
ThreadPoolTaskExecutor管理并發(fā)事務(wù)。 - 事務(wù)管理:使用Spring的
@Transactional注解確保事務(wù)完整性。 - 異步處理:通過(guò)
@Async實(shí)現(xiàn)異步事務(wù)處理,提升并發(fā)能力。 - 調(diào)整線程池配置:根據(jù)實(shí)際負(fù)載和硬件資源進(jìn)行調(diào)整。
- 數(shù)據(jù)庫(kù)優(yōu)化:通過(guò)索引、緩存等手段提升數(shù)據(jù)庫(kù)處理能力。
- 異步與批處理:減少事務(wù)執(zhí)行時(shí)間,提高TPS。
其他重要指標(biāo)
響應(yīng)時(shí)間(Response Time)
定義:
響應(yīng)時(shí)間是指從用戶發(fā)起請(qǐng)求到收到系統(tǒng)響應(yīng)所經(jīng)歷的時(shí)間。它通常用來(lái)衡量系統(tǒng)處理請(qǐng)求的速度,是用戶體驗(yàn)的關(guān)鍵指標(biāo)之一。
- 直接影響用戶的滿意度和業(yè)務(wù)的轉(zhuǎn)化率。
- 幫助識(shí)別性能瓶頸和優(yōu)化系統(tǒng)性能。
計(jì)算方法:
響應(yīng)時(shí)間可以通過(guò)測(cè)量從發(fā)送請(qǐng)求到接收到響應(yīng)的時(shí)間間隔來(lái)計(jì)算。在代碼層面,可以使用各種性能監(jiān)控工具來(lái)自動(dòng)收集這些數(shù)據(jù)。
代碼示例:
public class ResponseTimeMeasure {
public static long measureResponseTime() {
long startTime = System.currentTimeMillis();
// 模擬請(qǐng)求處理
try {
Thread.sleep(100); // 假設(shè)處理請(qǐng)求需要100毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
public static void main(String[] args) {
long responseTime = measureResponseTime();
System.out.println("Response Time: " + responseTime + " ms");
}
}吞吐量(Throughput)
定義:
吞吐量是指系統(tǒng)在單位時(shí)間內(nèi)處理的請(qǐng)求數(shù)量,通常用來(lái)衡量系統(tǒng)的處理能力。
- 反映系統(tǒng)在高負(fù)載下的表現(xiàn)。
- 用于性能測(cè)試和資源規(guī)劃。
計(jì)算方法:
吞吐量可以通過(guò)測(cè)量單位時(shí)間內(nèi)成功處理的請(qǐng)求總數(shù)來(lái)計(jì)算。
代碼示例:
public class ThroughputMeasure {
public static void measureThroughput() {
long requestCount = 0;
long startTime = System.currentTimeMillis();
// 模擬請(qǐng)求處理
try {
for (int i = 0; i < 1000; i++) {
// 模擬處理請(qǐng)求
Thread.sleep(1); // 假設(shè)每個(gè)請(qǐng)求處理需要1毫秒
requestCount++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
System.out.println("Throughput: " + (requestCount / (elapsedTime / 1000.0)) + " requests/second");
}
public static void main(String[] args) {
measureThroughput();
}
}錯(cuò)誤率(Error Rate)
定義:
錯(cuò)誤率是指在一定時(shí)間內(nèi)失敗請(qǐng)求占總請(qǐng)求的比例。
- 反映系統(tǒng)的穩(wěn)定性和可靠性。
- 用于故障診斷和改進(jìn)系統(tǒng)質(zhì)量。
計(jì)算方法:
錯(cuò)誤率可以通過(guò)測(cè)量失敗請(qǐng)求數(shù)除以總請(qǐng)求數(shù)來(lái)計(jì)算。
代碼示例:
public class ErrorRateMeasure {
public static double measureErrorRate(int totalRequests, int failedRequests) {
return (double) failedRequests / totalRequests;
}
public static void main(String[] args) {
int totalRequests = 1000;
int failedRequests = 10;
double errorRate = measureErrorRate(totalRequests, failedRequests);
System.out.println("Error Rate: " + errorRate);
}
}并發(fā)用戶數(shù)(Concurrent Users)
定義:
并發(fā)用戶數(shù)是指在同一時(shí)間點(diǎn)上,系統(tǒng)中活躍的用戶數(shù)量。
- 反映系統(tǒng)的最大服務(wù)能力。
- 用于容量規(guī)劃和性能優(yōu)化。
計(jì)算方法:
并發(fā)用戶數(shù)可以通過(guò)監(jiān)控系統(tǒng)中同時(shí)在線的用戶數(shù)量來(lái)計(jì)算。
代碼示例:
import java.util.concurrent.atomic.AtomicInteger;
public class ConcurrentUsersMeasure {
private static final AtomicInteger concurrentUsers = new AtomicInteger(0);
public static void addUser() {
concurrentUsers.incrementAndGet();
System.out.println("Current Concurrent Users: " + concurrentUsers.get());
}
public static void removeUser() {
concurrentUsers.decrementAndGet();
System.out.println("Current Concurrent Users: " + concurrentUsers.get());
}
public static void main(String[] args) {
// 模擬用戶登錄和登出
addUser();
addUser();
removeUser();
}
}數(shù)據(jù)存儲(chǔ)與分析
使用數(shù)據(jù)庫(kù)(如MySQL)存儲(chǔ)
表設(shè)計(jì):
- 創(chuàng)建一個(gè)表來(lái)存儲(chǔ)事務(wù)或請(qǐng)求的詳細(xì)信息,包括時(shí)間戳、類型、狀態(tài)等。
CREATE TABLE transactions (
id INT AUTO_INCREMENT PRIMARY KEY,
transaction_data VARCHAR(255),
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(50)
);數(shù)據(jù)插入:
- 使用JDBC或Spring Data JPA將事務(wù)數(shù)據(jù)插入到MySQL中。
使用ElasticSearch進(jìn)行分析
- 數(shù)據(jù)導(dǎo)入:
- 使用Logstash或自定義腳本將數(shù)據(jù)從MySQL導(dǎo)入到ElasticSearch。
- 索引設(shè)計(jì):
- 設(shè)計(jì)合適的索引結(jié)構(gòu)以支持快速查詢和分析。
- 查詢與分析:
- 使用ElasticSearch的查詢DSL進(jìn)行復(fù)雜的查詢和分析。
可視化工具的選擇(如Grafana)
- Grafana簡(jiǎn)介:
- Grafana是一款開源的可視化工具,支持多種數(shù)據(jù)源,包括ElasticSearch。
- 配置數(shù)據(jù)源:
- 在Grafana中添加ElasticSearch作為數(shù)據(jù)源。
- 創(chuàng)建儀表板:
- 使用Grafana創(chuàng)建儀表板,展示關(guān)鍵指標(biāo)如TPS、QPS等。
- 實(shí)時(shí)監(jiān)控:
- 設(shè)置告警規(guī)則,一旦指標(biāo)超出預(yù)設(shè)閾值,立即通知相關(guān)人員。
總結(jié)與最佳實(shí)踐
指標(biāo)收集的常見陷阱
- 數(shù)據(jù)丟失:
- 由于網(wǎng)絡(luò)或系統(tǒng)故障,可能導(dǎo)致部分指標(biāo)數(shù)據(jù)丟失。
- 高延遲:
- 實(shí)時(shí)性要求高的場(chǎng)景中,延遲會(huì)影響監(jiān)控的準(zhǔn)確性。
- 數(shù)據(jù)冗余:
- 過(guò)多的無(wú)用數(shù)據(jù)會(huì)增加存儲(chǔ)和分析的復(fù)雜性。
- 不一致性:
- 不同數(shù)據(jù)源或系統(tǒng)之間的時(shí)間戳不一致,導(dǎo)致數(shù)據(jù)對(duì)齊困難。
- 性能開銷:
- 過(guò)于頻繁的統(tǒng)計(jì)和日志記錄可能影響系統(tǒng)性能。
提高統(tǒng)計(jì)精度的方法
- 分布式日志收集:
- 使用Kafka等消息隊(duì)列系統(tǒng),確保日志的實(shí)時(shí)收集和傳輸。
- 批量處理:
- 聚合數(shù)據(jù)后再進(jìn)行存儲(chǔ)和分析,減少系統(tǒng)負(fù)載。
- 使用緩存:
- 對(duì)于常用的統(tǒng)計(jì)結(jié)果,使用Redis等緩存存儲(chǔ),以提高訪問(wèn)速度。
- 時(shí)間同步:
- 確保所有數(shù)據(jù)源的時(shí)間同步,使用NTP等協(xié)議保持一致性。
- 數(shù)據(jù)清洗:
- 定期清理無(wú)效或重復(fù)的數(shù)據(jù),保持?jǐn)?shù)據(jù)庫(kù)的高效和準(zhǔn)確。
- 監(jiān)控與告警:
- 設(shè)置合理的告警規(guī)則,及時(shí)發(fā)現(xiàn)和處理異常。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot項(xiàng)目Slf4j沖突問(wèn)題及解決方案
在Spring Boot項(xiàng)目中使用Log4j2替代默認(rèn)的SLF4J實(shí)現(xiàn)時(shí),可能會(huì)遇到多個(gè)SLF4J實(shí)現(xiàn)的沖突,通過(guò)調(diào)整pom.xml文件的配置順序,并通過(guò)查看Maven依賴樹形關(guān)系,找到并排除沖突的依賴(例如jdbc依賴中的logback),可以解決這個(gè)問(wèn)題2025-12-12
idea?compile項(xiàng)目正常啟動(dòng)項(xiàng)目的時(shí)候build失敗報(bào)“找不到符號(hào)”等問(wèn)題及解決方案
這篇文章主要介紹了idea?compile項(xiàng)目正常,啟動(dòng)項(xiàng)目的時(shí)候build失敗,報(bào)“找不到符號(hào)”等問(wèn)題,這種問(wèn)題屬于lombok編譯失敗導(dǎo)致,可能原因是依賴jar包沒有更新到最新版本,需要的朋友可以參考下2023-10-10
Spring Boot中日志管理與異常處理實(shí)踐指南
本文系統(tǒng)化講解SpringBoot日志管理與異常處理,涵蓋Logback配置、分層異常處理、上下文記錄及ELK集成,強(qiáng)調(diào)日志分級(jí)、自定義異常設(shè)計(jì),增強(qiáng)應(yīng)用穩(wěn)定性與可維護(hù)性,感興趣的朋友跟隨小編一起看看吧2025-06-06
SpringBoot多環(huán)境切換的靈活配置詳細(xì)教程
在真實(shí)項(xiàng)目開發(fā)的時(shí)候,一定會(huì)有多個(gè)環(huán)境,下面這篇文章主要給大家介紹了關(guān)于SpringBoot多環(huán)境切換靈活配置的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04
深入學(xué)習(xí)java內(nèi)存化和函數(shù)式協(xié)同
這篇文章主要介紹了深入學(xué)習(xí)java內(nèi)存化和函數(shù)式協(xié)同,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06
Java調(diào)用Pytorch模型實(shí)現(xiàn)圖像識(shí)別
這篇文章主要為大家詳細(xì)介紹了Java如何調(diào)用Pytorch實(shí)現(xiàn)圖像識(shí)別功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-06-06
Swagger-boostrap-ui如何配置用戶名密碼訪問(wèn)
這篇文章主要介紹了Swagger-boostrap-ui如何配置用戶名密碼訪問(wèn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
關(guān)于@GetMapping和@GetMapping(value=““)的區(qū)別
這篇文章主要介紹了關(guān)于@GetMapping和@GetMapping(value=““)的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
mac下idea的svn密碼記不住的問(wèn)題及處理方法
這篇文章主要介紹了mac下idea的svn密碼記不住的問(wèn)題及處理方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09

