JAVA后端+鸿蒙前端用户管理系统
概要
Java后端 + 鸿蒙前端用户管理系统(全栈项目)
后端基于 **Spring Boot 4.x + MyBatis-Plus + MySQL** 搭建,采用三层架构提供 RESTful API,实现用户数据的增删改查与模糊搜索,返回 JSON 数据。
前端基于 **HarmonyOS + ArkTS** 开发,采用 MVVM 架构,使用 ArkUI 组件搭建界面,通过 HTTP 网络请求调用后端接口,实现用户列表展示、添加、删除等功能。
前后端分离,通过 JSON 格式交互数据,打通从数据库到手机屏幕的完整数据链路。
整体架构流程
用户操作(手机屏幕)
↓
鸿蒙前端(ArkTS + ArkUI)
├── View 层:UserPage 页面展示,用户点击按钮
├── ViewModel 层:UserViewModel 处理业务逻辑,管理状态
├── Model 层:UserModel 定义用户数据结构
├── 网络工具类:NetWorkUtil 发送 HTTP 请求
↓ GET/POST/DELETE(JSON 数据)
SpringBoot 后端(Java)
├── Controller 层:UserController 接收请求,返回 JSON
├── Service 层:UserService 处理增删改查业务
├── Mapper 层:UserMapper 操作数据库(MyBatis-Plus)
↓ SQL
MySQL 数据库(user_manager)
↓ 返回数据
逐层向上返回 JSON → 鸿蒙 ViewModel 解析数据 → View 刷新界面
JAVA部分

鸿蒙ArkTs部分:

运行结果图

