下面我將詳細介紹如何在基于 TypeScript 的前端項目中使用 umi-request 調用 IntelliJ IDEA 中開發的 Java 接口,包括完整的實現方案和代碼示例。
整體方案設計
一、Java 后端接口準備
1. 創建 Spring Boot 控制器
// src/main/java/com/example/demo/controller/UserController.java
@RestController
@RequestMapping("/api")
public class UserController {@GetMapping("/users")public ResponseEntity<List<UserDTO>> getUsers() {// 實際業務邏輯 - 從數據庫獲取用戶List<UserDTO> users = userService.getAllUsers();return ResponseEntity.ok(users);}@PostMapping("/users")public ResponseEntity<UserDTO> createUser(@RequestBody UserDTO userDTO) {UserDTO savedUser = userService.createUser(userDTO);return new ResponseEntity<>(savedUser, HttpStatus.CREATED);}@GetMapping("/users/{id}")public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {UserDTO user = userService.getUserById(id);return ResponseEntity.ok(user);}
}
2. 定義 DTO 對象
// src/main/java/com/example/demo/dto/UserDTO.java
public class UserDTO {private Long id;private String username;private String email;private LocalDateTime createdAt;// 必須有無參構造函數public UserDTO() {}// 必須有 getter 和 setterpublic Long getId() { return id; }public void setId(Long id) { this.id = id; }// ...其他 getter/setter
}
3. 解決跨域問題
// src/main/java/com/example/demo/config/WebConfig.java
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://localhost:8000") // 前端開發地址.allowedMethods("GET", "POST", "PUT", "DELETE").allowedHeaders("*").allowCredentials(true).maxAge(3600);}
}
二、前端配置與實現
1. 安裝 umi-request
npm install umi-request --save
# 或
yarn add umi-request
2. 創建請求工具文件
src/utils/request.ts
import { extend } from 'umi-request';
import { notification } from 'antd';// 定義后端接口基礎URL
const API_BASE_URL = process.env.NODE_ENV === 'production' ? 'https://api.yourdomain.com' : 'http://localhost:8080';// 創建請求實例
const request = extend({prefix: API_BASE_URL,timeout: 10000,headers: {'Content-Type': 'application/json',},errorHandler: (error) => {// 統一錯誤處理const { response } = error;if (response && response.status) {const errorText = response.statusText || '請求錯誤';const { status } = response;notification.error({message: `請求錯誤 ${status}`,description: errorText,});} else if (!response) {notification.error({message: '網絡異常',description: '無法連接到服務器,請檢查網絡',});}return Promise.reject(error);},
});// 請求攔截器
request.interceptors.request.use((url, options) => {// 添加認證 tokenconst token = localStorage.getItem('token');if (token) {options.headers = {...options.headers,Authorization: `Bearer ${token}`,};}return { url, options };
});// 響應攔截器
request.interceptors.response.use(async (response) => {const data = await response.clone().json();// 處理業務邏輯錯誤if (data && data.code !== 0) {notification.error({message: '操作失敗',description: data.message || '服務器返回錯誤',});}return response;
});export default request;
3. 定義 TypeScript 接口類型
src/services/types.ts
// 用戶數據類型
export interface User {id: number;username: string;email: string;createdAt: string; // 前端通常使用字符串表示日期
}// 創建用戶參數
export interface CreateUserParams {username: string;email: string;password: string;
}// API 響應格式
export interface ApiResponse<T> {code: number;message: string;data: T;
}
4. 創建 API 服務
src/services/userService.ts
import request from '@/utils/request';
import { User, CreateUserParams, ApiResponse } from './types';// 獲取用戶列表
export async function getUsers(): Promise<ApiResponse<User[]>> {return request('/api/users', {method: 'GET',});
}// 創建用戶
export async function createUser(params: CreateUserParams
): Promise<ApiResponse<User>> {return request('/api/users', {method: 'POST',data: params,});
}// 獲取單個用戶
export async function getUserById(id: number
): Promise<ApiResponse<User>> {return request(`/api/users/${id}`, {method: 'GET',});
}
5. 在 React 組件中使用
src/pages/UserList/index.tsx
import React, { useState, useEffect } from 'react';
import { Table, Button, Form, Input, message } from 'antd';
import { getUsers, createUser } from '@/services/userService';
import type { User, CreateUserParams } from '@/services/types';const UserList: React.FC = () => {const [users, setUsers] = useState<User[]>([]);const [loading, setLoading] = useState(false);const [form] = Form.useForm();// 加載用戶數據const loadUsers = async () => {setLoading(true);try {const response = await getUsers();if (response.code === 0) {setUsers(response.data);}} catch (error) {message.error('加載用戶數據失敗');} finally {setLoading(false);}};useEffect(() => {loadUsers();}, []);// 提交新用戶表單const handleSubmit = async (values: CreateUserParams) => {try {const response = await createUser(values);if (response.code === 0) {message.success('用戶創建成功');form.resetFields();loadUsers(); // 刷新列表}} catch (error) {message.error('創建用戶失敗');}};const columns = [{title: 'ID',dataIndex: 'id',key: 'id',},{title: '用戶名',dataIndex: 'username',key: 'username',},{title: '郵箱',dataIndex: 'email',key: 'email',},{title: '創建時間',dataIndex: 'createdAt',key: 'createdAt',},];return (<div style={{ padding: 24 }}><h2>用戶管理</h2>{/* 用戶列表 */}<Table dataSource={users} columns={columns} loading={loading}rowKey="id"/>{/* 創建用戶表單 */}<Formform={form}layout="vertical"onFinish={handleSubmit}style={{ marginTop: 24, maxWidth: 500 }}><Form.Itemlabel="用戶名"name="username"rules={[{ required: true, message: '請輸入用戶名' }]}><Input placeholder="請輸入用戶名" /></Form.Item><Form.Itemlabel="郵箱"name="email"rules={[{ required: true, message: '請輸入郵箱' },{ type: 'email', message: '請輸入有效的郵箱地址' }]}><Input placeholder="請輸入郵箱" /></Form.Item><Form.Itemlabel="密碼"name="password"rules={[{ required: true, message: '請輸入密碼' }]}><Input.Password placeholder="請輸入密碼" /></Form.Item><Form.Item><Button type="primary" htmlType="submit">創建用戶</Button></Form.Item></Form></div>);
};export default UserList;
三、環境配置與優化
1. 配置環境變量
.env.development
# 開發環境配置
API_BASE_URL=http://localhost:8080
.env.production
# 生產環境配置
API_BASE_URL=https://api.yourdomain.com
修改 request.ts
const API_BASE_URL = process.env.API_BASE_URL || 'http://localhost:8080';
2. 接口文檔集成(可選)
在 Java 項目中添加 Swagger 支持:
// pom.xml
<dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version>
</dependency>// SwaggerConfig.java
@Configuration
@EnableSwagger2
public class SwaggerConfig {@Beanpublic Docket api() {return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build();}
}
前端可以通過訪問?http://localhost:8080/swagger-ui/
?查看 API 文檔
3. 安全認證處理
Java 端添加 JWT 認證
@PostMapping("/login")
public ResponseEntity<AuthResponse> login(@RequestBody LoginRequest request) {// 驗證用戶名密碼// 生成 JWT tokenString token = JwtUtil.generateToken(userDetails);return ResponseEntity.ok(new AuthResponse(token));
}
前端處理認證
// 在 request.ts 的攔截器中
request.interceptors.request.use((url, options) => {// 排除登錄接口if (url.includes('/login')) return { url, options };const token = localStorage.getItem('token');if (token) {options.headers = {...options.headers,Authorization: `Bearer ${token}`,};}return { url, options };
});// 處理 401 未授權
request.interceptors.response.use(async (response) => {if (response.status === 401) {// 跳轉到登錄頁window.location.href = '/login';}return response;
});
四、調試與錯誤排查
常見問題解決方案
問題 | 可能原因 | 解決方案 |
---|---|---|
404 錯誤 | 接口路徑錯誤 | 檢查前后端路徑是否一致 |
403 錯誤 | 跨域問題 | 確認后端 CORS 配置正確 |
401 錯誤 | 未授權 | 檢查認證 token 是否有效 |
500 錯誤 | 后端異常 | 查看 Java 控制臺日志 |
網絡錯誤 | 服務未啟動 | 確認 Java 服務正在運行 |
調試工具
-
瀏覽器開發者工具
-
Network 標簽查看請求/響應詳情
-
Console 查看錯誤信息
-
-
Postman 測試接口
-
直接測試 Java 接口是否正常工作
-
-
IDEA HTTP Client
-
在 IDEA 中創建?
.http
?文件測試接口
-
### 獲取用戶列表
GET http://localhost:8080/api/users### 創建用戶
POST http://localhost:8080/api/users
Content-Type: application/json{"username": "testuser","email": "test@example.com","password": "password123"
}
五、生產環境部署
Nginx 配置示例
nginxserver {listen 80;server_name yourdomain.com;# 前端靜態文件location / {root /path/to/frontend/dist;index index.html;try_files $uri $uri/ /index.html;}# 后端 API 代理location /api {proxy_pass http://localhost:8080;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}# 其他配置...
}
總結
通過以上步驟,你可以完整實現 TypeScript 前端使用 umi-request 調用 Java 接口的功能:
-
Java 后端:創建 RESTful API 并解決跨域問題
-
前端配置:設置 umi-request 實例和攔截器
-
類型安全:定義 TypeScript 接口類型
-
服務封裝:創建 API 服務模塊
-
組件集成:在 React 組件中調用 API
-
環境配置:設置不同環境的 API 地址
-
安全認證:集成 JWT 認證機制
-
部署優化:配置生產環境部署方案
這種架構提供了清晰的分離和類型安全,使得前后端開發可以并行進行,同時保持了代碼的可維護性和可擴展性。