Java 对接印度股票数据源实现 http+ws实时数据

以下是使用 Java 对接 StockTV 印度股票数据源的完整实现,包括实时行情、K线数据、公司信息等功能。

1. 项目依赖

首先在 pom.xml 中添加必要的依赖:

xml 复制代码
<dependencies>
    <!-- HTTP 客户端 -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.14</version>
    </dependency>
    
    <!-- JSON 处理 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>
    
    <!-- WebSocket 客户端 -->
    <dependency>
        <groupId>org.java-websocket</groupId>
        <artifactId>Java-WebSocket</artifactId>
        <version>1.5.3</version>
    </dependency>
    
    <!-- 日志 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.7</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>2.0.7</version>
    </dependency>
</dependencies>

2. 配置类

java 复制代码
package com.stocktv.india.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class StockTVConfig {
    
    // API 基础配置
    public static final String BASE_URL = "https://api.stocktv.top";
    public static final String WS_URL = "wss://ws-api.stocktv.top/connect";
    
    // 印度市场特定配置
    public static final int INDIA_COUNTRY_ID = 14;
    public static final int NSE_EXCHANGE_ID = 46;
    public static final int BSE_EXCHANGE_ID = 74;
    
    // API Key - 请替换为实际的 API Key
    private String apiKey;
    
    // HTTP 客户端
    private final CloseableHttpClient httpClient;
    private final ObjectMapper objectMapper;
    
    public StockTVConfig(String apiKey) {
        this.apiKey = apiKey;
        this.httpClient = HttpClients.createDefault();
        this.objectMapper = new ObjectMapper();
    }
    
    // Getters
    public String getApiKey() { return apiKey; }
    public CloseableHttpClient getHttpClient() { return httpClient; }
    public ObjectMapper getObjectMapper() { return objectMapper; }
}

3. 数据模型类

股票基本信息

java 复制代码
package com.stocktv.india.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.math.BigDecimal;

@Data
public class Stock {
    @JsonProperty("id")
    private Long id;
    
    @JsonProperty("symbol")
    private String symbol;
    
    @JsonProperty("name")
    private String name;
    
    @JsonProperty("last")
    private BigDecimal lastPrice;
    
    @JsonProperty("chg")
    private BigDecimal change;
    
    @JsonProperty("chgPct")
    private BigDecimal changePercent;
    
    @JsonProperty("high")
    private BigDecimal high;
    
    @JsonProperty("low")
    private BigDecimal low;
    
    @JsonProperty("volume")
    private Long volume;
    
    @JsonProperty("open")
    private Boolean isOpen;
    
    @JsonProperty("exchangeId")
    private Integer exchangeId;
    
    @JsonProperty("countryId")
    private Integer countryId;
    
    @JsonProperty("time")
    private Long timestamp;
    
    @JsonProperty("fundamentalMarketCap")
    private BigDecimal marketCap;
    
    @JsonProperty("fundamentalRevenue")
    private String revenue;
    
    // 技术指标
    @JsonProperty("technicalDay")
    private String technicalDay;
    
    @JsonProperty("technicalHour")
    private String technicalHour;
    
    @JsonProperty("technicalWeek")
    private String technicalWeek;
    
    @JsonProperty("technicalMonth")
    private String technicalMonth;
}

K线数据

java 复制代码
package com.stocktv.india.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.math.BigDecimal;

@Data
public class KLine {
    @JsonProperty("time")
    private Long timestamp;
    
    @JsonProperty("open")
    private BigDecimal open;
    
    @JsonProperty("high")
    private BigDecimal high;
    
    @JsonProperty("low")
    private BigDecimal low;
    
    @JsonProperty("close")
    private BigDecimal close;
    
    @JsonProperty("volume")
    private Long volume;
    
    @JsonProperty("vo")
    private BigDecimal turnover;
}

指数数据

java 复制代码
package com.stocktv.india.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.math.BigDecimal;

@Data
public class Index {
    @JsonProperty("id")
    private Long id;
    
