最普通的 CRUDS 能10分钟快速搞定吗

Table of Contents

1. 项目结构

我们将项目分为两个部分:

  • 后端:Spring Boot + Spring Data JPA + MySQL
  • 前端:Vue.js 3

项目结构如下:

task-manager/
├── backend/               # Spring Boot 项目
│   ├── src/
│   │   ├── main/
│   │   │   ├── java/
│   │   │   │   └── com/
│   │   │   │       └── example/
│   │   │   │           ├── controller/
│   │   │   │           ├── model/
│   │   │   │           ├── repository/
│   │   │   │           └── service/
│   │   │   └── resources/
│   │   │       ├── application.properties
│   │   │       └── data.sql
│   │   └── test/
│   └── pom.xml
└── frontend/              # Vue.js 3 项目
    ├── public/
    ├── src/
    │   ├── assets/
    │   ├── components/
    │   ├── router/
    │   ├── views/
    │   ├── App.vue
    │   └── main.js
    ├── package.json
    └── vite.config.js

2. 后端实现(Spring Boot + Spring Data JPA + MySQL)

2.1 配置 MySQL 数据库

application.properties 中配置 MySQL 连接:

spring.datasource.url=jdbc:mysql://localhost:3306/task_manager
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

2.2 创建 Task 实体类

model 包中创建 Task.java

package com.example.model;

import jakarta.persistence.*;
import java.time.LocalDateTime;

@Entity
public class Task {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String priority;
    private int duration; // in minutes
    private LocalDateTime scheduleTime;
    private LocalDateTime startTime;
    private LocalDateTime endTime;
    private LocalDateTime deadline;

    // Getters and Setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getPriority() { return priority; }
    public void setPriority(String priority) { this.priority = priority; }
    public int getDuration() { return duration; }
    public void setDuration(int duration) { this.duration = duration; }
    public LocalDateTime getScheduleTime() { return scheduleTime; }
    public void setScheduleTime(LocalDateTime scheduleTime) { this.scheduleTime = scheduleTime; }
    public LocalDateTime getStartTime() { return startTime; }
    public void setStartTime(LocalDateTime startTime) { this.startTime = startTime; }
    public LocalDateTime getEndTime() { return endTime; }
    public void setEndTime(LocalDateTime endTime) { this.endTime = endTime; }
    public LocalDateTime getDeadline() { return deadline; }
    public void setDeadline(LocalDateTime deadline) { this.deadline = deadline; }
}

2.3 创建 TaskRepository 接口

repository 包中创建 TaskRepository.java

package com.example.repository;

import com.example.model.Task;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;

public interface TaskRepository extends JpaRepository<Task, Long> {
    List<Task> findByNameContaining(String name); // 搜索功能
}

2.4 创建 TaskService 服务类

service 包中创建 TaskService.java

package com.example.service;

import com.example.model.Task;
import com.example.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class TaskService {
    @Autowired
    private TaskRepository taskRepository;

    public List<Task> getAllTasks() {
        return taskRepository.findAll();
    }

    public Task getTaskById(Long id) {
        return taskRepository.findById(id).orElse(null);
    }

    public Task createTask(Task task) {
        return taskRepository.save(task);
    }

    public Task updateTask(Long id, Task taskDetails) {
        Task task = taskRepository.findById(id).orElse(null);
        if (task != null) {
            task.setName(taskDetails.getName());
            task.setPriority(taskDetails.getPriority());
            task.setDuration(taskDetails.getDuration());
            task.setScheduleTime(taskDetails.getScheduleTime());
            task.setStartTime(taskDetails.getStartTime());
            task.setEndTime(taskDetails.getEndTime());
            task.setDeadline(taskDetails.getDeadline());
            return taskRepository.save(task);
        }
        return null;
    }

    public void deleteTask(Long id) {
        taskRepository.deleteById(id);
    }

    public List<Task> searchTasks(String name) {
        return taskRepository.findByNameContaining(name);
    }
}

2.5 创建 TaskController 控制器

controller 包中创建 TaskController.java

package com.example.controller;

import com.example.model.Task;
import com.example.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/tasks")
public class TaskController {
    @Autowired
    private TaskService taskService;

    @GetMapping
    public List<Task> getAllTasks() {
        return taskService.getAllTasks();
    }

    @GetMapping("/{id}")
    public Task getTaskById(@PathVariable Long id) {
        return taskService.getTaskById(id);
    }

    @PostMapping
    public Task createTask(@RequestBody Task task) {
        return taskService.createTask(task);
    }

