格式修改
This commit is contained in:
+3
-5
@@ -1,16 +1,14 @@
|
||||
package com.baiyue.integration.provider;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import com.baiyue.integration.config.IntegrationProperties;
|
||||
import com.baiyue.integration.dto.ProviderStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AmazonLogisticsAdapter implements IntegrationProviderAdapter {
|
||||
private final IntegrationProperties properties;
|
||||
|
||||
public AmazonLogisticsAdapter(IntegrationProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
@Resource private IntegrationProperties properties;
|
||||
|
||||
@Override
|
||||
public ProviderStatus status() {
|
||||
|
||||
+3
-5
@@ -1,16 +1,14 @@
|
||||
package com.baiyue.integration.provider;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import com.baiyue.integration.config.IntegrationProperties;
|
||||
import com.baiyue.integration.dto.ProviderStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class BaiduOcrAdapter implements IntegrationProviderAdapter {
|
||||
private final IntegrationProperties properties;
|
||||
|
||||
public BaiduOcrAdapter(IntegrationProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
@Resource private IntegrationProperties properties;
|
||||
|
||||
@Override
|
||||
public ProviderStatus status() {
|
||||
|
||||
+11
-7
@@ -1,5 +1,8 @@
|
||||
package com.baiyue.integration.provider.ocr;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.integration.config.IntegrationProperties;
|
||||
@@ -31,18 +34,19 @@ public class BaiduMeterClient {
|
||||
private static final int QPS_LIMIT_ERROR_CODE = 18;
|
||||
private static final long INITIAL_RETRY_DELAY_MILLIS = 1_000;
|
||||
|
||||
private final IntegrationProperties.BaiduOcr config;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final HttpClient httpClient;
|
||||
@Resource private IntegrationProperties properties;
|
||||
@Resource private ObjectMapper objectMapper;
|
||||
private IntegrationProperties.BaiduOcr config;
|
||||
private HttpClient httpClient;
|
||||
private final Object requestRateLock = new Object();
|
||||
|
||||
private volatile CachedToken cachedToken;
|
||||
private long nextRequestAtMillis;
|
||||
|
||||
public BaiduMeterClient(IntegrationProperties properties, ObjectMapper objectMapper) {
|
||||
this.config = properties.baiduOcr();
|
||||
this.objectMapper = objectMapper;
|
||||
this.httpClient = HttpClient.newBuilder()
|
||||
@PostConstruct
|
||||
void initializeClient() {
|
||||
config = properties.baiduOcr();
|
||||
httpClient = HttpClient.newBuilder()
|
||||
.connectTimeout(config == null ? java.time.Duration.ofSeconds(10)
|
||||
: config.effectiveConnectTimeout())
|
||||
.build();
|
||||
|
||||
+6
-2
@@ -1,5 +1,7 @@
|
||||
package com.baiyue.integration.security;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -10,9 +12,11 @@ import java.security.MessageDigest;
|
||||
|
||||
@Component
|
||||
public class InternalServiceTokenGuard {
|
||||
private final byte[] expectedToken;
|
||||
@Value("${baiyue.security.internal-service-token}") private String token;
|
||||
private byte[] expectedToken;
|
||||
|
||||
public InternalServiceTokenGuard(@Value("${baiyue.security.internal-service-token}") String token) {
|
||||
@PostConstruct
|
||||
void initializeToken() {
|
||||
if (token == null || token.getBytes(StandardCharsets.UTF_8).length < 32) {
|
||||
throw new IllegalStateException("INTERNAL_SERVICE_TOKEN 至少需要 32 字节");
|
||||
}
|
||||
|
||||
+3
-5
@@ -1,5 +1,7 @@
|
||||
package com.baiyue.integration.service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import com.baiyue.integration.dto.ProviderStatus;
|
||||
import com.baiyue.integration.provider.IntegrationProviderAdapter;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -8,11 +10,7 @@ import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ProviderStatusService {
|
||||
private final List<IntegrationProviderAdapter> adapters;
|
||||
|
||||
public ProviderStatusService(List<IntegrationProviderAdapter> adapters) {
|
||||
this.adapters = adapters;
|
||||
}
|
||||
@Resource private List<IntegrationProviderAdapter> adapters;
|
||||
|
||||
public List<ProviderStatus> providers() {
|
||||
return adapters.stream().map(IntegrationProviderAdapter::status).toList();
|
||||
|
||||
+8
-20
@@ -1,5 +1,7 @@
|
||||
package com.baiyue.integration.service.ocr;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.integration.config.IntegrationProperties;
|
||||
@@ -33,28 +35,14 @@ import java.util.stream.Stream;
|
||||
public class WeightOcrBatchService {
|
||||
private static final Set<String> SUPPORTED_EXTENSIONS = Set.of("jpg", "jpeg", "png", "bmp");
|
||||
|
||||
private final IntegrationProperties properties;
|
||||
private final WeightOcrStoragePolicy storagePolicy;
|
||||
private final ImageCropper imageCropper;
|
||||
private final BaiduMeterClient baiduMeterClient;
|
||||
private final WeightCandidateSelector candidateSelector;
|
||||
private final ObjectMapper objectMapper;
|
||||
@Resource private IntegrationProperties properties;
|
||||
@Resource private WeightOcrStoragePolicy storagePolicy;
|
||||
@Resource private ImageCropper imageCropper;
|
||||
@Resource private BaiduMeterClient baiduMeterClient;
|
||||
@Resource private WeightCandidateSelector candidateSelector;
|
||||
@Resource private ObjectMapper objectMapper;
|
||||
private final Semaphore batchSlot = new Semaphore(1);
|
||||
|
||||
public WeightOcrBatchService(IntegrationProperties properties,
|
||||
WeightOcrStoragePolicy storagePolicy,
|
||||
ImageCropper imageCropper,
|
||||
BaiduMeterClient baiduMeterClient,
|
||||
WeightCandidateSelector candidateSelector,
|
||||
ObjectMapper objectMapper) {
|
||||
this.properties = properties;
|
||||
this.storagePolicy = storagePolicy;
|
||||
this.imageCropper = imageCropper;
|
||||
this.baiduMeterClient = baiduMeterClient;
|
||||
this.candidateSelector = candidateSelector;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
public WeightOcrBatchResult recognize(WeightOcrBatchRequest request) throws IOException {
|
||||
baiduMeterClient.validateReady();
|
||||
if (!batchSlot.tryAcquire()) {
|
||||
|
||||
+4
-7
@@ -1,5 +1,7 @@
|
||||
package com.baiyue.integration.service.ocr;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.integration.config.IntegrationProperties;
|
||||
@@ -19,13 +21,8 @@ import java.util.UUID;
|
||||
@Service
|
||||
public class WeightOcrSingleImageService {
|
||||
private static final Set<String> CONTENT_TYPES = Set.of("image/jpeg", "image/png", "image/bmp");
|
||||
private final IntegrationProperties properties;
|
||||
private final WeightOcrBatchService batches;
|
||||
|
||||
public WeightOcrSingleImageService(IntegrationProperties properties, WeightOcrBatchService batches) {
|
||||
this.properties = properties;
|
||||
this.batches = batches;
|
||||
}
|
||||
@Resource private IntegrationProperties properties;
|
||||
@Resource private WeightOcrBatchService batches;
|
||||
|
||||
public WeightOcrImageResult recognize(MultipartFile file) throws IOException {
|
||||
IntegrationProperties.BaiduOcr config = properties.baiduOcr();
|
||||
|
||||
+3
-5
@@ -1,5 +1,7 @@
|
||||
package com.baiyue.integration.service.ocr;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.integration.config.IntegrationProperties;
|
||||
@@ -14,11 +16,7 @@ import java.nio.file.Path;
|
||||
*/
|
||||
@Component
|
||||
public class WeightOcrStoragePolicy {
|
||||
private final IntegrationProperties properties;
|
||||
|
||||
public WeightOcrStoragePolicy(IntegrationProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
@Resource private IntegrationProperties properties;
|
||||
|
||||
public BatchPaths resolve(String inputValue, String outputValue, String batchId) throws IOException {
|
||||
IntegrationProperties.BaiduOcr config = requireConfig();
|
||||
|
||||
@@ -72,6 +72,6 @@ logging:
|
||||
rollingpolicy:
|
||||
file-name-pattern: "${LOGGING_ROLLING_FILE_NAME_PATTERN:${LOG_PATH:./logs}/${spring.application.name}.%d{yyyy-MM-dd}.%i.log.gz}"
|
||||
max-file-size: "${LOGGING_ROLLING_MAX_FILE_SIZE:100MB}"
|
||||
max-history: "${LOGGING_ROLLING_MAX_HISTORY:30}"
|
||||
max-history: "${LOGGING_ROLLING_MAX_HISTORY:7}"
|
||||
total-size-cap: "${LOGGING_ROLLING_TOTAL_SIZE_CAP:5GB}"
|
||||
clean-history-on-start: "${LOGGING_ROLLING_CLEAN_HISTORY_ON_START:false}"
|
||||
|
||||
+19
-6
@@ -6,10 +6,15 @@ import com.baiyue.integration.dto.ocr.WeightOcrBatchRequest;
|
||||
import com.baiyue.integration.dto.ocr.WeightOcrImageResult.Status;
|
||||
import com.baiyue.integration.provider.ocr.BaiduMeterClient;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.springframework.util.unit.DataSize;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.Color;
|
||||
@@ -26,9 +31,14 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@DisplayName("OCR 重量批量识别功能")
|
||||
@SpringJUnitConfig(classes = {WeightOcrBatchService.class, WeightOcrStoragePolicy.class,
|
||||
ImageCropper.class, WeightCandidateSelector.class, WeightOcrBatchServiceTest.TestConfig.class})
|
||||
class WeightOcrBatchServiceTest {
|
||||
@TempDir
|
||||
Path tempDirectory;
|
||||
@MockBean private IntegrationProperties properties;
|
||||
@MockBean private BaiduMeterClient client;
|
||||
@Resource private WeightOcrBatchService service;
|
||||
|
||||
@Test
|
||||
void completesBatchAndWritesArtifactsWithoutCallingRealProvider() throws Exception {
|
||||
@@ -43,15 +53,10 @@ class WeightOcrBatchServiceTest {
|
||||
}
|
||||
ImageIO.write(image, "png", batchInput.resolve("weight.png").toFile());
|
||||
|
||||
IntegrationProperties properties = properties(inputRoot, outputRoot);
|
||||
BaiduMeterClient client = mock(BaiduMeterClient.class);
|
||||
when(properties.baiduOcr()).thenReturn(properties(inputRoot, outputRoot).baiduOcr());
|
||||
when(client.recognize(any())).thenReturn(new BaiduMeterClient.MeterResponse(
|
||||
"{\"words_result\":[]}",
|
||||
List.of(new OcrCandidate("12.35", 0.98, 10, 10, 80, 30))));
|
||||
ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();
|
||||
WeightOcrBatchService service = new WeightOcrBatchService(
|
||||
properties, new WeightOcrStoragePolicy(properties), new ImageCropper(), client,
|
||||
new WeightCandidateSelector(), objectMapper);
|
||||
|
||||
var result = service.recognize(new WeightOcrBatchRequest("batch-a", null, null, null, false));
|
||||
|
||||
@@ -72,4 +77,12 @@ class WeightOcrBatchServiceTest {
|
||||
50, Duration.ZERO, 0);
|
||||
return new IntegrationProperties(baidu, null);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class TestConfig {
|
||||
@Bean
|
||||
ObjectMapper objectMapper() {
|
||||
return new ObjectMapper().findAndRegisterModules();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -7,6 +7,9 @@ import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.springframework.util.unit.DataSize;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
@@ -15,17 +18,21 @@ import java.time.Duration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@DisplayName("OCR 文件存储策略功能")
|
||||
@SpringJUnitConfig(WeightOcrStoragePolicy.class)
|
||||
class WeightOcrStoragePolicyTest {
|
||||
@TempDir
|
||||
Path tempDirectory;
|
||||
@MockBean private IntegrationProperties properties;
|
||||
@Resource private WeightOcrStoragePolicy policy;
|
||||
|
||||
@Test
|
||||
void resolvesDirectoriesInsideConfiguredRoots() throws Exception {
|
||||
Path input = Files.createDirectories(tempDirectory.resolve("input/batch-a"));
|
||||
Path outputRoot = tempDirectory.resolve("output");
|
||||
WeightOcrStoragePolicy policy = new WeightOcrStoragePolicy(properties(input.getParent(), outputRoot));
|
||||
when(properties.baiduOcr()).thenReturn(config(input.getParent(), outputRoot));
|
||||
|
||||
WeightOcrStoragePolicy.BatchPaths paths = policy.resolve("batch-a", null, "batch-id");
|
||||
|
||||
@@ -38,7 +45,7 @@ class WeightOcrStoragePolicyTest {
|
||||
Path inputRoot = Files.createDirectories(tempDirectory.resolve("input"));
|
||||
Path outputRoot = tempDirectory.resolve("output");
|
||||
Path outside = Files.createDirectories(tempDirectory.resolve("outside"));
|
||||
WeightOcrStoragePolicy policy = new WeightOcrStoragePolicy(properties(inputRoot, outputRoot));
|
||||
when(properties.baiduOcr()).thenReturn(config(inputRoot, outputRoot));
|
||||
|
||||
assertThatThrownBy(() -> policy.resolve(outside.toString(), null, "batch-id"))
|
||||
.isInstanceOfSatisfying(BizException.class,
|
||||
@@ -48,12 +55,12 @@ class WeightOcrStoragePolicyTest {
|
||||
exception -> assertThat(exception.getResultCode()).isEqualTo(ResultCode.FORBIDDEN));
|
||||
}
|
||||
|
||||
private IntegrationProperties properties(Path inputRoot, Path outputRoot) {
|
||||
private IntegrationProperties.BaiduOcr config(Path inputRoot, Path outputRoot) {
|
||||
IntegrationProperties.BaiduOcr baidu = new IntegrationProperties.BaiduOcr(
|
||||
true, "key", "secret", URI.create("https://example.com/token"),
|
||||
URI.create("https://example.com/meter"), Duration.ofSeconds(1), Duration.ofSeconds(1),
|
||||
inputRoot, outputRoot, DataSize.ofMegabytes(3), 40_000_000L,
|
||||
50, Duration.ZERO, 0);
|
||||
return new IntegrationProperties(baidu, null);
|
||||
return baidu;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user