技术名词解释
用户操作(手机屏幕)
↓
HarmonyOS 前端(ArkTS + ArkUI + ComponentV2)
├── View 层:UserPage(@ComponentV2 + @Local)
├── ViewModel 层:UserViewModel(@ObservedV2 + @Trace)
├── Model 层:UserModel(实体类)
├── 网络工具类:NetWorkUtil(@kit.NetworkKit + Promise 异步)
↓ HTTP RESTful API(JSON)
SpringBoot 4.x 后端(内嵌 Tomcat,端口 8080)
├── Controller 层:UserController(@RestController + @RequestMapping)
├── Service 层:UserService(@Service + 业务逻辑封装)
├── Mapper 层:UserMapper(继承 BaseMapper,零 SQL CRUD)
↓ JDBC
MySQL 8.0 数据库(user_manager.user 表,自增主键)
↓ 返回数据
JSON 响应 → ViewModel 解析 → @Trace 触发 UI 刷新 → ArkUI 组件渲染
技术细节
一:JAVA部分(必须使用springboot):
UserController:
package com.itheima.student_manager.controller;
import com.itheima.student_manager.entity.User;
import com.itheima.student_manager.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用户管理 RESTful API
* 完整路径前缀:/api/users
*/
@RestController // 所有方法返回值自动转为 JSON
@RequestMapping("/users") // 路径前缀
public class UserController {
@Autowired
private UserService userService;
/**
* 查询所有用户
* GET http://localhost:8080/api/users
*/
@GetMapping
public List<User> listAll() {
return userService.listAll();
}
/**
* 根据ID查询单个用户
* GET http://localhost:8080/api/users/1
*/
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return userService.getById(id);
}
/**
* 根据姓名模糊查询
* GET http://localhost:8080/api/users/search?name=张
*/
@GetMapping("/search")
public List<User> search(@RequestParam String name) {
return userService.searchByName(name);
}
/**
* 添加用户(接收 JSON 数据)
* POST http://localhost:8080/api/users
* 请求体:{"name": "张三", "age": 20, "email": "zs@qq.com"}
*/
@PostMapping
public String add(@RequestBody User user) {
boolean success = userService.add(user);
return success ? "添加成功" : "添加失败";
}
/**
* 修改用户
* PUT http://localhost:8080/api/users/1
* 请求体:{"name": "李四", "age": 21, "email": "ls@qq.com"}
*/
@PutMapping("/{id}")
public String update(@PathVariable Long id, @RequestBody User user) {
user.setId(id); // 把路径中的ID设置到用户对象上
boolean success = userService.update(user);
return success ? "修改成功" : "修改失败";
}
/**
* 删除用户
* DELETE http://localhost:8080/api/users/1
*/
@DeleteMapping("/{id}")
public String delete(@PathVariable Long id) {
boolean success = userService.delete(id);
return success ? "删除成功" : "删除失败";
}
}
User
package com.itheima.student_manager.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 用户实体类
* 对应数据库中的 user 表
*/
@Data // 自动生成 getter/setter/toString
@TableName("user") // 指定数据库表名
public class User {
/**
* 用户ID(主键,自动生成)
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 用户姓名
*/
private String name;
/**
* 用户年龄
*/
private Integer age;
/**
* 用户邮箱
*/
private String email;
}
UserMapper
package com.itheima.student_manager.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.student_manager.entity.User;
import org.apache.ibatis.annotations.Mapper;
/**
* 用户数据访问层
* 继承 BaseMapper 后,自动拥有增删改查方法,无需写 SQL
*/
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 继承的方法:
// insert(User user) → 添加用户
// deleteById(Long id) → 根据ID删除
// updateById(User user) → 根据ID更新
// selectById(Long id) → 根据ID查询
// selectList(null) → 查询全部
// selectPage(...) → 分页查询
}
UserService
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.student_manager.entity.User;
import com.itheima.student_manager.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 用户业务逻辑层
* 处理具体业务,如查重、数据校验等
*/
@Service // 声明为 Spring 的 Service 组件
public class UserService {
@Autowired
private UserMapper userMapper;
/**
* 查询所有用户
*/
public List<User> listAll() {
return userMapper.selectList(null);
}
/**
* 根据ID查询用户
*/
public User getById(Long id) {
return userMapper.selectById(id);
}
/**
* 根据姓名模糊查询
*/
public List<User> searchByName(String name) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", name); // SQL: WHERE name LIKE '%name%'
return userMapper.selectList(wrapper);
}
/**
* 添加用户
*/
public boolean add(User user) {
return userMapper.insert(user) > 0; // 返回true表示成功
}
/**
* 更新用户
*/
public boolean update(User user) {
return userMapper.updateById(user) > 0;
}
/**
* 删除用户
*/
public boolean delete(Long id) {
return userMapper.deleteById(id) > 0;
}
}
StudentManagerApplication
package com.itheima.student_manager;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.itheima.student_manager.mapper") // 扫描 Mapper 接口
public class StudentManagerApplication {
public static void main(String[] args) {
SpringApplication.run(StudentManagerApplication.class, args);
}
}
application.yaml
server:
servlet:
context-path: /api
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/user_manager?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: 123456
# MyBatis-Plus 自动建表
mybatis-plus:
global-config:
db-config:
table-auto: update
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itheima</groupId>
<artifactId>student_manager</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>student_manager</name>
<description>student_manager</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.42</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二:鸿蒙部分(前端):
UserModel
export class UserModel {
id: number;
name: string;
age: number;
email: string;
constructor(id: number, name: string, age: number, email: string) {
this.id = id;
this.name = name;
this.age = age;
this.email = email;
}
}
NetWorkUtil
import { http } from '@kit.NetworkKit';
export class NetWorkUtil {
private static async request(
url: string,
method: http.RequestMethod,
data?: Object
): Promise<string> {
let httpRequest = http.createHttp();
return new Promise<string>((resolve, reject) => {
httpRequest.on('headersReceive', (header: Object) => {
console.info('响应头: ' + JSON.stringify(header));
});
let requestParams: http.HttpRequestOptions = {
method: method,
header: {
// 关键:伪装成浏览器
'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',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Cache-Control': 'no-cache',
},
expectDataType: http.HttpDataType.STRING,
connectTimeout: 60000,
readTimeout: 60000
};
if (method === http.RequestMethod.POST && data) {
requestParams.extraData = JSON.stringify(data);
}
httpRequest.request(url, requestParams, (err: Error, httpResponse: http.HttpResponse) => {
if (!err) {
console.info('响应码: ' + httpResponse.responseCode);
if (httpResponse.responseCode === 200) {
// 修复 result 处理
const result = httpResponse.result;
const resultStr = Array.isArray(result) ? result.join('') : result.toString();
console.info('获取成功,数据长度: ' + resultStr.length);
resolve(resultStr);
} else {
console.error('响应码异常: ' + httpResponse.responseCode);
reject(new Error(`请求失败,响应码: ${httpResponse.responseCode}`));
}
} else {
console.error('请求失败: ' + JSON.stringify(err));
reject(err);
}
httpRequest.off('headersReceive');
httpRequest.destroy();
});
});
}
static async get(url: string): Promise<string> {
return NetWorkUtil.request(url, http.RequestMethod.GET);
}
static async post(url: string, data: Object): Promise<string> {
return NetWorkUtil.request(url, http.RequestMethod.POST, data);
}
static async delete(url: string): Promise<string> {
return NetWorkUtil.request(url, http.RequestMethod.DELETE);
}
}
UserViewModel
import { UserModel } from '../model/UserModel';
import { NetWorkUtil } from '../util/NetWorkUtil';
const BASE_URL: string = 'http://10.0.2.2:8080/api';
@ObservedV2
export class UserViewModel {
@Trace users: UserModel[] = [];
@Trace isLoading: boolean = false;
@Trace resultMessage: string = '';
/**
* 将 JSON 字符串解析为 UserModel 数组
*/
private parseUsers(responseStr: string): UserModel[] {
const rawData: Object[] = JSON.parse(responseStr) as Object[];
const userList: UserModel[] = [];
for (let i = 0; i < rawData.length; i++) {
const item: Record<string, Object> = rawData[i] as Record<string, Object>;
const user: UserModel = new UserModel(
item['id'] as number,
item['name'] as string,
item['age'] as number,
item['email'] as string
);
userList.push(user);
}
return userList;
}
/**
* 查询所有用户
*/
async fetchAllUsers(): Promise<void> {
this.isLoading = true;
try {
const responseStr: string = await NetWorkUtil.get(`${BASE_URL}/users`);
this.users = this.parseUsers(responseStr);
} catch (err) {
this.resultMessage = '获取用户列表失败';
} finally {
this.isLoading = false;
}
}
/**
* 添加用户
*/
async addUser(name: string, age: number, email: string): Promise<void> {
this.isLoading = true;
try {
const data: Record<string, Object> = {
'name': name,
'age': age,
'email': email
};
const responseStr: string = await NetWorkUtil.post(`${BASE_URL}/users`, data);
this.resultMessage = responseStr;
await this.fetchAllUsers();
} catch (err) {
this.resultMessage = '添加用户失败';
} finally {
this.isLoading = false;
}
}
/**
* 删除用户
*/
async deleteUser(id: number): Promise<void> {
this.isLoading = true;
try {
const responseStr: string = await NetWorkUtil.delete(`${BASE_URL}/users/${id}`);
console.info('=== 删除返回: ' + responseStr);
this.resultMessage = responseStr;
await this.fetchAllUsers();
} catch (err) {
console.error('=== 删除失败: ' + JSON.stringify(err));
this.resultMessage = '删除失败';
} finally {
this.isLoading = false;
}
}
/**
* 搜索用户
*/
async searchUsers(name: string): Promise<void> {
this.isLoading = true;
try {
const responseStr: string = await NetWorkUtil.get(`${BASE_URL}/users/search?name=${name}`);
this.users = this.parseUsers(responseStr);
} catch (err) {
this.resultMessage = '搜索失败';
} finally {
this.isLoading = false;
}
}
}
UserPage
import { UserViewModel } from '../viewmodel/UserViewModel';
import { UserModel } from '../model/UserModel';
@ComponentV2
export struct UserPage {
@Local viewModel: UserViewModel = new UserViewModel();
@Local inputName: string = '';
@Local inputAge: string = '';
@Local inputEmail: string = '';
aboutToAppear(): void {
this.viewModel.fetchAllUsers();
}
@Builder
itemBuilder(user: UserModel) {
Row() {
Text(`${user.id}`).width('10%').fontSize(14)
Text(user.name).width('20%').fontSize(16)
Text(`${user.age}`).width('10%').fontSize(14)
Text(user.email).width('35%').fontSize(14).fontColor(Color.Gray)
Button('删除')
.fontSize(12)
.onClick(() => {
this.viewModel.deleteUser(user.id);
})
}
.width('100%')
.padding(10)
.border({ width: { bottom: 0.5 }, color: Color.Gray })
}
build() {
Column() {
Text('用户管理系统')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Row() {
TextInput({ placeholder: '姓名', text: this.inputName })
.width('25%')
.onChange((value: string) => { this.inputName = value; })
TextInput({ placeholder: '年龄', text: this.inputAge })
.width('20%')
.onChange((value: string) => { this.inputAge = value; })
TextInput({ placeholder: '邮箱', text: this.inputEmail })
.width('30%')
.onChange((value: string) => { this.inputEmail = value; })
Button('添加')
.fontSize(12)
.onClick(() => {
this.viewModel.addUser(this.inputName, parseInt(this.inputAge), this.inputEmail);
this.inputName = '';
this.inputAge = '';
this.inputEmail = '';
})
}
.width('100%')
.padding(10)
if (this.viewModel.resultMessage !== '') {
Text(this.viewModel.resultMessage)
.fontColor(this.viewModel.resultMessage.includes('成功') ? Color.Green : Color.Red)
.margin(5)
}
if (this.viewModel.isLoading) {
LoadingProgress().width(30).height(30).margin(20)
}
List() {
ForEach(this.viewModel.users, (user: UserModel) => {
ListItem() {
this.itemBuilder(user)
}
})
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.padding(10)
}
}
Index
import { UserPage } from './UserPage';
@Entry
@ComponentV2
struct Index {
build() {
Column() {
UserPage()
}
.width('100%')
.height('100%')
}
}
module.json5 网络请求依赖
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
小结
完成了一个 Java 后端(SpringBoot + MyBatis-Plus)+ 鸿蒙前端(ArkTS + ArkUI) 的全栈学生管理系统,打通了前后端分离的完整数据链路。
更多推荐



所有评论(0)