Jelajahi Sumber

Revert "Revert "1、增加百度翻译接口""

This reverts commit 0df1d23359e942f57a0c9260e041b38b90b923d3.
Neo 10 bulan lalu
induk
melakukan
2688eb41d2

+ 35 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/controller/TranslateApiController.java

@@ -0,0 +1,35 @@
+package org.jeecg.modules.api.okki.translate.controller;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpHeaders;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.api.okki.translate.dto.TranslateRequestDto;
+import org.jeecg.modules.api.okki.translate.dto.TranslateResults;
+import org.jeecg.modules.api.okki.translate.service.TranslateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.UnsupportedEncodingException;
+
+@RestController
+@Slf4j
+@RequestMapping("/website")
+public class TranslateApiController {
+
+    @Autowired
+    private TranslateService translateService;
+
+    @PostMapping(value = "/translate")
+    public Result<TranslateResults> add(@RequestBody TranslateRequestDto translateRequestDto, @RequestHeader(HttpHeaders.AUTHORIZATION) String authorization) throws UnsupportedEncodingException {
+        log.info("请求参数 param{} authorization{}", translateRequestDto.toString(), authorization);
+        String Authorization = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImRlYW4iLCJleHAiOjE3MTQ0NjU5Njl9.QdCBYR8mioXcKGi1n5RdMQ5RbJHCSGbE8dkdwYuOXh4";
+
+        if (!authorization.equals(Authorization)) {
+            return Result.error("sign 验证不通过");
+        }
+
+        TranslateResults translateResults = translateService.doTranslate(translateRequestDto);
+
+        return Result.OK(translateResults);
+    }
+}

+ 24 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/dto/RransResultBaidu.java

@@ -0,0 +1,24 @@
+package org.jeecg.modules.api.okki.translate.dto;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+import java.util.ArrayList;
+
+@Data
+public class RransResultBaidu {
+
+    @JSONField(name = "error_code")
+    private String errorCode;
+
+    @JSONField(name = "error_msg")
+    private String errorMsg;
+
+    private String from;
+
+    private String to;
+
+    @JSONField(name = "trans_result")
+    ArrayList<TransRresultSigle>  transResult;
+}
+

+ 11 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/dto/TransRresultSigle.java

@@ -0,0 +1,11 @@
+package org.jeecg.modules.api.okki.translate.dto;
+
+import lombok.Data;
+
+@Data
+public class TransRresultSigle {
+
+    private  String src;
+
+    private  String dst;
+}

+ 21 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/dto/TranslateRequestDto.java

@@ -0,0 +1,21 @@
+package org.jeecg.modules.api.okki.translate.dto;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+@Data
+public class TranslateRequestDto {
+
+    @JsonProperty("site_id")
+    private Integer siteId;
+
+    private String from;
+
+    private ArrayList<String> to;
+
+    private HashMap<String,String> contents;
+}

+ 13 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/dto/TranslateResults.java

@@ -0,0 +1,13 @@
+package org.jeecg.modules.api.okki.translate.dto;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class TranslateResults {
+
+    private String msg;
+
+    private Map data;
+}

+ 90 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/service/TranslateService.java