    @JsonProperty("name")
    private String name;
    
    @JsonProperty("symbol")
    private String symbol;
    
    @JsonProperty("last")
    private BigDecimal lastPrice;
    
    @JsonProperty("chg")
    private BigDecimal change;
    
    @JsonProperty("chgPct")
    private BigDecimal changePercent;
    
    @JsonProperty("high")
    private BigDecimal high;
    
    @JsonProperty("low")
    private BigDecimal low;
    
    @JsonProperty("isOpen")
    private Boolean isOpen;
    
    @JsonProperty("time")
    private Long timestamp;
}

API 响应包装类

java 复制代码
package com.stocktv.india.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.List;

@Data
public class ApiResponse<T> {
    @JsonProperty("code")
    private Integer code;
    
    @JsonProperty("message")
    private String message;
    
    @JsonProperty("data")
    private T data;
}

@Data
class StockListResponse {
    @JsonProperty("records")
    private List<Stock> records;
    
    @JsonProperty("total")
    private Integer total;
    
    @JsonProperty("current")
    private Integer current;
    
    @JsonProperty("pages")
    private Integer pages;
}

4. HTTP API 客户端

java 复制代码
package com.stocktv.india.client;

import com.fasterxml.jackson.core.type.TypeReference;
import com.stocktv.india.config.StockTVConfig;
import com.stocktv.india.model.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

public class StockTVHttpClient {
    
    private static final Logger logger = LoggerFactory.getLogger(StockTVHttpClient.class);
    
    private final StockTVConfig config;
    private final CloseableHttpClient httpClient;
    
    public StockTVHttpClient(StockTVConfig config) {
        this.config = config;
        this.httpClient = config.getHttpClient();
    }
    
    /**
     * 获取印度股票列表
     */
    public List<Stock> getIndiaStocks(Integer pageSize, Integer page) throws IOException, URISyntaxException {
        URI uri = new URIBuilder(config.BASE_URL + "/stock/stocks")
                .addParameter("countryId", String.valueOf(config.INDIA_COUNTRY_ID))
                .addParameter("pageSize", String.valueOf(pageSize))
                .addParameter("page", String.valueOf(page))
                .addParameter("key", config.getApiKey())
                .build();
        
        ApiResponse<StockListResponse> response = executeGetRequest(uri, 
            new TypeReference<ApiResponse<StockListResponse>>() {});
        
        if (response.getCode() == 200) {
            return response.getData().getRecords();
        } else {
            throw new RuntimeException("API Error: " + response.getMessage());
        }
    }
    
    /**
     * 查询单个股票
     */
    public List<Stock> queryStock(Long pid, String symbol, String name) throws IOException, URISyntaxException {
        URIBuilder uriBuilder = new URIBuilder(config.BASE_URL + "/stock/queryStocks")
                .addParameter("key", config.getApiKey());
        
        if (pid != null) {
            uriBuilder.addParameter("id", String.valueOf(pid));
        }
        if (symbol != null) {
            uriBuilder.addParameter("symbol", symbol);
        }
        if (name != null) {
            uriBuilder.addParameter("name", name);
        }
        
        URI uri = uriBuilder.build();
        
        ApiResponse<List<Stock>> response = executeGetRequest(uri, 
            new TypeReference<ApiResponse<List<Stock>>>() {});
        
        return response.getData();
    }
    
    /**
     * 批量查询多个股票
     */
    public List<Stock> getStocksByPids(List<Long> pids) throws IOException, URISyntaxException {
        String pidsStr = String.join(",", pids.stream().map(String::valueOf).toArray(String[]::new));
        
        URI uri = new URIBuilder(config.BASE_URL + "/stock/stocksByPids")
                .addParameter("key", config.getApiKey())
                .addParameter("pids", pidsStr)
                .build();
        
        ApiResponse<List<Stock>> response = executeGetRequest(uri, 
            new TypeReference<ApiResponse<List<Stock>>>() {});
        
        return response.getData();
    }
    
