使用 DeepSeek API 实现新闻文章地理位置检测与地图可视化

news2025/7/18 13:06:57

使用 DeepSeek API 实现新闻文章地理位置检测与地图可视化 | Implementing News Article Location Detection and Map Visualization with DeepSeek API

作者:zhutoutoutousan | Author: zhutoutoutousan
发布时间:2025-04-08 | Published: 2025-04-08
标签:AI, Next.js, React, DeepSeek API, 地图可视化 | Tags: AI, Next.js, React, DeepSeek API, Map Visualization

链接

https://github.com/zhutoutoutousan/lotion-notes

摘要 | Abstract

本文介绍了如何在 Next.js 应用中集成 DeepSeek API 实现新闻文章的地理位置检测功能,并将检测到的位置信息在交互式地图上可视化展示。我们还将探讨如何批量处理多篇文章的位置检测,以及如何优化 API 调用以提高性能和用户体验。

This article introduces how to integrate DeepSeek API in a Next.js application to implement location detection for news articles and visualize the detected locations on an interactive map. We will also explore how to batch process location detection for multiple articles and optimize API calls to improve performance and user experience.

引言 | Introduction

在信息爆炸的时代,新闻文章往往包含丰富的地理信息。通过提取这些信息,我们可以为用户提供更直观的新闻阅读体验,帮助他们更好地理解新闻事件的地理分布。本文将详细介绍如何实现这一功能。

In the era of information explosion, news articles often contain rich geographical information. By extracting this information, we can provide users with a more intuitive news reading experience, helping them better understand the geographical distribution of news events. This article will detail how to implement this functionality.

技术栈 | Tech Stack

  • 前端框架 | Frontend Framework: Next.js, React, TypeScript
  • UI 组件 | UI Components: Shadcn UI, Tailwind CSS
  • 地图可视化 | Map Visualization: Leaflet.js
  • AI 服务 | AI Service: DeepSeek API
  • 状态管理 | State Management: React Hooks

实现步骤 | Implementation Steps

1. 设置 DeepSeek API | Setting up DeepSeek API

首先,我们需要获取 DeepSeek API 密钥并设置环境变量。

First, we need to obtain a DeepSeek API key and set up environment variables.

# .env.local
DEEPSEEK_API_KEY=your_deepseek_api_key

2. 创建 API 路由 | Creating API Route

在 Next.js 中,我们创建一个 API 路由来处理 DeepSeek API 的请求。

In Next.js, we create an API route to handle DeepSeek API requests.

// client/app/api/deepseek/route.ts
import { NextResponse } from "next/server";