@@ -0,0 +1,90 @@
+package org.jeecg.modules.api.okki.translate.service;
+
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.modules.api.okki.translate.dto.RransResultBaidu;
+import org.jeecg.modules.api.okki.translate.dto.TransRresultSigle;
+import org.jeecg.modules.api.okki.translate.dto.TranslateRequestDto;
+import org.jeecg.modules.api.okki.translate.dto.TranslateResults;
+import org.jeecg.modules.api.okki.translate.tools.TransBaiduApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.UnsupportedEncodingException;
+import java.util.*;
+import java.util.concurrent.*;
+
+@Slf4j
+@Service
+public class TranslateService {
+
+    @Autowired
+    private TransBaiduApi transBaiduApi;
+
+    private final ExecutorService executorService = Executors.newFixedThreadPool(10);
+
+    public TranslateResults doTranslate(TranslateRequestDto translateRequestDto) throws UnsupportedEncodingException {
+        // TODO 站点信息校验
+
+        String fromLanguage = translateRequestDto.getFrom();
+        List<String> targetLanguages = translateRequestDto.getTo();
+        Map<String, String> contents = translateRequestDto.getContents();
+
+        TranslateResults results = new TranslateResults();
+        Map<String, Map<String, String>> translatedInfo = new ConcurrentHashMap<>();
+
+        List<Future<Void>> futures = new ArrayList<>();
+
+        // 预解码所有内容
+        Map<String, String> decodedContents = new HashMap<>();
+        for (Map.Entry<String, String> entry : contents.entrySet()) {
+            decodedContents.put(entry.getKey(), new String(Base64.getDecoder().decode(entry.getValue())));
+        }
+
+        for (String targetLanguage : targetLanguages) {
+            for (Map.Entry<String, String> entry : decodedContents.entrySet()) {
+                futures.add(executorService.submit(() -> {
+                    processTranslation(entry.getKey(), entry.getValue(), fromLanguage, targetLanguage, translatedInfo, contents.get(entry.getKey()));
+                    return null;
+                }));
+            }
+        }
+
+        // 等待所有任务完成
+        for (Future<Void> future : futures) {
+            try {
+                future.get();
+            } catch (InterruptedException | ExecutionException e) {
+                log.error("翻译任务执行出错", e);
+                Thread.currentThread().interrupt();  // 处理中断
+            }
+        }
+
+        results.setMsg("successful");
+        results.setData(translatedInfo);
+
+        return results;
+    }
+
+    private void processTranslation(String key, String decodedSrc, String fromLanguage, String targetLanguage, Map<String, Map<String, String>> translatedInfo, String originalValue) {
+        try {
+            String transObj = transBaiduApi.getTransResult(decodedSrc, fromLanguage, targetLanguage);
+
+            RransResultBaidu resultBaidu = JSON.parseObject(transObj, RransResultBaidu.class);
+
+            if (resultBaidu.getErrorCode() == null && !resultBaidu.getTransResult().isEmpty()) {
+                for (TransRresultSigle singleResult : resultBaidu.getTransResult()) {
+                    String encodedDst = Base64.getEncoder().encodeToString(singleResult.getDst().getBytes());
+
+                    Map<String, String> trans = translatedInfo.computeIfAbsent(key, k -> new HashMap<>());
+                    trans.put(targetLanguage, encodedDst);
+                    trans.put("_original", originalValue);
+                }
+            } else {
+                log.error("调用百度翻译发生错误!error_code:{} error_msg:{}", resultBaidu.getErrorCode(), resultBaidu.getErrorMsg());
+            }
+        } catch (Exception e) {
+            log.error("处理翻译时发生异常", e);
+        }
+    }
+}

+ 159 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/tools/HttpGet.java

