JAVA集成本地部署的DeepSeek的圖文教程
一、下載部署DeepSeek
1.下載ollama
前往 Ollama 主頁(yè)。

點(diǎn)擊下載,選擇對(duì)應(yīng)操作系統(tǒng),點(diǎn)擊下載。

下載完成后打開(kāi)直接無(wú)腦下一步就行。
安裝完成之后打開(kāi)CMD頁(yè)面,輸入ollama,如果有輸出就代表安裝成功,如果顯示"不是內(nèi)部命令"就需要配置一下環(huán)境變量。

###配置環(huán)境變量以及更改ollama模型路徑###
win10系統(tǒng)為例,右鍵此電腦>高級(jí)系統(tǒng)設(shè)置>高級(jí)>環(huán)境變量
ollama 默認(rèn)會(huì)安裝到 C:\Users\XX\AppData\Local\Programs\ollama 下,將此文件全部移到其他盤。
選擇系統(tǒng)變量Path>編輯>新建>輸入移動(dòng)后的ollama地址

在系統(tǒng)變量中點(diǎn)擊新建,輸入變量名OLLAMA_MODELS,變量值D:\ollama\models(希望ollama模型放入哪個(gè)位置)

配置完成后重啟電腦,打開(kāi)CMD頁(yè)面再次輸入ollama,查看是否有輸出
2.下載DeepSeek-R1模型并啟動(dòng)
打開(kāi) Ollama 首頁(yè),點(diǎn)擊 DeepSeek-R1

在這里有模型各種參數(shù)大小

DeepSeek-R1模型有1.5b、7b、8b、14b、32b、70b和671b的參數(shù)量區(qū)別,B代表十億的意思,1.5b代表15億參數(shù)量的意思。671B是基礎(chǔ)大模型,1.5B、7B、8B、14B、32B、70B是蒸餾后的小模型,它們的區(qū)別主要體現(xiàn)在參數(shù)規(guī)模、模型容量、性能表現(xiàn)、準(zhǔn)確性、訓(xùn)練成本、推理成本和不同使用場(chǎng)景:
| DeepSeek模型版本 | 參數(shù)量 | 特點(diǎn) | 適用場(chǎng)景 | 硬件配置 |
| DeepSeek-R1-1.5B | 1.5B | 輕量級(jí)模型,參數(shù)量少,模型規(guī)模小 | 適用于輕量級(jí)任務(wù),如短文本生成、基礎(chǔ)問(wèn)答等 | 4核處理器、8G內(nèi)存,無(wú)需顯卡 |
| DeepSeek-R1-7B | 7B | 平衡型模型,性能較好,硬件需求適中 | 適合中等復(fù)雜度任務(wù),如文案撰寫、表格處理、統(tǒng)計(jì)分析等 | 8核處理器、16G內(nèi)存,Ryzen7或更高,RTX 3060(12GB)或更高 |
| DeepSeek-R1-8B | 8B | 性能略強(qiáng)于7B模型,適合更高精度需求 | 適合需要更高精度的輕量級(jí)任務(wù),比如代碼生成、邏輯推理等 | 8核處理器、16G內(nèi)存,Ryzen7或更高,RTX 3060(12GB)或4060 |
| DeepSeek-R1-14B | 14B | 高性能模型,擅長(zhǎng)復(fù)雜的任務(wù),如數(shù)學(xué)推理、代碼生成 | 可處理復(fù)雜任務(wù),如長(zhǎng)文本生成、數(shù)據(jù)分析等 | i9-13900K或更高、32G內(nèi)存,RTX 4090(24GB)或A5000 |
| DeepSeek-R1-32B | 32B | 專業(yè)級(jí)模型,性能強(qiáng)大,適合高精度任務(wù) | 適合超大規(guī)模任務(wù),如語(yǔ)言建模、大規(guī)模訓(xùn)練、金融預(yù)測(cè)等 | Xeon 8核、128GB內(nèi)存或更高,2-4張A100(80GB)或更高 |
| DeepSeek-R1-70B | 70B | 頂級(jí)模型,性能最強(qiáng),適合大規(guī)模計(jì)算和高復(fù)雜任務(wù) | 適合高精度專業(yè)領(lǐng)域任務(wù),比如多模態(tài)任務(wù)預(yù)處理。這些任務(wù)對(duì)硬件要求非常高,需要高端的 CPU 和顯卡,適合預(yù)算充足的企業(yè)或研究機(jī)構(gòu)使用 | Xeon 8核、128GB內(nèi)存或更高,8張A100/H100(80GB)或更高 |
| DeepSeek-R1-671B | 671B | 超大規(guī)模模型,性能卓越,推理速度快,適合極高精度需求 | 適合國(guó)家級(jí) / 超大規(guī)模 AI 研究,如氣候建模、基因組分析等,以及通用人工智能探索 | 64核、512GB或更高,8張A100/H100 |
根據(jù)自己電腦的配置選擇對(duì)應(yīng)大小的模型,復(fù)制安裝命令,在cmd中執(zhí)行命令