    /**
     * 获取印度主要指数
     */
    public List<Index> getIndiaIndices() throws IOException, URISyntaxException {
        URI uri = new URIBuilder(config.BASE_URL + "/stock/indices")
                .addParameter("countryId", String.valueOf(config.INDIA_COUNTRY_ID))
                .addParameter("key", config.getApiKey())
                .build();
        
        ApiResponse<List<Index>> response = executeGetRequest(uri, 
            new TypeReference<ApiResponse<List<Index>>>() {});
        
        return response.getData();
    }
    
    /**
     * 获取K线数据
     */
    public List<KLine> getKLineData(Long pid, String interval) throws IOException, URISyntaxException {
        URI uri = new URIBuilder(config.BASE_URL + "/stock/kline")
                .addParameter("pid", String.valueOf(pid))
                .addParameter("interval", interval)
                .addParameter("key", config.getApiKey())
                .build();
        
        ApiResponse<List<KLine>> response = executeGetRequest(uri, 
            new TypeReference<ApiResponse<List<KLine>>>() {});
        
        return response.getData();
    }
    
    /**
     * 获取涨跌排行榜
     */
    public List<Stock> getUpDownList(Integer type) throws IOException, URISyntaxException {
        URI uri = new URIBuilder(config.BASE_URL + "/stock/updownList")
                .addParameter("countryId", String.valueOf(config.INDIA_COUNTRY_ID))
                .addParameter("type", String.valueOf(type))
                .addParameter("key", config.getApiKey())
                .build();
        
        ApiResponse<List<Stock>> response = executeGetRequest(uri, 
            new TypeReference<ApiResponse<List<Stock>>>() {});
        
        return response.getData();
    }
    
    /**
     * 通用GET请求执行方法
     */
    private <T> T executeGetRequest(URI uri, TypeReference<T> typeReference) throws IOException {
        HttpGet request = new HttpGet(uri);
        
        try (CloseableHttpResponse response = httpClient.execute(request)) {
            String responseBody = EntityUtils.toString(response.getEntity());
            logger.debug("API Response: {}", responseBody);
            
            return config.getObjectMapper().readValue(responseBody, typeReference);
        }
    }
}

5. WebSocket 实时数据客户端

