使用Maven和SpringBoot搭建客戶(hù)數(shù)據(jù)清洗項(xiàng)目框架
一、第一步:環(huán)境搭建——給Java項(xiàng)目裝上‘數(shù)據(jù)吸塵器’
目標(biāo):用Maven和Spring Boot搭建數(shù)據(jù)清洗項(xiàng)目框架。
步驟:
創(chuàng)建Maven項(xiàng)目:
<!-- pom.xml:添加依賴(lài) -->
<dependencies>
<!-- 數(shù)據(jù)庫(kù)連接 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
<!-- 函數(shù)式編程工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- 數(shù)據(jù)驗(yàn)證 -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
</dependencies>
配置數(shù)據(jù)庫(kù)連接:
# application.properties:連接MySQL spring.datasource.url=jdbc:mysql://localhost:3306/customer_db spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
二、第二步:數(shù)據(jù)采集——用Java抓取‘臟數(shù)據(jù)’
目標(biāo):從數(shù)據(jù)庫(kù)、API、CSV等多源采集客戶(hù)數(shù)據(jù)。
步驟:
數(shù)據(jù)庫(kù)查詢(xún):
// CustomerDAO.java:從MySQL讀取客戶(hù)數(shù)據(jù)
import java.sql.*;
import java.util.*;
public class CustomerDAO {
public List<Map<String, Object>> fetchDirtyData() {
String query = "SELECT * FROM customers WHERE status = 'pending'";
List<Map<String, Object>> data = new ArrayList<>();
try (Connection conn = DriverManager.getConnection("jdbc:mysql://...", "...", "...");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query)) {
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
Map<String, Object> row = new HashMap<>();
for (int i = 1; i <= meta.getColumnCount(); i++) {
row.put(meta.getColumnName(i), rs.getObject(i));
}
data.add(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
return data;
}
}
API數(shù)據(jù)采集:
// ApiService.java:調(diào)用第三方API獲取數(shù)據(jù)
import java.net.http.*;
import java.net.URI;
import java.util.concurrent.*;
public class ApiService {
public String fetchDataFromAPI() {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/customers"))
.build();
try {
return client.send(request, BodyHandlers.ofString()).body();
} catch (Exception e) {
return "{}"; // 返回空對(duì)象避免崩潰
}
}
}
三、第三步:數(shù)據(jù)清洗——用Java的‘三板斧’搞定臟數(shù)據(jù)
目標(biāo):用正則表達(dá)式、函數(shù)式編程、并行流清洗數(shù)據(jù)。
步驟:
處理缺失值與格式問(wèn)題:
// DataCleaner.java:清洗單個(gè)字段
import org.apache.commons.lang3.StringUtils;
public class DataCleaner {
public static String cleanPhone(String rawPhone) {
// 去除非數(shù)字字符
String cleaned = StringUtils.remove(rawPhone, " ").replaceAll("[^0-9]", "");
// 補(bǔ)全11位手機(jī)號(hào)
if (cleaned.length() == 10) {
return "1" + cleaned; // 假設(shè)國(guó)內(nèi)手機(jī)號(hào)
}
return cleaned;
}
}
批量清洗與去重:
// BatchProcessor.java:并行處理數(shù)據(jù)
public class BatchProcessor {
public static List<Map<String, Object>> cleanData(List<Map<String, Object>> rawData) {
return rawData.parallelStream()
.filter(row -> row.get("email") != null) // 過(guò)濾缺失郵箱
.map(row -> {
Map<String, Object> cleanedRow = new HashMap<>(row);
cleanedRow.put("phone", DataCleaner.cleanPhone((String) row.get("phone")));
cleanedRow.put("address", row.get("address").toString().trim()); // 去除前后空格
return cleanedRow;
})
.distinct() // 去重(需重寫(xiě)equals/hashCode)
.collect(Collectors.toList());
}
}
四、第四步:數(shù)據(jù)集成——用ETL讓數(shù)據(jù)‘全家福’
目標(biāo):將清洗后的數(shù)據(jù)整合到目標(biāo)系統(tǒng)(如Hadoop、數(shù)據(jù)庫(kù))。
步驟:
數(shù)據(jù)轉(zhuǎn)換為JSON格式:
// DataTransformer.java:使用Jackson庫(kù)
import com.fasterxml.jackson.databind.ObjectMapper;
public class DataTransformer {
public String toJson(List<Map<String, Object>> data) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(data);
} catch (Exception e) {
return "[]";
}
}
}
寫(xiě)入HDFS(Hadoop):
// HdfsWriter.java:用Hadoop API
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
public class HdfsWriter {
public void writeToFile(String data) {
Configuration conf = new Configuration();
Path path = new Path("/user/hadoop/cleaned_customers.json");
try (FSDataOutputStream out = FileSystem.get(conf).create(path)) {
out.write(data.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
五、第五步:質(zhì)量驗(yàn)證——給數(shù)據(jù)打‘體檢報(bào)告’
目標(biāo):用斷言和統(tǒng)計(jì)分析確保數(shù)據(jù)質(zhì)量。
步驟:
數(shù)據(jù)校驗(yàn)規(guī)則:
// DataValidator.java:校驗(yàn)手機(jī)號(hào)格式
public class DataValidator {
public static boolean validatePhone(String phone) {
// 中國(guó)手機(jī)號(hào)正則:1開(kāi)頭,11位數(shù)字
return phone != null && phone.matches("^1\\d{10}$");
}
}
生成質(zhì)量報(bào)告:
// QualityReport.java:統(tǒng)計(jì)清洗結(jié)果
public class QualityReport {
public static void generateReport(List<Map<String, Object>> data) {
long validPhones = data.stream()
.filter(row -> DataValidator.validatePhone((String) row.get("phone")))
.count();
System.out.println("? 有效手機(jī)號(hào)數(shù)量:" + validPhones);
System.out.println("?? 總數(shù)據(jù)量:" + data.size());
System.out.println("?? 清洗完成!");
}
}
六、實(shí)戰(zhàn)案例:電商客戶(hù)數(shù)據(jù)‘變形記’
場(chǎng)景:
清洗包含臟數(shù)據(jù)的電商客戶(hù)信息(如電話(huà)格式錯(cuò)誤、地址缺失)。
完整流程代碼:
// Main.java:端到端流程
public class Main {
public static void main(String[] args) {
// 1. 采集數(shù)據(jù)
CustomerDAO dao = new CustomerDAO();
List<Map<String, Object>> raw = dao.fetchDirtyData();
// 2. 清洗數(shù)據(jù)
List<Map<String, Object>> cleaned = BatchProcessor.cleanData(raw);
// 3. 驗(yàn)證數(shù)據(jù)
QualityReport.generateReport(cleaned);
// 4. 輸出到HDFS
HdfsWriter writer = new HdfsWriter();
writer.writeToFile(new DataTransformer().toJson(cleaned));
System.out.println("?? 數(shù)據(jù)清洗大業(yè)完成!");
}
}
七、常見(jiàn)問(wèn)題與解決方案
Q1:數(shù)據(jù)量太大,Java內(nèi)存溢出?
解決:
// 使用分頁(yè)查詢(xún)
public List<Map<String, Object>> fetchDirtyData(int offset, int limit) {
String query = "SELECT * FROM customers WHERE status = 'pending' LIMIT " + offset + ", " + limit;
// ...
}
Q2:API返回?cái)?shù)據(jù)格式不一致?
解決:
// 使用Optional處理可能缺失的字段
public String getSafeField(JsonNode node, String key) {
return node.has(key) ? node.get(key).asText() : "";
}
通過(guò)本文,你已經(jīng)掌握了:
- 環(huán)境搭建:用Maven和Spring Boot快速啟動(dòng)項(xiàng)目。
- 數(shù)據(jù)采集:從數(shù)據(jù)庫(kù)、API、CSV等多源抓取數(shù)據(jù)。
- 數(shù)據(jù)清洗:用正則表達(dá)式、函數(shù)式編程處理缺失值、格式問(wèn)題。
- 數(shù)據(jù)集成:通過(guò)ETL將數(shù)據(jù)寫(xiě)入Hadoop或數(shù)據(jù)庫(kù)。
- 質(zhì)量驗(yàn)證:用斷言和統(tǒng)計(jì)分析確保數(shù)據(jù)合規(guī)。
- 實(shí)戰(zhàn)案例:電商客戶(hù)數(shù)據(jù)的全流程清洗。
- 故障排除:內(nèi)存溢出、API數(shù)據(jù)不一致等問(wèn)題的解決方法。
到此這篇關(guān)于使用Maven和SpringBoot搭建客戶(hù)數(shù)據(jù)清洗項(xiàng)目框架的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)清洗內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring?boot前后端交互之?dāng)?shù)據(jù)格式轉(zhuǎn)換問(wèn)題
這篇文章主要介紹了spring?boot前后端交互之?dāng)?shù)據(jù)格式轉(zhuǎn)換,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01
Springboot內(nèi)置tomcat配置虛擬路徑過(guò)程解析
這篇文章主要介紹了Springboot內(nèi)置tomcat配置虛擬路徑過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
java解析php函數(shù)json_encode unicode 編碼問(wèn)題
這篇文章主要介紹了java解析php函數(shù)json_encode unicode 編碼問(wèn)題,需要的朋友可以參考下2016-04-04
Springboot登錄驗(yàn)證的統(tǒng)一攔截處理的實(shí)現(xiàn)
如果不進(jìn)行統(tǒng)一的攔截處理,每次用戶(hù)請(qǐng)求你都要去進(jìn)行用戶(hù)的信息驗(yàn)證,所以本文主要介紹了Springboot登錄驗(yàn)證的統(tǒng)一攔截處理的實(shí)現(xiàn),感興趣的可以了解一下,感興趣的可以了解一下2023-09-09
單元測(cè)試 @mock與@SpringBootTest的使用
這篇文章主要介紹了單元測(cè)試 @mock與@SpringBootTest的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
SpringBoot2整合Redis實(shí)現(xiàn)讀寫(xiě)操作
Redis,對(duì)于大家來(lái)說(shuō)應(yīng)該不陌生,是經(jīng)常使用的開(kāi)發(fā)技術(shù)之一。本文將結(jié)合實(shí)例代碼,介紹SpringBoot2整合Redis實(shí)現(xiàn)讀寫(xiě)操作,感興趣的小伙伴們可以參考一下2021-07-07