@@ -0,0 +1,159 @@
+package org.jeecg.modules.api.okki.translate.tools;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+class HttpGet {
+    protected static final int SOCKET_TIMEOUT = 10000; // 10S
+    protected static final String GET = "GET";
+
+    public static String get(String host, Map<String, String> params) {
+        try {
+            // 设置SSLContext
+            SSLContext sslcontext = SSLContext.getInstance("TLS");
+            sslcontext.init(null, new TrustManager[] { myX509TrustManager }, null);
+
+            String sendUrl = getUrlWithQueryString(host, params);
+
+            // System.out.println("URL:" + sendUrl);
+
+            URL uri = new URL(sendUrl); // 创建URL对象
+            HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
+            if (conn instanceof HttpsURLConnection) {
+                ((HttpsURLConnection) conn).setSSLSocketFactory(sslcontext.getSocketFactory());
+            }
+
+            conn.setConnectTimeout(SOCKET_TIMEOUT); // 设置相应超时
+            conn.setRequestMethod(GET);
+            int statusCode = conn.getResponseCode();
+            if (statusCode != HttpURLConnection.HTTP_OK) {
+                System.out.println("Http错误码:" + statusCode);
+            }
+
+            // 读取服务器的数据
+            InputStream is = conn.getInputStream();
+            BufferedReader br = new BufferedReader(new InputStreamReader(is));
+            StringBuilder builder = new StringBuilder();
+            String line = null;
+            while ((line = br.readLine()) != null) {
+                builder.append(line);
+            }
+
+            String text = builder.toString();
+
+            close(br); // 关闭数据流
+            close(is); // 关闭数据流
+            conn.disconnect(); // 断开连接
+
+            return text;
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (KeyManagementException e) {
+            e.printStackTrace();
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    public static String getUrlWithQueryString(String url, Map<String, String> params) {
+        if (params == null) {
+            return url;
+        }
+
+        StringBuilder builder = new StringBuilder(url);
+        if (url.contains("?")) {
+            builder.append("&");
+        } else {
+            builder.append("?");
+        }
+
+        int i = 0;
+        for (String key : params.keySet()) {
+            String value = params.get(key);
+            if (value == null) { // 过滤空的key
+                continue;
+            }
+
+            if (i != 0) {
+                builder.append('&');
+            }
+
+            builder.append(key);
+            builder.append('=');
+            builder.append(encode(value));
+
+            i++;
+        }
+
+        return builder.toString();
+    }
+
+    protected static void close(Closeable closeable) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 对输入的字符串进行URL编码, 即转换为%20这种形式
+     * 
+     * @param input 原文
+     * @return URL编码. 如果编码失败, 则返回原文
+     */
+    public static String encode(String input) {
+        if (input == null) {
+            return "";
+        }
+
+        try {
+            return URLEncoder.encode(input, "utf-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+
+        return input;
+    }
+
+    private static TrustManager myX509TrustManager = new X509TrustManager() {
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+        }
+
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+        }
+    };
+
+}

+ 117 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/tools/MD5.java

@@ -0,0 +1,117 @@
+package org.jeecg.modules.api.okki.translate.tools;
+
+import java.io.*;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * MD5编码相关的类
+ * 
+ * @author wangjingtao
+ * 
+ */
+public class MD5 {
+    // 首先初始化一个字符数组,用来存放每个16进制字符
+    private static final char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
+            'e', 'f' };
+
+    /**
+     * 获得一个字符串的MD5值
+     * 
+     * @param input 输入的字符串
+     * @return 输入字符串的MD5值
+     * 
+     */
+    public static String md5(String input) throws UnsupportedEncodingException {
+        if (input == null)
+            return null;
+
+        try {
+            // 拿到一个MD5转换器(如果想要SHA1参数换成”SHA1”)
+            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
+            // 输入的字符串转换成字节数组
+            byte[] inputByteArray = input.getBytes("utf-8");
+            // inputByteArray是输入字符串转换得到的字节数组
+            messageDigest.update(inputByteArray);
+            // 转换并返回结果,也是字节数组,包含16个元素
+            byte[] resultByteArray = messageDigest.digest();
+            // 字符数组转换成字符串返回
+            return byteArrayToHex(resultByteArray);
+        } catch (NoSuchAlgorithmException e) {
+            return null;
+        }
+    }
+
+    /**
+     * 获取文件的MD5值
+     * 
+     * @param file
+     * @return
+     */
+    public static String md5(File file) {
+        try {
+            if (!file.isFile()) {
+                System.err.println("文件" + file.getAbsolutePath() + "不存在或者不是文件");
+                return null;
+            }
+
+            FileInputStream in = new FileInputStream(file);
+
+            String result = md5(in);
+
+            in.close();
+
+            return result;
+
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    public static String md5(InputStream in) {
+
+        try {
+            MessageDigest messagedigest = MessageDigest.getInstance("MD5");
+
+            byte[] buffer = new byte[1024];
+            int read = 0;
+            while ((read = in.read(buffer)) != -1) {
+                messagedigest.update(buffer, 0, read);
+            }
+
+            in.close();
+
+            String result = byteArrayToHex(messagedigest.digest());
+
+            return result;
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    private static String byteArrayToHex(byte[] byteArray) {
+        // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
+        char[] resultCharArray = new char[byteArray.length * 2];
+        // 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
+        int index = 0;
+        for (byte b : byteArray) {
+            resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
+            resultCharArray[index++] = hexDigits[b & 0xf];
+        }
+
+        // 字符数组组合成字符串返回
+        return new String(resultCharArray);
+
+    }
+
+}

+ 49 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/okki/translate/tools/TransBaiduApi.java

@@ -0,0 +1,49 @@
+package org.jeecg.modules.api.okki.translate.tools;
+
+import org.springframework.stereotype.Service;
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class TransBaiduApi {
+
+    private static final String APP_ID = "20240513002050555";
+    private static final String SECURITY_KEY = "B69U3yzNw9_xdvpSZooR";
+
+    private String appid;
+    private  String securityKey;
+
+    private static final String TRANS_API_HOST = "http://api.fanyi.baidu.com/api/trans/vip/translate";
+
+    public TransBaiduApi() {
+        this.appid = APP_ID;
+        this.securityKey = SECURITY_KEY;
+    }
+
+    public String getTransResult(String query, String from, String to) throws UnsupportedEncodingException {
+        Map<String, String> params = buildParams(query, from, to);
+        return HttpGet.get(TRANS_API_HOST, params);
+    }
+
+    private Map<String, String> buildParams(String query, String from, String to) throws UnsupportedEncodingException {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("q", query);
+        params.put("from", from);
+        params.put("to", to);
+
+        params.put("appid", appid);
+
+        // 随机数
+        String salt = String.valueOf(System.currentTimeMillis());
+        params.put("salt", salt);
+
+        // 签名
+        String src = appid + query + salt + securityKey; // 加密前的原文
+        params.put("sign", MD5.md5(src));
+
+        return params;
+    }
+
+}