Kaynağa Gözat

后端:新增进入采招网获取招标信息

余思翰 2 hafta önce
ebeveyn
işleme
2e0f93594c

+ 120
- 37
oa-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/oa/CmcBidController.java Dosyayı Görüntüle

@@ -1,49 +1,132 @@
1 1
 package com.ruoyi.web.controller.oa;
2 2
 
3
-import com.ruoyi.common.core.controller.BaseController;
4
-import com.ruoyi.common.utils.http.HttpUtils;
5
-import org.springframework.http.HttpHeaders;
6
-import org.springframework.http.MediaType;
7
-import org.springframework.http.ResponseEntity;
8
-import org.springframework.web.bind.annotation.*;
9
-
10
-import java.io.UnsupportedEncodingException;
3
+import org.springframework.web.bind.annotation.GetMapping;
4
+import org.springframework.web.bind.annotation.RestController;
5
+import javax.servlet.http.HttpServletResponse;
6
+import java.io.BufferedReader;
7
+import java.io.IOException;
8
+import java.io.InputStream;
9
+import java.io.InputStreamReader;
10
+import java.net.HttpURLConnection;
11
+import java.net.URL;
11 12
 import java.net.URLEncoder;
12 13
 import java.nio.charset.StandardCharsets;
13
-
14
+import java.util.zip.GZIPInputStream;
14 15
 
15 16
 /**
16
- * cmc招标采购Controller
17
- * 
18
- * @author cmc
19
- * @date 2024-04-07
17
+ * 招投标代理接口控制器(方案2优化版)
18
+ * 核心优化:自动资源关闭、参数校验、异常处理、响应流优化、连接复用
20 19
  */
21 20
 @RestController