    @PutMapping("/{id}")
    public Task updateTask(@PathVariable Long id, @RequestBody Task taskDetails) {
        return taskService.updateTask(id, taskDetails);
    }

    @DeleteMapping("/{id}")
    public void deleteTask(@PathVariable Long id) {
        taskService.deleteTask(id);
    }

    @GetMapping("/search")
    public List<Task> searchTasks(@RequestParam String name) {
        return taskService.searchTasks(name);
    }
}

3. 前端实现(Vue.js 3)

3.1 创建 Vue.js 项目

使用 Vite 创建 Vue.js 项目:

npm create vite@latest frontend --template vue
cd frontend
npm install

3.2 安装 Axios

安装 Axios 用于 HTTP 请求:

npm install axios

3.3 创建 Task 组件

src/components/ 下创建 TaskList.vueTaskForm.vue

TaskList.vue

<template>
  <div>
    <h1>Task List</h1>
    <input v-model="searchQuery" placeholder="Search tasks" @input="searchTasks" />
    <ul>
      <li v-for="task in tasks" :key="task.id">
        {{ task.name }} - {{ task.priority }}
        <button @click="editTask(task)">Edit</button>
        <button @click="deleteTask(task.id)">Delete</button>
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      tasks: [],
      searchQuery: ''
    };
  },
  created() {
    this.fetchTasks();
  },
  methods: {
    fetchTasks() {
      axios.get('http://localhost:8080/api/tasks').then(response => {
        this.tasks = response.data;
      });
    },
    searchTasks() {
      axios.get(`http://localhost:8080/api/tasks/search?name=${this.searchQuery}`).then(response => {
        this.tasks = response.data;
      });
    },
    editTask(task) {
      this.$emit('edit-task', task);
    },
    deleteTask(id) {
      axios.delete(`http://localhost:8080/api/tasks/${id}`).then(() => {
        this.fetchTasks();
      });
    }
  }
};
</script>

TaskForm.vue

<template>
  <div>
    <h2>{{ editMode ? 'Edit Task' : 'Create Task' }}</h2>
    <form @submit.prevent="submitForm">
      <input v-model="task.name" placeholder="Name" required />
      <input v-model="task.priority" placeholder="Priority" required />
      <input v-model="task.duration" type="number" placeholder="Duration (minutes)" required />
      <input v-model="task.scheduleTime" type="datetime-local" placeholder="Schedule Time" />
      <input v-model="task.startTime" type="datetime-local" placeholder="Start Time" />
      <input v-model="task.endTime" type="datetime-local" placeholder="End Time" />
      <input v-model="task.deadline" type="datetime-local" placeholder="Deadline" />
      <button type="submit">{{ editMode ? 'Update' : 'Create' }}</button>
    </form>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  props: {
    taskToEdit: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      task: { ...this.taskToEdit },
      editMode: !!this.taskToEdit.id
    };
  },
  methods: {
    submitForm() {
      if (this.editMode) {
        axios.put(`http://localhost:8080/api/tasks/${this.task.id}`, this.task).then(() => {
          this.$emit('task-updated');
        });
      } else {
        axios.post('http://localhost:8080/api/tasks', this.task).then(() => {
          this.$emit('task-created');
        });
      }
    }
  }
};
</script>

3.4 在 App.vue 中使用组件

<template>
  <div>
    <TaskForm :taskToEdit="taskToEdit" @task-created="fetchTasks" @task-updated="fetchTasks" />
    <TaskList @edit-task="setTaskToEdit" />
  </div>
</template>

<script>
import TaskForm from './components/TaskForm.vue';
import TaskList from './components/TaskList.vue';

export default {
  components: {
    TaskForm,
    TaskList
  },
  data() {
    return {
      taskToEdit: {}
    };
  },
  methods: {
    fetchTasks() {
      this.$refs.taskList.fetchTasks();
    },
    setTaskToEdit(task) {
      this.taskToEdit = task;
    }
  }
};
</script>

4. 运行项目

  1. 启动 Spring Boot 后端:
    cd backend
    mvn spring-boot:run
  2. 启动 Vue.js 前端:
    cd frontend
    npm run dev
  3. 访问 http://localhost:5173 即可使用 Task 管理功能。

通过以上步骤,我们快速实现了一个基于 Spring Boot + Vue.js 的 Task CRUDS 应用!

Comments |0|

Legend *) Required fields are marked
**) You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Category: 似水流年