java 复制代码
package com.stocktv.india.client;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.stocktv.india.config.StockTVConfig;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class StockTVWebSocketClient {
    
    private static final Logger logger = LoggerFactory.getLogger(StockTVWebSocketClient.class);
    
    private final StockTVConfig config;
    private final ObjectMapper objectMapper;
    private WebSocketClient webSocketClient;
    private CountDownLatch connectionLatch;
    
    public StockTVWebSocketClient(StockTVConfig config) {
        this.config = config;
        this.objectMapper = config.getObjectMapper();
    }
    
    /**
     * 连接WebSocket服务器
     */
    public void connect() throws Exception {
        String wsUrl = config.WS_URL + "?key=" + config.getApiKey();
        URI serverUri = URI.create(wsUrl);
        
        connectionLatch = new CountDownLatch(1);
        
        webSocketClient = new WebSocketClient(serverUri) {
            @Override
            public void onOpen(ServerHandshake handshake) {
                logger.info("WebSocket连接已建立");
                connectionLatch.countDown();
            }
            
            @Override
            public void onMessage(String message) {
                try {
                    handleMessage(message);
                } catch (Exception e) {
                    logger.error("处理WebSocket消息时出错", e);
                }
            }
            
            @Override
            public void onClose(int code, String reason, boolean remote) {
                logger.info("WebSocket连接已关闭: code={}, reason={}, remote={}", code, reason, remote);
            }
            
            @Override
            public void onError(Exception ex) {
                logger.error("WebSocket连接错误", ex);
            }
        };
        
        webSocketClient.connect();
        
        // 等待连接建立
        if (!connectionLatch.await(10, TimeUnit.SECONDS)) {
            throw new RuntimeException("WebSocket连接超时");
        }
    }
    
    /**
     * 处理收到的消息
     */
    private void handleMessage(String message) throws Exception {
        JsonNode jsonNode = objectMapper.readTree(message);
        
        // 解析实时行情数据
        if (jsonNode.has("pid")) {
            RealTimeData realTimeData = objectMapper.treeToValue(jsonNode, RealTimeData.class);
            onRealTimeData(realTimeData);
        } else {
            logger.info("收到消息: {}", message);
        }
    }
    
    /**
     * 处理实时行情数据 - 需要子类重写
     */
    protected void onRealTimeData(RealTimeData data) {
        logger.info("实时行情: {} - 最新价: {}, 涨跌幅: {}%", 
            data.getPid(), data.getLastNumeric(), data.getPcp());
    }
    
    /**
     * 发送消息
     */
    public void sendMessage(String message) {
        if (webSocketClient != null && webSocketClient.isOpen()) {
            webSocketClient.send(message);
        }
    }
    
    /**
     * 关闭连接
     */
    public void close() {
        if (webSocketClient != null) {
            webSocketClient.close();
        }
    }
    
    /**
     * 实时数据模型
     */
    public static class RealTimeData {
        private String pid;
        private String lastNumeric;
        private String bid;
        private String ask;
        private String high;
        private String low;
        private String lastClose;
        private String pc;
        private String pcp;
        private String turnoverNumeric;
        private String time;
        private String timestamp;
        private Integer type;
        
        // Getters and Setters
        public String getPid() { return pid; }
        public void setPid(String pid) { this.pid = pid; }
        public String getLastNumeric() { return lastNumeric; }
        public void setLastNumeric(String lastNumeric) { this.lastNumeric = lastNumeric; }
        public String getBid() { return bid; }
        public void setBid(String bid) { this.bid = bid; }
        public String getAsk() { return ask; }
        public void setAsk(String ask) { this.ask = ask; }
        public String getHigh() { return high; }
        public void setHigh(String high) { this.high = high; }
        public String getLow() { return low; }
        public void setLow(String low) { this.low = low; }
        public String getLastClose() { return lastClose; }
        public void setLastClose(String lastClose) { this.lastClose = lastClose; }
        public String getPc() { return pc; }
        public void setPc(String pc) { this.pc = pc; }
        public String getPcp() { return pcp; }
        public void setPcp(String pcp) { this.pcp = pcp; }
        public String getTurnoverNumeric() { return turnoverNumeric; }
        public void setTurnoverNumeric(String turnoverNumeric) { this.turnoverNumeric = turnoverNumeric; }
        public String getTime() { return time; }
        public void setTime(String time) { this.time = time; }
        public String getTimestamp() { return timestamp; }
        public void setTimestamp(String timestamp) { this.timestamp = timestamp; }
        public Integer getType() { return type; }
        public void setType(Integer type) { this.type = type; }
    }
}

6. 服务类

java 复制代码
package com.stocktv.india.service;