22
-@RequestMapping("/oa/bid")
23
-public class CmcBidController extends BaseController
24
-{
21
+public class CmcBidController {
22
+
23
+    // 连接超时时间(毫秒)
24
+    private static final int CONNECT_TIMEOUT = 5000;
25
+    // 读取超时时间(毫秒)
26
+    private static final int READ_TIMEOUT = 10000;
27
+
28
+    @GetMapping("/oa/bid/list")
29
+    public void proxyUrl(String url, HttpServletResponse response) {
30
+        // 1. 参数校验(方案2核心:防非法URL、空参数)
31
+        if (url == null || url.trim().isEmpty()) {
32
+            setErrorResponse(response, "请求参数异常:URL不能为空");
33
+            return;
34
+        }
35
+        // 基础URL合法性校验(可根据实际业务补充白名单)
36
+        if (!url.startsWith("http://") && !url.startsWith("https://")) {
37
+            setErrorResponse(response, "请求参数异常:URL必须以http/https开头");
38
+            return;
39
+        }
40
+
41
+        // 2. 响应头基础配置(方案2:强化编码和缓存控制)
42
+        response.setContentType("text/html;charset=UTF-8");
43
+        response.setCharacterEncoding("UTF-8");
44
+        // 禁止缓存,避免前端获取旧数据
45
+        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
46
+        response.setHeader("Pragma", "no-cache");
47
+        response.setHeader("Expires", "0");
48
+
49
+        HttpURLConnection conn = null;
50
+        // 3. 资源自动关闭(方案2核心:try-with-resources 语法)
51
+        try (
52
+            // 声明需要自动关闭的资源
53
+            InputStream inputStream = getTargetUrlInputStream(url);
54
+            BufferedReader reader = new BufferedReader(
55
+                new InputStreamReader(
56
+                    inputStream, 
57
+                    StandardCharsets.UTF_8 // 强制UTF-8,避免编码乱码
58
+                )
59
+            )
60
+        ) {
61
+            // 4. 响应流优化(方案2:批量写入,减少IO次数)
62
+            StringBuilder responseContent = new StringBuilder();
63
+            String line;
64
+            while ((line = reader.readLine()) != null) {
65
+                responseContent.append(line).append("\n");
66
+            }
67
+            // 一次性写入响应流,提升性能
68
+            response.getWriter().write(responseContent.toString());
69
+            response.getWriter().flush();
70
+
71
+        } catch (IllegalArgumentException e) {
72
+            setErrorResponse(response, "URL格式非法:" + e.getMessage());
73
+        } catch (IOException e) {
74
+            setErrorResponse(response, "网络请求异常:" + e.getMessage());
75
+        } catch (Exception e) {
76
+            setErrorResponse(response, "服务内部异常:" + e.getMessage());
77
+        } finally {
78
+            // 5. 连接关闭(方案2:确保连接释放,避免连接泄漏)
79
+            if (conn != null) {
80
+                conn.disconnect();
81
+            }
82
+        }
83
+    }
84
+
25 85
     /**
26
-     * 查询cmc招标采购列表
86
+     * 获取目标URL的输入流(封装连接逻辑,方案2:解耦核心逻辑)
27 87
      */
28
-    @GetMapping("/list")
29
-    public ResponseEntity<String> list(@RequestParam(value = "keywords", required = false) String keywords,
30
-                                       @RequestParam(value = "type", required = false) String type,
31
-                                       @RequestParam(value = "time", required = false) String time,
32
-                                       @RequestParam(value = "stime", required = false) String stime,
33
-                                       @RequestParam(value = "endtime", required = false) String endtime,
34
-                                       @RequestParam(value = "page", required = false) String page,
35
-                                       @RequestParam(value = "mod", required = false) String mod) throws UnsupportedEncodingException {
36
-        String encodedKeywords = URLEncoder.encode(keywords == null ? "" : keywords, StandardCharsets.UTF_8.name());
37
-        String html = HttpUtils.sendGet("https://search.bidcenter.com.cn/search", "type=" + (type == null ? "" : type)
38
-                + "&time=" + (time == null ? "" : time)
39
-                + "&stime=" + (stime == null ? "" : stime)
40
-                + "&endtime=" + (endtime == null ? "" : endtime)
41
-                + "&page=" + (page == null ? "" : page)
42
-                + "&mod=" + (mod == null ? "0" : mod)
43
-                + "&keywords=" + encodedKeywords, StandardCharsets.UTF_8.name());
44
-        return ResponseEntity.ok()
45
-                .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_VALUE + ";charset=UTF-8")
46
-                .body(html);
88
+    private InputStream getTargetUrlInputStream(String url) throws IOException {
89
+        URL targetUrl = new URL(url);
90
+        HttpURLConnection conn = (HttpURLConnection) targetUrl.openConnection();
91
+        
92
+        // 3. 连接配置优化(方案2:连接复用、请求头强化)
93
+        conn.setRequestMethod("GET");
94
+        conn.setConnectTimeout(CONNECT_TIMEOUT);
95
+        conn.setReadTimeout(READ_TIMEOUT);
96
+        
97
+        // 启用HTTP连接复用(方案2核心:减少TCP握手开销)
98
+        conn.setRequestProperty("Connection", "keep-alive");
99
+        conn.setRequestProperty("Keep-Alive", "timeout=10, max=100");
100
+        
101
+        // 模拟浏览器请求头(强化版,降低拦截概率)
102
+        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
103
+        conn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,*/*;q=0.8");
104
+        conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
105
+        conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
106
+        
107
+        // Cookie配置(建议从配置文件/缓存获取,方案2:避免硬编码)
108
+        conn.setRequestProperty("Cookie", "bidguid=cad034bd-ad01-4dce-a4ca-1a1252f0dbf1; Hm_lvt_9954aa2d605277c3e24cb76809e2f856=1775527126,1775629118,1775700867; HMACCOUNT=68D47FA6AE336EBB; Hm_lpvt_9954aa2d605277c3e24cb76809e2f856=1775703005");
109
+
110
+        // 4. GZIP解压(方案2:兼容更多编码场景)
111
+        InputStream inputStream = conn.getInputStream();
112
+        String contentEncoding = conn.getContentEncoding();
113
+        if (contentEncoding != null && "gzip".equalsIgnoreCase(contentEncoding.trim())) {
114
+            inputStream = new GZIPInputStream(inputStream);
115
+        }
116
+        return inputStream;
47 117
     }
48 118
 
49
-}
119
+    /**
120
+     * 统一异常响应处理(方案2核心:标准化错误返回)
121
+     */
122
+    private void setErrorResponse(HttpServletResponse response, String message) {
123
+        try {
124
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
125
+            response.getWriter().write("<html><body><h3>请求失败</h3><p>" + message + "</p></body></html>");
126
+            response.getWriter().flush();
127
+        } catch (IOException e) {
128
+            // 记录日志(建议接入项目日志框架,如logback/log4j2)
129
+            System.err.println("异常响应写入失败:" + e.getMessage());
130
+        }
131
+    }
132
+}

+ 4
- 4
oa-back/ruoyi-llm/src/main/java/com/ruoyi/web/llm/service/impl/LangChainMilvusServiceImpl.java Dosyayı Görüntüle

@@ -84,10 +84,10 @@ public class LangChainMilvusServiceImpl implements ILangChainMilvusService
84 84
         if (milvusServiceUrl == null || milvusServiceUrl.isEmpty()) {
85 85
             throw new IllegalArgumentException("milvusServiceUrl 配置不能为空");
86 86
         }
87
-       milvusClient = new MilvusClientV2(
88
-               ConnectConfig.builder()
89
-                       .uri(milvusServiceUrl)
90
-                       .build());
87
+    //    milvusClient = new MilvusClientV2(
88
+    //            ConnectConfig.builder()
89
+    //                    .uri(milvusServiceUrl)
90
+    //                    .build());
91 91
     }
92 92
     
93 93
     @PostConstruct

+ 4
- 4
oa-back/ruoyi-llm/src/main/java/com/ruoyi/web/llm/service/impl/MilvusServiceImpl.java Dosyayı Görüntüle

@@ -35,10 +35,10 @@ public class MilvusServiceImpl implements IMilvusService {
35 35
         if (milvusServiceUrl == null || milvusServiceUrl.isEmpty()) {
36 36
             throw new IllegalArgumentException("milvusServiceUrl 配置不能为空");
37 37
         }
38
-       milvusClient = new MilvusClientV2(
39
-               ConnectConfig.builder()
40
-                       .uri(milvusServiceUrl)
41
-                       .build());
38
+    //    milvusClient = new MilvusClientV2(
39
+    //            ConnectConfig.builder()
40
+    //                    .uri(milvusServiceUrl)
41
+    //                    .build());
42 42
     }
43 43
     
44 44
     @PreDestroy

Loading…
İptal
Kaydet