当前位置: 首页 > news >正文

第二个简单的SpringBoot和Vue前后端全栈的todoapp案例

项目源于哔哩哔哩,按视频手敲了一下,补充上代码和一些细节。

全栈项目实践:1小时快速入门SpringBoot+vue3+element-plus_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LH4y1w7Nd/?spm_id_from=333.1387.favlist.content.click&vd_source=3d07f741ba02111ffca810ad6ade218a

H2数据库的安装和使用

  1. H2 Database Enginehttps://h2database.com/html/main.html 官网下载安装版文件h2-setup-2024-08-11.exehttps://github.com/h2database/h2database/releases/download/version-2.3.232/h2-setup-2024-08-11.exe
  2. IDEA配置H2,名称填写test时,会自动生成test.mv.db数据库文件,注意URL的写法,测试连接成功则配置成功
    jdbc:h2:file:C:/Users/Administrator/Desktop/todoapp/todoapp/test
  3. 数据库使用SQL语言建表Todo
    -- auto-generated definition
    create table TODO
    (ID        BIGINT auto_incrementprimary key,TITLE     CHARACTER VARYING(256),COMPLETED BOOLEAN
    );

  4. application.properties定义好H2数据库
    spring.h2.console.enabled=true
    spring.datasource.url=jdbc:h2:file:C:/Users/Administrator/Desktop/todoapp/todoapp/test
    spring.datasource.driver-class-name=org.h2.Driver
    spring.datasource.username=sa
    spring.datasource.password=password
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
  5. SpringBoot先网络测试要出现200成功

其他的根据视频来就行,没要到视频代码,自己手敲一份,附上代码部分。

package com.example.todoapp.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowedMethods("*").allowedHeaders("*");}
}
package com.example.todoapp.controller;import com.example.todoapp.domain.Todo;
import com.example.todoapp.service.TodoService;
import jakarta.annotation.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/api/todos")
public class TodoController {@Resourceprivate TodoService todoService;@GetMappingpublic List<Todo> getAllTodos() {return todoService.getAllTodos();}@PostMappingpublic Todo createTodo(@RequestBody Todo todo) {return todoService.createTodo(todo);}@PutMapping("/{id}")public Todo updateTodo(@PathVariable Long id, @RequestBody Todo updatedTodo) {return todoService.updateTodo(id, updatedTodo);}@DeleteMapping("/{id}")public  void  deleteTodo(@PathVariable Long id){todoService.deleteTodo(id);}
}
package com.example.todoapp.dao;import com.example.todoapp.domain.Todo;
import org.springframework.data.jpa.repository.JpaRepository;public interface TodoRepository extends JpaRepository<Todo, Long> {
}
package com.example.todoapp.domain;import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;@Entity
public class Todo {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String title;private Boolean completed;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public Boolean getCompleted() {return completed;}public void setCompleted(Boolean completed) {this.completed = completed;}@Overridepublic String toString() {return "Todo{" +"id=" + id +", title='" + title + '\'' +", completed=" + completed +'}';}
}
package com.example.todoapp.service;import com.example.todoapp.domain.Todo;import java.util.List;public interface TodoService {List<Todo> getAllTodos();Todo createTodo(Todo todo);Todo updateTodo(Long id,Todo updatedTodo);void deleteTodo(Long id);
}
package com.example.todoapp.service;import com.example.todoapp.dao.TodoRepository;
import com.example.todoapp.domain.Todo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class TodoServiceImpl implements TodoService {@Resourceprivate TodoRepository todoRepository;@Overridepublic List<Todo> getAllTodos() {return todoRepository.findAll();}@Overridepublic Todo createTodo(Todo todo) {return todoRepository.save(todo);}@Overridepublic Todo updateTodo(Long id, Todo updatedTodo) {return todoRepository.findById(id).map(todo -> {todo.setTitle(updatedTodo.getTitle());todo.setCompleted(updatedTodo.getCompleted());return todoRepository.save(todo);}).orElseGet(() -> {updatedTodo.setId(id);return todoRepository.save(updatedTodo);});}@Overridepublic void deleteTodo(Long id) {todoRepository.deleteById(id);}
}
<script setup>
import { onMounted, ref } from 'vue'
import axios from 'axios'
import { ElMessage } from 'element-plus'const newTodo = ref('')const todos = ref([])const axiosInstance = axios.create({baseURL: 'http://localhost:8080',timeout: 5000,
})const fetchTodos = async () => {try {const response = await axiosInstance.get('/api/todos')todos.value = response.data} catch (error) {ElMessage.error('查询待办事项失败')console.error(error)}
}const addTodo = async () => {if (!newTodo.value) returntry {const response = await axiosInstance.post('/api/todos', {title: newTodo.value,completed: false,})todos.value.push(response.data)newTodo.value = ''ElMessage.success('待办事项创建成功')} catch (error) {ElMessage.error('待办事项创建失败')console.error(error)}
}const toggleCompleted = async (todo) => {try {todo.completed = !todo.completedawait axiosInstance.put(`/api/todos/${todo.id}`, todo)ElMessage.success('待办事项更新成功')} catch (error) {ElMessage.error('待办事项更新失败')console.error(error)todo.completed = !todo.completed}
}const deleteTodo = async (todo) => {try {await axiosInstance.delete(`/api/todos/${todo.id}`)await fetchTodos()ElMessage.success('待办事项更新成功')} catch (error) {ElMessage.error('待办事项更新失败')console.error(error)todo.completed = !todo.completed}
}onMounted(fetchTodos)
</script><template><div class="todo-app"><el-card class="todo-card"><template #header><div class="todo-header">待办事项</div></template><div class="todo-input"><el-input v-model="newTodo" placeholder="新建待办事项..."></el-input><el-button type="primary" @click="addTodo">添加</el-button></div><div v-if="todos.length" class="todo-list"><el-card v-for="todo in todos" :key="todo.id" class="todo-item"><div class="todo-item-actions"><div class="todo-item-title">{{ todo.title }}</div><el-buttonclass="todo-button"@click="toggleCompleted(todo)":type="todo.completed ? 'success' : 'info'">{{ todo.completed ? '已完成' : '未完成' }}</el-button><el-button type="danger" @click="deleteTodo(todo)">删除</el-button></div></el-card></div><div v-else class="no-todos">暂无待办事项</div></el-card></div>
</template><style scoped>
.todo-app {display: flex;justify-self: center;align-items: center;height: 100vh;background: #f0f2f5;padding: 20px;box-sizing: border-box;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.todo-card {width: 100%;max-width: 500px;border-radius: 8px;box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.1);background: #ffffff;
}
.todo-header {font-size: 24px;font-weight: bold;text-align: center;padding: 16px;background-color: #409eff;color: #fff;border-radius: 8px 8px 0 0;margin: 0;
}
.todo-input {display: flex;align-items: center;gap: 10px;padding: 20px;background-color: #fff;border-bottom: 1px solid #ebeef5;
}
.el-input {flex: 1;
}
.todo-list {padding: 20px;background-color: #fff;
}
.todo-item {display: flex;justify-content: space-between;align-items: center;padding: 10px 15px;border: 1px solid #ebeef5;border-radius: 8px;background-color: #f9f9f9;transition:background-color 0.3s,transform 0.3s;
}
.todo-item:hover {background-color: #ebf7ff;tranform: translateY(-2px);
}
.todo-item-title {font-weight: bold;flex: 1;margin-right: 20px;word-wrap: break-word;width: 160px;
}
.completed .todo-item-title {text-decoration: line-through;color: #909399;
}
.todo-item-actions {display: flex;align-items: center;
}
.no-todos {text-align: center;padding: 20px;color: #909399;font-size: 18px;
}
</style>
<script setup>
import TodoList from './components/TodoList.vue';
</script><template><div id="app"><el-container><el-main><TodoList/></el-main></el-container></div>
</template>
import { createApp } from 'vue'
import App from './App.vue'
import 'element-plus/dist/index.css'
import ElementPlus from 'element-plus'const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