export async function POST(req: Request) {
  try {
    const { prompt } = await req.json();

    if (!prompt) {
      return NextResponse.json(
        { error: 'Prompt is required' },
        { status: 400 }
      );
    }

    const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.DEEPSEEK_API_KEY}`,
      },
      body: JSON.stringify({
        model: 'deepseek-chat',
        messages: [{ role: 'user', content: prompt }],
        temperature: 0.7,
        max_tokens: 1000,
      }),
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('DeepSeek API error:', errorText);
      return NextResponse.json(
        { error: 'Failed to process request with DeepSeek API' },
        { status: response.status }
      );
    }

    const data = await response.json();
    return NextResponse.json(data);
  } catch (error) {
    console.error('Error processing DeepSeek API request:', error);
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

3. 实现位置检测服务 | Implementing Location Detection Service

接下来,我们创建一个服务函数来处理位置检测逻辑。

Next, we create a service function to handle the location detection logic.

// client/services/news-service.ts
export interface Location {
  name: string;
  latitude: number;
  longitude: number;
}

export async function detectLocationWithDeepSeek(
  title: string,
  description: string,
  content?: string
): Promise<Location | null> {
  try {
    // 组合文本进行分析 | Combine the text for analysis
    const textToAnalyze = `${title}. ${description}${content ? `. ${content}` : ''}`;
    
    // 创建 DeepSeek API 的提示 | Create a prompt for the DeepSeek API
    const prompt = `
      Analyze the following news article text and extract the primary geographic location mentioned.
      If multiple locations are mentioned, choose the most relevant one.
      If no specific location is mentioned, return null.
      
      Text: "${textToAnalyze}"
      
      Return a JSON object with the following structure:
      {
        "name": "Location Name",
        "latitude": latitude as number,
        "longitude": longitude as number
      }
      
      If no location is found, return null.
    `;
    
    // 调用 DeepSeek API | Call the DeepSeek API
    const response = await fetch('/api/deepseek', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ prompt }),
    });
    
    if (!response.ok) {
      throw new Error(`API request failed with status ${response.status}`);
    }
    
    const data = await response.json();
    
    // 解析响应 | Parse the response
    try {
      // 从 DeepSeek API 响应中提取内容 | Extract the content from the DeepSeek API response
      const content = data.choices[0].message.content;
      
      // 从内容中提取 JSON 字符串(它被 ```json 和 ```包裹)| Extract the JSON string from the content (it's wrapped in ```json and ```)
      const jsonMatch = content.match(/```json\n([\s\S]*?)\n```/);
      
      if (jsonMatch && jsonMatch[1]) {
        const locationData = JSON.parse(jsonMatch[1]);
        
        // 验证位置数据 | Validate the location data
        if (
          locationData &&
          typeof locationData.name === 'string' &&
          typeof locationData.latitude === 'number' &&
          typeof locationData.longitude === 'number'
        ) {
          return {
            name: locationData.name,
            latitude: locationData.latitude,
            longitude: locationData.longitude,
          };
        }
      }
    } catch (parseError) {
      console.error('Failed to parse location data:', parseError);
    }
    
    return null;
  } catch (error) {
    console.error('Error detecting location:', error);
    return null;
  }
}

4. 创建地图组件 | Creating Map Component

我们使用 Leaflet.js 创建一个交互式地图组件来显示文章位置。

We use Leaflet.js to create an interactive map component to display article locations.

// client/components/NewsMap.tsx
'use client';

import { useState, useEffect, useRef } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { NewsArticle, Location } from '@/services/news-service';
import { MapPin } from 'lucide-react';

interface NewsMapProps {
  articles: NewsArticle[];
  selectedArticle: NewsArticle | null;
  onArticleSelect: (article: NewsArticle) => void;
}

export default function NewsMap({ articles, selectedArticle, onArticleSelect }: NewsMapProps) {
  const [mapLoaded, setMapLoaded] = useState(false);
  const [map, setMap] = useState<any>(null);
  const [markers, setMarkers] = useState<any[]>([]);
  const mapContainerRef = useRef<HTMLDivElement>(null);
  const mapInstanceRef = useRef<any>(null);
  const markersRef = useRef<any[]>([]);

  // 动态加载 Leaflet 以避免 SSR 问题 | Load Leaflet dynamically to avoid SSR issues
  useEffect(() => {
    const loadLeaflet = async () => {
      if (typeof window !== 'undefined') {
        // 导入 Leaflet CSS | Import Leaflet CSS
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';
        link.integrity = 'sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=';
        link.crossOrigin = '';
        document.head.appendChild(link);

        // 导入 Leaflet JS | Import Leaflet JS
        const L = await import('leaflet');
        
        // 修复 Leaflet 图标问题 | Fix Leaflet icon issue
        delete (L.Icon.Default.prototype as any)._getIconUrl;
        L.Icon.Default.mergeOptions({
          iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',
          iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',
          shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
        });

        setMapLoaded(true);
      }
    };

    loadLeaflet();
  }, []);

  // 当 Leaflet 加载完成时初始化地图 | Initialize map when Leaflet is loaded
  useEffect(() => {
    if (mapLoaded && mapContainerRef.current && !mapInstanceRef.current) {
      const L = require('leaflet');
      
      // 创建地图实例 | Create map instance
      const mapInstance = L.map(mapContainerRef.current).setView([0, 0], 2);
      
      // 添加图层(OpenStreetMap)| Add tile layer (OpenStreetMap)
      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
      }).addTo(mapInstance);
      
      mapInstanceRef.current = mapInstance;
      setMap(mapInstance);
    }
    
    // 清理函数 | Cleanup function
    return () => {
      if (mapInstanceRef.current) {
        mapInstanceRef.current.remove();
        mapInstanceRef.current = null;
      }
    };
  }, [mapLoaded]);

  // 当文章变化时更新标记 | Update markers when articles change
  useEffect(() => {
    if (!map) return;
    
    const L = require('leaflet');
    
    // 清除现有标记 | Clear existing markers
    markersRef.current.forEach(marker => marker.remove());
    markersRef.current = [];
    
    // 创建新标记 | Create new markers
    const newMarkers = articles.map(article => {
      if (!article.location) return null;
      
      // 使用位置中的纬度/经度 | Use latitude/longitude from the location
      const { latitude, longitude, name } = article.location;
      
      // 创建标记 | Create marker
      const marker = L.marker([latitude, longitude])
        .addTo(map)
        .bindPopup(`
          <div class="p-2">
            <h3 class="font-bold">${article.title}</h3>
            <p class="text-sm">${article.source}${article.publishedAt}</p>
          </div>
        `);
      
      // 添加点击事件 | Add click event
      marker.on('click', () => {
        onArticleSelect(article);
      });
      
      return marker;
    }).filter(Boolean);
    
    // 在 ref 中存储标记 | Store markers in ref
    markersRef.current = newMarkers;
    
    // 更新标记状态 | Update markers state
    setMarkers(newMarkers);
  }, [articles, map, onArticleSelect]);
  
  // 更新选中的文章标记 | Update selected article marker
  useEffect(() => {
    if (!map || !selectedArticle || !selectedArticle.location) return;
    
    // 查找并高亮选中的文章标记 | Find and highlight the selected article's marker
    const selectedMarker = markersRef.current.find(marker => {
      const { latitude, longitude } = selectedArticle.location!;
      const markerLatLng = marker.getLatLng();
      return markerLatLng.lat === latitude && markerLatLng.lng === longitude;
    });
    
    if (selectedMarker) {
      // 将地图中心设置为选中的标记 | Center map on selected marker
      map.setView(selectedMarker.getLatLng(), 5);
      
      // 打开弹出窗口 | Open popup
      selectedMarker.openPopup();
    }
  }, [selectedArticle, map]);
  
  return (
    <Card className="w-full h-[400px] overflow-hidden">
      <CardHeader className="p-4">
        <CardTitle className="flex items-center gap-2 text-lg">
          <MapPin className="h-5 w-5" />
          新闻位置 | News Locations
        </CardTitle>
      </CardHeader>
      <CardContent className="p-0 h-[calc(100%-4rem)]">
        {!mapLoaded ? (
          <div className="flex items-center justify-center h-full">
            <p>加载地图中... | Loading map...</p>
          </div>
        ) : (
          <div ref={mapContainerRef} className="w-full h-full" />
        )}
      </CardContent>
    </Card>
  );
}

5. 实现批量位置检测 | Implementing Batch Location Detection

为了处理多篇文章,我们实现了批量位置检测功能。

To process multiple articles, we implemented a batch location detection feature.

// 处理所有文章的位置检测 | Handle detecting locations for all articles
const handleDetectAllLocations = async () => {
  if (articles.length === 0) return;
  
  setDetectingAllLocations(true);
  setAllLocationsProgress(0);
  setLocationError(null);
  
  // 创建文章数组的副本 | Create a copy of the articles array
  const updatedArticles = [...articles];
  let progress = 0;
  
  try {
    // 分批处理文章以避免 API 过载 | Process articles in batches to avoid overwhelming the API
    const batchSize = 3;
    for (let i = 0; i < articles.length; i += batchSize) {
      const batch = articles.slice(i, Math.min(i + batchSize, articles.length));
      
      // 处理批次中的每篇文章 | Process each article in the batch
      await Promise.all(batch.map(async (article) => {
        try {
          // 如果文章已有位置数据则跳过 | Skip if article already has location data
          if (article.location) {
            progress++;
            setAllLocationsProgress(Math.round((progress / articles.length) * 100));
            return;
          }
          
          const location = await detectLocationWithDeepSeek(
            article.title,
            article.description,
            article.content
          );
          
          if (location) {
            // 使用位置数据更新文章 | Update the article with location data
            const updatedArticle = {
              ...article,
              location
            };
            
            // 更新数组中的文章 | Update the article in the array
            const index = updatedArticles.findIndex(a => a.id === article.id);
            if (index !== -1) {
              updatedArticles[index] = updatedArticle;
            }
            
            // 如果是同一篇文章则更新选中的文章 | Update the selected article if it's the same one
            if (selectedArticle && selectedArticle.id === article.id) {
              setSelectedArticle(updatedArticle);
            }
          }
        } catch (err) {
          console.error(`Failed to detect location for article: ${article.title}`, err);
        } finally {
          progress++;
          setAllLocationsProgress(Math.round((progress / articles.length) * 100));
        }
      }));
      
      // 每批次后更新文章状态 | Update the articles state after each batch
      setArticles(updatedArticles);
      
      // 批次之间添加小延迟以避免速率限制 | Add a small delay between batches to avoid rate limiting
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  } catch (err) {
    setLocationError("Failed to detect locations for some articles. Please try again later.");
    console.error(err);
  } finally {
    setDetectingAllLocations(false);
    setAllLocationsProgress(0);
  }
};

6. 添加 UI 元素 | Adding UI Elements

最后,我们在 UI 中添加了检测位置按钮和进度指示器。

Finally, we added the detect location button and progress indicator to the UI.

<Button
  variant="outline"
  onClick={handleDetectAllLocations}
  disabled={detectingAllLocations || articles.length === 0}
  className="whitespace-nowrap"
>
  {detectingAllLocations ? (
    <>
      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
      {allLocationsProgress}% 完成 | Complete
    </>
  ) : (
    <>
      <MapPin className="mr-2 h-4 w-4" />
      检测所有位置 | Detect All Locations
    </>
  )}
</Button>

{locationError && (
  <Alert variant="destructive" className="mb-4">
    <AlertCircle className="h-4 w-4" />
    <AlertTitle>位置检测错误 | Location Detection Error</AlertTitle>
    <AlertDescription>{locationError}</AlertDescription>
  </Alert>
)}

性能优化 | Performance Optimization

为了提高性能和用户体验,我们实施了以下优化措施:

To improve performance and user experience, we implemented the following optimizations:

  1. 批量处理 | Batch Processing: 将文章分批处理,避免一次性发送过多请求。
    Process articles in batches to avoid sending too many requests at once.

  2. 延迟加载 | Lazy Loading: 动态加载 Leaflet 库,避免 SSR 问题。
    Dynamically load the Leaflet library to avoid SSR issues.

  3. 缓存标记 | Caching Markers: 使用 ref 缓存标记,避免不必要的重新渲染。
    Use refs to cache markers to avoid unnecessary re-renders.

  4. 错误处理 | Error Handling: 完善的错误处理机制,确保用户体验不受影响。
    Comprehensive error handling to ensure user experience is not affected.

  5. 进度指示 | Progress Indication: 显示批量处理的进度,提供更好的用户反馈。
    Display batch processing progress for better user feedback.

展示

自动日程规划
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

结论 | Conclusion

通过集成 DeepSeek API 和 Leaflet.js,我们成功实现了新闻文章的地理位置检测和地图可视化功能。这一功能不仅提升了用户体验,还为用户提供了更直观的新闻阅读方式。批量处理功能进一步增强了应用的实用性,使用户能够一次性处理多篇文章。

By integrating DeepSeek API and Leaflet.js, we successfully implemented location detection and map visualization for news articles. This feature not only enhances user experience but also provides users with a more intuitive way to read news. The batch processing feature further enhances the application’s utility, allowing users to process multiple articles at once.

未来改进 | Future Improvements

  1. 聚类标记 | Clustered Markers: 当标记过多时,实现标记聚类以提高性能。
    Implement marker clustering when there are too many markers to improve performance.

  2. 自定义标记样式 | Custom Marker Styles: 根据文章类别或重要性自定义标记样式。
    Customize marker styles based on article category or importance.

  3. 时间线视图 | Timeline View: 添加时间线视图,按时间顺序展示新闻事件。
    Add a timeline view to display news events chronologically.

  4. 离线支持 | Offline Support: 实现离线缓存,减少 API 调用。
    Implement offline caching to reduce API calls.

参考资料 | References

  • DeepSeek API 文档 | DeepSeek API Documentation
  • Leaflet.js 文档 | Leaflet.js Documentation
  • Next.js API 路由 | Next.js API Routes
  • React Hooks | React Hooks

如果您喜欢这篇文章,请点赞并关注我们以获取更多技术内容!
If you like this article, please like and follow us for more technical content!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2331560.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何精准控制大模型的推理深度

论文标题 ThinkEdit: Interpretable Weight Editing to Mitigate Overly Short Thinking in Reasoning Models 论文地址 https://arxiv.org/pdf/2503.22048 代码地址 https://github.com/Trustworthy-ML-Lab/ThinkEdit 作者背景 加州大学圣迭戈分校 动机 链式推理能显…

【力扣hot100题】(078)跳跃游戏Ⅱ

好难啊&#xff0c;我愿称之为跳崖游戏。 依旧用了两种方法&#xff0c;一种是我一开始想到的&#xff0c;一种是看答案学会的。 我自己用的方法是动态规划&#xff0c;维护一个数组记录到该位置的最少步长&#xff0c;每遍历到一个位置就嵌套循环遍历这个位置能到达的位置&a…

WES与WGS数据线粒体DNA数据分析及检测工具

1. 线粒体DNA的异质性 传统的全外显子组测序&#xff08;WES&#xff09;和全基因组测序&#xff08;WGS&#xff09;的二代测序&#xff08;SGS&#xff09; 数据分析流程&#xff0c;能够识别多种类型的基因改变。但大多数用于基因变异分析和注释的工具&#xff0c;在输出文…

word表格间隔设置

1.怎么解决word表格间隔达不到我们想要的要求 其实很简单, 我们直接在word表格里面, 全选表格中里面的内容。接着,我们选择自动调整---->根据内容自动调整表格,即可达到我们想要的要求

SpringBoot 接口限流Lua脚本接合Redis 服务熔断 自定义注解 接口保护

介绍 Spring Boot 接口限流是防止接口被频繁请求而导致服务器负载过重或服务崩溃的一种策略。通过限流&#xff0c;我们可以控制单位时间内允许的请求次数&#xff0c;确保系统的稳定性。限流可以帮助防止恶意请求、保护系统资源&#xff0c;并优化 API 的可用性&#xff0c;避…

I/O进程4

day4 九、信号灯集 1.概念 信号灯(semaphore)&#xff0c;也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制&#xff1b;System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。 通过信号灯集实现共享内存的同步操作。 2.编程…

【语法】C++的list

目录 为什么会有list&#xff1f; 迭代器失效&#xff1a; list和vector的迭代器不同的地方&#xff1a; list的大部分用法和vector都很像&#xff0c;例如push_back&#xff0c;构造&#xff0c;析构&#xff0c;赋值重载这些就不再废话了&#xff0c;本篇主要讲的是和vecto…

【Ai/Agent】Windows11中安装CrewAI过程中的错误解决记录

CrewAi是什么&#xff0c;可以看之下之前写的 《初识CrewAI多智能代理团队协框架》 (注&#xff1a;这篇是基于linux系统下安装实践的) 基于以下记录解决问题后&#xff0c;可以再回到之前的文章继续进行CrewAI的安装 遇到问题 在windows系统中安装 CrewAi 不管是使用 pip 或者…

OSPF的数据报文格式【复习篇】

OSPF协议是跨层封装的协议&#xff08;跨四层封装&#xff09;&#xff0c;直接将应用层的数据封装在网络层协议之后&#xff0c;IP协议包中协议号字段对应的数值为89 OSPF的头部信息&#xff1a; 所有的数据共有的信息字段 字段名描述版本当前OSPF进程使用的版本&#xff08;…

【力扣刷题实战】Z字形变换

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 力扣题目&#xff1a;Z字形变换 题目描述 解题思路 问题理解 算法选择 具体思路 解题要点 完整代码&#xff08;C&#xff09; 兄弟们共勉 &#xff01;&#xff01;&#xff01; 每篇前言 博客主页&#xff1a;小卡…

力扣题解:142. 环形链表 II

在链表学习中&#xff0c;我们已经了解了单链表和双链表&#xff0c;两者的最后一个结点都会指向NULL&#xff1b;今天我们介绍的循环列表则不同&#xff0c;其末尾结点指向的这是链表中的一个结点。 循环链表是一种特殊类型的链表&#xff0c;其尾节点的指针指向头节点&#…

latex模板文件

LaTeX 是一款广泛应用于学术领域的​​文档排版系统​​&#xff0c;尤其以其在数学公式、科学符号和复杂技术文档排版中的强大能力著称。虽然它本身并非专门的“数学软件”&#xff0c;但在处理数学相关内容时表现尤为出色。 1. LaTeX 的核心特点​ 数学公式支持​​&#xff…

BLE 协议栈事件驱动机制详解

在 BlueNRG-LP 等 BLE 系统中,事件驱动是控制状态转移、数据交互和外设协作的基础。本文将深入讲解 BLE 协议栈中事件的来源、分发流程、处理结构与实际工程实践策略,帮助你构建稳定、可维护的 BLE 系统。 📦 一、BLE 事件的来源分类 BLE 协议栈中的事件严格来自协议栈本身…

Rust 之四 运算符、标量、元组、数组、字符串、结构体、枚举

概述 Rust 的基本语法对于从事底层 C/C 开发的人来说多少有些难以理解&#xff0c;虽然官方有详细的文档来介绍&#xff0c;不过内容是相当的多&#xff0c;看起来也费劲。本文通过将每个知识点简化为 一个 DEMO 每种特性各用一句话描述的形式来简化学习过程&#xff0c;提高学…

fuse-python使用fuse来挂载fs

winfsp 安装winfsp,https://winfsp.dev/ fusepy python安装fusepy #!/usr/bin/env python3 import os import stat from fuse import FUSE, FuseOSError, Operationsclass Passthrough(Operations):def __init__(self, root):self.root root# 辅助函数&#xff1a;将挂载点…

基于ueditor编辑器的功能开发之增加自定义一键排版功能

用户有自己的文章格式&#xff0c;要求复制或者粘贴进来的文章能够一键排版&#xff0c;不需要手动调试 这个需求的话咱们就需要自己去注册一个事件啦&#xff0c;这里我没有修改源码&#xff0c;而是在编辑器初始化之后给他注册了一个事件 我的工具列表变量 vue组件中data中…

VS Code Markdown渲染配置

VS code markdown preview enhanced插件渲染配置 mac: commandshiftP命令输入Markdown Preview Enhanced: Customize CSS&#xff0c;并点击在打开的style.less配置文件添加一下配置 /* Please visit the URL below for more information: */ /* https://shd101wyy.github.…

数据结构篇:线性表的另一表达—链表之单链表(上篇)

目录 1.链表的引入 1.1 链表的概念 1.2 next的意义 2.链表的分类 3.单链表的实现 3.1 单链表实现接口 3.1.1 插入节点函数封装 3.1.2 尾插 3.1.3 头插 3.1.4 报错的根本问题 3.1.5 头删 3.1.6 尾删 4.小结 1.链表的引入 根据顺序表的一些缺陷…

SpringBoot企业级开发之【用户模块-获取用户详细信息】

接口文档的要求&#xff1a; 了解一下token令牌头是怎么用的 我们直接放到前端交互的controller类下&#xff0c;在声明的方法中加入参数为String token且加入注解RequestHeader(name"Authorization【你自己设定的token】") 设计思路: 实战开发&#xff1a; control…

Mockito如何对静态方法进行测试

在 Mockito 中,直接对静态方法进行模拟是困难的,因为 Mockito 的设计理念是优先通过依赖注入(DI)管理对象,而静态方法破坏了这种设计(难以解耦)。不过,从 Mockito 3.4.0 版本开始,通过 mockStatic 方法支持了对静态方法的模拟(需配合 mockito-inline 依赖)。 从 Mo…