import com.stocktv.india.client.StockTVHttpClient;
import com.stocktv.india.client.StockTVWebSocketClient;
import com.stocktv.india.config.StockTVConfig;
import com.stocktv.india.model.Index;
import com.stocktv.india.model.KLine;
import com.stocktv.india.model.Stock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class IndiaStockService {
    
    private static final Logger logger = LoggerFactory.getLogger(IndiaStockService.class);
    
    private final StockTVHttpClient httpClient;
    private final StockTVWebSocketClient webSocketClient;
    
    public IndiaStockService(String apiKey) {
        StockTVConfig config = new StockTVConfig(apiKey);
        this.httpClient = new StockTVHttpClient(config);
        this.webSocketClient = new StockTVWebSocketClient(config);
    }
    
    /**
     * 获取Nifty 50成分股
     */
    public List<Stock> getNifty50Stocks() {
        try {
            // 获取前50只股票(实际应该根据Nifty 50成分股列表查询)
            return httpClient.getIndiaStocks(50, 1);
        } catch (Exception e) {
            logger.error("获取Nifty 50成分股失败", e);
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 获取印度主要指数
     */
    public List<Index> getMajorIndices() {
        try {
            return httpClient.getIndiaIndices();
        } catch (Exception e) {
            logger.error("获取印度指数失败", e);
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 查询特定股票
     */
    public List<Stock> getStockBySymbol(String symbol) {
        try {
            return httpClient.queryStock(null, symbol, null);
        } catch (Exception e) {
            logger.error("查询股票失败: " + symbol, e);
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 获取股票K线数据
     */
    public List<KLine> getStockKLine(Long pid, String interval) {
        try {
            return httpClient.getKLineData(pid, interval);
        } catch (Exception e) {
            logger.error("获取K线数据失败: pid=" + pid, e);
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 获取涨幅榜
     */
    public List<Stock> getGainers() {
        try {
            return httpClient.getUpDownList(1); // 1表示涨幅榜
        } catch (Exception e) {
            logger.error("获取涨幅榜失败", e);
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 启动实时数据监听
     */
    public void startRealTimeMonitoring() {
        try {
            webSocketClient.connect();
            logger.info("实时数据监听已启动");
        } catch (Exception e) {
            logger.error("启动实时数据监听失败", e);
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 停止实时数据监听
     */
    public void stopRealTimeMonitoring() {
        webSocketClient.close();
        logger.info("实时数据监听已停止");
    }
}

7. 使用示例

java 复制代码
package com.stocktv.india.demo;

import com.stocktv.india.service.IndiaStockService;
import com.stocktv.india.client.StockTVWebSocketClient;
import com.stocktv.india.model.Index;
import com.stocktv.india.model.KLine;
import com.stocktv.india.model.Stock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class IndiaStockDemo {
    
    private static final Logger logger = LoggerFactory.getLogger(IndiaStockDemo.class);
    
    public static void main(String[] args) {
        // 替换为实际的 API Key
        String apiKey = "您的API_KEY";
        
        IndiaStockService stockService = new IndiaStockService(apiKey);
        
        try {
            // 1. 获取印度主要指数
            logger.info("=== 印度主要指数 ===");
            List<Index> indices = stockService.getMajorIndices();
            indices.forEach(index -> 
                logger.info("{}: {} ({}{}%)", 
                    index.getName(), index.getLastPrice(), 
                    index.getChange().doubleValue() > 0 ? "+" : "", 
                    index.getChangePercent())
            );
            
            // 2. 获取Nifty 50成分股
            logger.info("\n=== Nifty 50成分股(示例)===");
            List<Stock> niftyStocks = stockService.getNifty50Stocks();
            niftyStocks.stream().limit(10).forEach(stock -> 
                logger.info("{} ({}) : {} INR, 涨跌幅: {}%", 
                    stock.getSymbol(), stock.getName(), 
                    stock.getLastPrice(), stock.getChangePercent())
            );
            
            // 3. 查询特定股票
            logger.info("\n=== 查询RELIANCE股票 ===");
            List<Stock> relianceStock = stockService.getStockBySymbol("RELIANCE");
            if (!relianceStock.isEmpty()) {
                Stock stock = relianceStock.get(0);
                logger.info("Reliance Industries: {} INR, 成交量: {}", 
                    stock.getLastPrice(), stock.getVolume());
            }
            
            // 4. 获取K线数据
            logger.info("\n=== RELIANCE日K线数据 ===");
            if (!relianceStock.isEmpty()) {
                Long pid = relianceStock.get(0).getId();
                List<KLine> kLines = stockService.getStockKLine(pid, "P1D");
                kLines.stream().limit(5).forEach(kLine -> 
                    logger.info("时间: {}, 开: {}, 高: {}, 低: {}, 收: {}", 
                        kLine.getTimestamp(), kLine.getOpen(), 
                        kLine.getHigh(), kLine.getLow(), kLine.getClose())
                );
            }
            
            // 5. 获取涨幅榜
            logger.info("\n=== 今日涨幅榜 ===");
            List<Stock> gainers = stockService.getGainers();
            gainers.stream().limit(5).forEach(stock -> 
                logger.info("{}: {} INR, 涨幅: {}%", 
                    stock.getSymbol(), stock.getLastPrice(), stock.getChangePercent())
            );
            
            // 6. 启动实时数据监听(可选)
            logger.info("\n=== 启动实时数据监听 ===");
            // stockService.startRealTimeMonitoring();
            
            // 保持程序运行一段时间
            Thread.sleep(30000);
            
            // 停止实时数据监听
            // stockService.stopRealTimeMonitoring();
            
        } catch (Exception e) {
            logger.error("演示程序执行失败", e);
        }
    }
}

8. 自定义实时数据处理

如果需要自定义实时数据处理逻辑,可以继承 StockTVWebSocketClient

java 复制代码
package com.stocktv.india.custom;

import com.stocktv.india.client.StockTVWebSocketClient;
import com.stocktv.india.config.StockTVConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomWebSocketClient extends StockTVWebSocketClient {
    
    private static final Logger logger = LoggerFactory.getLogger(CustomWebSocketClient.class);
    
    public CustomWebSocketClient(StockTVConfig config) {
        super(config);
    }
    
    @Override
    protected void onRealTimeData(RealTimeData data) {
        // 自定义实时数据处理逻辑
        if ("7310".equals(data.getPid())) { // RELIANCE的PID
            logger.info("RELIANCE实时行情 - 价格: {}, 涨跌幅: {}%, 成交量: {}", 
                data.getLastNumeric(), data.getPcp(), data.getTurnoverNumeric());
        }
        
        // 可以在这里添加交易逻辑、报警逻辑等
        if (Double.parseDouble(data.getPcp()) > 5.0) {
            logger.warn("股票 {} 涨幅超过5%: {}%", data.getPid(), data.getPcp());
        }
    }
}

9. 配置说明

时间间隔参数

  • PT5M - 5分钟K线
  • PT15M - 15分钟K线
  • PT1H - 1小时K线
  • P1D - 日K线
  • P1W - 周K线
  • P1M - 月K线

排行榜类型

  • 1 - 涨幅榜
  • 2 - 跌幅榜
  • 3 - 涨停榜
  • 4 - 跌停榜

10. 注意事项

  1. API Key管理: 建议从配置文件或环境变量读取API Key
  2. 错误处理: 所有API调用都需要适当的异常处理
  3. 频率限制: 注意API的调用频率限制
  4. 连接管理: WebSocket连接需要处理重连逻辑
  5. 数据缓存: 对于不经常变化的数据可以实施缓存

这个完整的Java实现提供了对接印度股票数据源的所有核心功能,可以根据具体需求进行扩展和优化。

相关推荐
uzong7 分钟前
软件架构指南 Software Architecture Guide
后端
又是忙碌的一天7 分钟前
SpringBoot 创建及登录、拦截器
java·spring boot·后端
勇哥java实战分享1 小时前
短信平台 Pro 版本 ,比开源版本更强大
后端
学历真的很重要1 小时前
LangChain V1.0 Context Engineering(上下文工程)详细指南
人工智能·后端·学习·语言模型·面试·职场和发展·langchain
计算机毕设VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue二手家电管理系统(源码+数据库+文档)
vue.js·spring boot·后端·课程设计
上进小菜猪1 小时前
基于 YOLOv8 的智能杂草检测识别实战 [目标检测完整源码]
后端
韩师傅2 小时前
前端开发消亡史:AI也无法掩盖没有设计创造力的真相
前端·人工智能·后端
栈与堆3 小时前
LeetCode-1-两数之和
java·数据结构·后端·python·算法·leetcode·rust
superman超哥3 小时前
双端迭代器(DoubleEndedIterator):Rust双向遍历的优雅实现
开发语言·后端·rust·双端迭代器·rust双向遍历
1二山似3 小时前
crmeb多商户启动swoole时报‘加密文件丢失’
后端·swoole