相关文章:

  • Ubuntu22.04安装显卡驱动/卸载显卡驱动
  • Python+OpenCV打造AR/VR基础框架:从原理到实战的全链路解析
  • 电子电器架构 --- 车载网关的设计
  • [特殊字符]Meilisearch:AI驱动的现代搜索引擎
  • 【MyBatis-7】深入理解MyBatis二级缓存:提升应用性能的利器
  • 从0开始学习大模型--Day05--理解prompt工程
  • STL-list
  • DA14585墨水屏学习
  • LLMs之ChatGPT:《Connecting GitHub to ChatGPT deep research》翻译与解读
  • [学习]RTKLib详解:sbas.c与rtcm.c
  • cursor sign in 网页登录成功,sursor软件里一直登陆不成功没有登陆信息
  • 扫雷革命:矩阵拓扑与安全扩散的数学之美
  • [架构之美]Spring Boot多环境5种方案实现Dev/Test/Prod环境隔离
  • 二、Hive安装部署详细过程
  • 深度学习中的目标检测:从 PR 曲线到 AP
  • 各种音频产品及场景总结
  • 【生存技能】ubuntu 24.04 如何pip install
  • 好用的播放器推荐
  • MySQL索引详解(上)(结构/分类/语法篇)
  • expo多网络请求设定。
  • 铁肩担道义,历史鉴未来——中共中央政治局委员、外交部长王毅谈习近平主席对俄罗斯进行国事访问并出席纪念苏联伟大卫国战争胜利80周年庆典
  • 碧桂园:砸锅卖铁保交房、持续推进保主体,尽快让公司恢复正常经营
  • 体坛联播|郑钦文收获红土赛季首胜,国际乒联公布财报
  • 王受文已任全国工商联党组成员
  • 印巴冲突升级,巴防长称已击落5架印度战机
  • 巴基斯坦军方:印度导弹袭击已造成至少3死14伤