等待安裝完成后會(huì)自己?jiǎn)?dòng)。

退出 DeepSeek 輸入 /bye 或者 Ctrl+D
ollama 常用命令
ollama list :查看已安裝的模型
ollama ps:正在運(yùn)行的模型
ollama run 模型名稱:?jiǎn)?dòng)模型
ollama rm 模型名稱:卸載模型
下次啟動(dòng) DeepSeek 只需要先 ollama list 查看已安裝的模型,ollama run 模型名稱啟動(dòng)即可。
二、JAVA項(xiàng)目接入DeepSeek
創(chuàng)建一個(gè)是 Springboot 項(xiàng)目引入 okhttp,lombok 等依賴
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>配置文件中配置好本地 DeepSeek 的訪問(wèn)URL,ollama啟動(dòng)的 DeepSeek 端口默認(rèn)為 11434
deepseek:
api:
url: "http://127.0.0.1:11434/api/generate"
model: "deepseek-r1:1.5b"編寫 DeepSeekController
@RestController
@RequestMapping("/deepSeek")
public class DeepSeekController {
@Autowired
private DeepSeekService deepSeekService;
@GetMapping
@RequestMapping("/chat")
public String chat(String question) {
try {
return deepSeekService.chat(question);
} catch (IOException e) {
return "服務(wù)器繁忙,請(qǐng)稍后重試!";
}
}
}編寫DeepSeekRequest實(shí)體類
@Data
@Builder
public class DeepSeekRequest {
/**
* 消息列表,包含對(duì)話中的消息對(duì)象
*/
private String prompt;
/**
* 模型名稱,指定要使用的模型
*/
private String model;
}請(qǐng)求參數(shù)有很多,只列舉最主要的兩個(gè)參數(shù)
編寫DeepSeekResponse實(shí)體類
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("deepseek_response")
public class DeepSeekResponse {
private String id;
private String questionId;
//模型名稱
private String model;
//創(chuàng)建時(shí)間
@JSONField(name = "created_at")
private String createdAt;
//響應(yīng)內(nèi)容
private String response;
//
private boolean done;
//
@JSONField(name = "done_reason")
private String doneReason;
//
@TableField(typeHandler = JacksonTypeHandler.class)
private Integer[] context;
//
@JSONField(name = "total_duration")
private Long totalDuration;
//
@JSONField(name = "load_duration")
private Long loadDuration;
//
@JSONField(name = "prompt_eval_count")
private Long promptEvalCount;
//
@JSONField(name = "prompt_eval_duration")
private Long promptEvalDuration;
//
@JSONField(name = "eval_count")
private Long evalCount;
//
@JSONField(name = "eval_duration")
private Long evalDuration;
}編寫DeepSeekService
@Service
public class DeepSeekService {
@Value("${deepseek.api.url}")
private String url;
@Value("${deepseek.api.model}")
private String model;
private final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
public String chat(String question) throws IOException {
DeepSeekRequest requestBody = DeepSeekRequest.builder()
.model(model)
.prompt(question)
.build();
// 創(chuàng)建HTTP請(qǐng)求
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(JSON.toJSONString(requestBody), MediaType.get("application/json")))
.build();
// 發(fā)送請(qǐng)求并處理響應(yīng)
try {
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
DeepSeekResponse deepSeekResponse = JSON.parseObject(response.body().string(), DeepSeekResponse.class);
return deepSeekResponse.getResponse();
} catch (IOException e) {
e.printStackTrace();
}
return "服務(wù)器繁忙!";
}隨便寫一個(gè)前端頁(yè)面使用axios訪問(wèn)剛才暴露出來(lái)的接口就可以啦
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>智能 AI</title>
<link rel="stylesheet" rel="external nofollow" >
<link rel="stylesheet" href="/css/self.css" rel="external nofollow" >
</head>
<body>
<div id="app">
<div class="chat-container">
<div v-if="showTitle" class="welcome-title">你好!我是CloseAI,有什么可以幫助你的嗎?</div>
<div class="chat-messages">
<transition-group name="list">
<div v-for="message in messages" :key="message.id" class="message-wrapper"
:class="{'user-message-wrapper': message.sender === 'user', 'ai-message-wrapper': message.sender === 'ai'}">
<img :src="message.sender === 'user' ? '/images/user.png' : '/images/ai.png'" class="avatar"/>
<div class="message"
:class="{'user-message': message.sender === 'user', 'ai-message': message.sender === 'ai'}">
<span v-if="message.sender === 'user'">{{ message.text }}</span>
<div v-else v-html="message.formattedText || message.text"></div>
<div v-if="message.sender === 'ai' && message.isLoading" class="loading-icon"></div>
<!-- 調(diào)整停止按鈕容器位置 -->
<div v-if="(isThinking || animationFrameId) && message.sender === 'ai' && message.isActive"
class="stop-container">
<button @click="stopThinking" class="stop-btn" title="停止響應(yīng)">
<svg width="24" height="24" viewBox="0 0 24 24">
<rect x="6" y="4" width="4" height="16" rx="1"/>
<rect x="14" y="4" width="4" height="16" rx="1"/>
</svg>
</button>
</div>
</div>
</div>
</transition-group>
</div>
<div class="chat-input">
<input type="text" v-model="userInput" @keyup.enter="sendMessage" placeholder="給 CloseAI 發(fā)送消息..."/>
<button @click="sendMessage">Send</button>
</div>
</div>
</div>
<script src="/js/vue.js"></script>
<script src="/js/axios.min.js"></script>
<script src="/js/method.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.5/purify.min.js"></script>
<script>
function debounce(func, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
new Vue({
el: '#app',
data: {
userInput: '',
messages: [],
showTitle: true, // 添加一個(gè)新屬性來(lái)控制標(biāo)題的顯示
performanceConfig: {
maxMessageLength: 1000, // 超過(guò)該長(zhǎng)度啟用優(yōu)化
chunkSize: window.innerWidth < 768 ? 3 : 5 // 響應(yīng)式分段
},
// 新增控制變量
isThinking: false,
currentController: null, // 請(qǐng)求中止控制器
animationFrameId: null // 動(dòng)畫幀ID
},
methods: {
sendMessage() {
if (this.userInput.trim() !== '') {
this.showTitle = false; // 用戶開(kāi)始提問(wèn)時(shí)隱藏標(biāo)題
const userMessage = {
id: Date.now(),
sender: 'user',
text: this.userInput
};
this.messages.push(userMessage);
this.userInput = '';
// 停用所有舊消息
this.messages.forEach(msg => {
if (msg.sender === 'ai') {
this.$set(msg, 'isActive', false);
}
});
const aiMessage = {
id: Date.now() + 1,
sender: 'ai',
text: '思考中 ',
isLoading: true,
isThinking: true, // 新增狀態(tài)字段
isActive: true // 新增激活狀態(tài)字段
};
this.messages.push(aiMessage);
// 在請(qǐng)求前重置狀態(tài)
this.isThinking = true;
// 使用 axios 的取消令牌
const controller = new AbortController();
this.currentController = controller;
axios.get('/deepSeek/chat?question=' + userMessage.text, {
signal: controller.signal
}).then(response => {
aiMessage.isLoading = false;
aiMessage.text = ''
aiMessage.rawContent = response.data; // 新增原始內(nèi)容存儲(chǔ)
let index = 0;
let chunk = '';
const chunkSize = this.performanceConfig.chunkSize;
let lastUpdate = 0;
let lastFullRender = 0;
const processChunk = () => {
// 分塊處理邏輯
const remaining = response.data.length - index;
const step = remaining > chunkSize * 5 ? chunkSize * 5 : 1;
chunk += response.data.slice(index, index + step);
index += step;
// 增量更新文本
aiMessage.text = chunk;
this.safeParseMarkdown(aiMessage, true); // 實(shí)時(shí)解析
this.scrollToBottom();
};
const animate = (timestamp) => {
// 時(shí)間片控制邏輯
if (timestamp - lastUpdate > 16) { // 約60fps
processChunk();
lastUpdate = timestamp;
}
// 完整渲染控制(每100ms強(qiáng)制更新一次)
if (timestamp - lastFullRender > 100) {
this.$forceUpdate();
lastFullRender = timestamp;
}
if (timestamp - lastUpdate > 20) {
const remainingChars = response.data.length - index;
const step = remainingChars > chunkSize ? chunkSize : 1;
aiMessage.text += response.data.substr(index, step);
index += step;
this.safeParseMarkdown(aiMessage);
this.scrollToBottom();
lastUpdate = timestamp;
}
if (index < response.data.length) {
this.animationFrameId = requestAnimationFrame(animate);
} else {
this.$set(aiMessage, 'isActive', false); // 關(guān)閉激活狀態(tài)
this.$set(aiMessage, 'formattedText',
DOMPurify.sanitize(marked.parse(aiMessage.text))
);
this.animationFrameId = null; // 新增重置
this.isThinking = false; // 在此處更新?tīng)顟B(tài)
this.finalizeMessage(aiMessage);
}
};
// 修改動(dòng)畫啟動(dòng)方式
this.animationFrameId = requestAnimationFrame(animate);
}).catch(error => {
if (error.name !== 'CanceledError') {
console.error('Error:', error);
}
}).finally(() => {
this.animationFrameId = null;
// 新增消息狀態(tài)更新
this.messages.forEach(msg => {
if (msg.sender === 'ai') {
msg.isLoading = false;
msg.isThinking = false;
}
});
});
}
},
// 新增滾動(dòng)方法
scrollToBottom() {
const container = this.$el.querySelector('.chat-messages');
container.scrollTop = container.scrollHeight;
},
// 優(yōu)化的Markdown解析方法
safeParseMarkdown: debounce(function (aiMessage, immediate = false) {
if (immediate) {
// // 快速解析基礎(chǔ)格式(粗體、斜體等)
// const quickFormatted = aiMessage.text
// .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
// .replace(/\*(.*?)\*/g, '<em>$1</em>');
// 完整Markdown解析
this.$set(aiMessage, 'formattedText',
DOMPurify.sanitize(marked.parse(aiMessage.text))
);
} else {
// 完整Markdown解析
this.$set(aiMessage, 'formattedText',
DOMPurify.sanitize(marked.parse(aiMessage.text))
);
}
}, 50), // 完整解析保持50ms防抖
stopThinking() {
// 只停止當(dāng)前活動(dòng)消息
const activeMessage = this.messages.find(msg =>
msg.sender === 'ai' && msg.isActive
);
if (activeMessage) {
// 更新消息狀態(tài)
this.$set(activeMessage, 'text', activeMessage.text + '\n(響應(yīng)已停止)');
this.$set(activeMessage, 'isLoading', false);
this.$set(activeMessage, 'isActive', false);
this.safeParseMarkdown(activeMessage);
}
// 取消網(wǎng)絡(luò)請(qǐng)求
if (this.currentController) {
this.currentController.abort()
}
// 停止打印渲染
if (this.animationFrameId) {
cancelAnimationFrame(this.animationFrameId);
this.animationFrameId = null;
}
// 更新所有相關(guān)消息狀態(tài)
this.messages.forEach(msg => {
if (msg.sender === 'ai' && (msg.isLoading || msg.isThinking)) {
msg.text += '\n(響應(yīng)已停止)';
msg.isLoading = false;
msg.isThinking = false;
this.safeParseMarkdown(msg);
}
});
this.isThinking = false;
this.animationFrameId = null; // 確保重置
},
// 新增最終處理函數(shù)
finalizeMessage(aiMessage) {
this.$set(aiMessage, 'formattedText',
DOMPurify.sanitize(marked.parse(aiMessage.text))
);
this.$set(aiMessage, 'isActive', false);
this.animationFrameId = null;
this.isThinking = false;
this.$forceUpdate();
},
}
});
</script>
</body>
</html>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.chat-container {
width: 100%;
/*max-width: 800px;*/
background-color: #fff;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
}
.welcome-title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
text-align: center;
font-size: 24px;
font-weight: bold;
}
/* 新增停止按鈕樣式 */
.stop-btn {
background-color: #ff4d4f;
color: white;
margin-left: 8px;
transition: all 0.3s;
}
.stop-btn:hover {
background-color: #f5f7fa;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
vertical-align: middle;
}
.chat-messages {
/*flex: 1;*/
overflow-y: auto;
padding: 20px;
/*display: flex;*/
flex-direction: column-reverse;
height: 70vh;
width: 500px;
scrollbar-width: none;
scroll-behavior: smooth; /* 平滑滾動(dòng)效果 */
contain: strict; /* 限制瀏覽器重排范圍 */
transform: translateZ(0);
}
.message {
margin-bottom: 15px;
padding: 12px;
border-radius: 12px;
max-width: 70%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
/*align-self: flex-end; !* 默認(rèn)消息靠右對(duì)齊 *!*/
display: table;
}
.message-wrapper {
display: flex;
max-width: 80%;
margin: 10px;
align-items: flex-start;
will-change: transform, opacity; /* 啟用GPU加速 */
}
/*.user-message-wrapper {*/
/* justify-content: flex-end;*/
/*}*/
.ai-message-wrapper {
justify-content: flex-start;
position: relative; /* 為絕對(duì)定位的停止按鈕提供參考系 */
margin-bottom: 50px; /* 給停止按鈕留出空間 */
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
vertical-align: middle;
}
.message {
margin-bottom: 0;
}
.user-message {
background-color: #007bff;
color: #fff;
margin-left: auto; /* 用戶消息靠右對(duì)齊 */
}
.ai-message {
background-color: #f0f2f5; /* AI消息背景色 */
margin-right: auto; /* 消息內(nèi)容靠左 */
position: relative; /* 添加相對(duì)定位 */
padding-bottom: 40px; /* 為按鈕預(yù)留空間 */
}
/* 在self.css中添加 */
.user-message-wrapper {
flex-direction: row-reverse; /* 反轉(zhuǎn)排列方向 */
margin-left: auto; /* 讓用戶消息靠右 */
}
.user-message-wrapper .avatar {
margin: 0 0 0 15px; /* 調(diào)整頭像右邊距 */
}
.chat-input {
display: flex;
align-items: center;
padding: 15px;
background-color: #f8f9fa;
}
.chat-input input {
flex: 1;
padding: 12px;
border: 1px solid #ccc;
border-radius: 6px;
margin-right: 15px;
transition: border-color 0.3s ease;
}
.chat-input input:focus {
border-color: #007bff;
}
.chat-input button {
padding: 12px 24px;
border: none;
border-radius: 6px;
background-color: #007bff;
color: #fff;
cursor: pointer;
transition: background-color 0.3s ease;
}
.message {
display: flex;
align-items: center;
}
/* 調(diào)整停止按鈕定位 */
.stop-container {
position: absolute;
bottom: 10px;
right: 10px;
z-index: 10;
}
.stop-btn {
background: #ff4757;
border: none;
border-radius: 50%;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transition: transform 0.2s;
}
.stop-btn:hover {
transform: scale(1.1);
}
.stop-btn svg {
fill: white;
width: 16px;
height: 16px;
}
.ai-message pre {
background: #f5f7fa;
padding: 15px;
border-radius: 6px;
overflow-x: auto;
}
.ai-message code {
font-family: 'Courier New', monospace;
font-size: 14px;
}
.ai-message table {
border-collapse: collapse;
margin: 10px 0;
}
.ai-message td, .ai-message th {
border: 1px solid #ddd;
padding: 8px;
}
.loading-icon {
width: 20px;
height: 20px;
border: 2px solid #ccc;
border-top-color: #007bff;
border-radius: 50%;
/*animation: spin 1s linear infinite;*/
margin-left: 10px;
/* 替換為CSS動(dòng)畫實(shí)現(xiàn)的加載效果 */
/*background: linear-gradient(90deg, #eee 25%, #ddd 50%, #eee 75%);*/
animation: spin 1s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.chat-input button:hover {
background-color: #0056b3;
}
.list-enter-active, .list-leave-active {
transition: all 0.5s ease;
}
.list-enter, .list-leave-to /* .list-leave-active in <2.1.8 */ {
opacity: 0;
transform: translateY(30px);
}
我的這個(gè)頁(yè)面有bug,只供參考!??!


到此這篇關(guān)于JAVA集成本地部署的DeepSeek的圖文教程的文章就介紹到這了,更多相關(guān)JAVA集成本地部署DeepSeek內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Idea中的.properties文件顯示問(wèn)題
這篇文章主要介紹了關(guān)于Idea中的.properties文件顯示問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
30w+數(shù)據(jù)使用RedisTemplate?pipeline空指針NullPointerException異常分析
這篇文章主要為大家介紹了30w+數(shù)據(jù)使用RedisTemplate?pipeline空指針NullPointerException異常分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
如何通過(guò)idea給web項(xiàng)目打war包
這篇文章主要介紹了如何通過(guò)idea給web項(xiàng)目打war包問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Java @PostMapping和@GetMapping方法使用詳解
這篇文章主要介紹了Java @PostMapping和@GetMapping方法使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-03-03
Spring boot 總結(jié)之跨域處理cors的方法
本篇文章主要介紹了Spring boot 總結(jié)之跨域處理cors的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02

