SpringBoot -No1: Controller无法注入 service 的坑

这几天做了个springboot的小项目

开始的时候,将启动的类指定为  当前的controller,里面没有依赖注入service ,一切都正常

后面专门 做了个MainApp用来启动 , 也在Controller中注入了Service。

我把这个类放到了contoller包中

但是发现总是启动不起来了.

报错的原因是 无法找到  这个service 

肯定是 service就没被扫描到。

认知中springboot是不用 配置这个 componentscan的

问题出在哪呢??

继续深读springboot发现:

SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描!

这个 @SpringBootApplication 指定的类是指SpringBoot项目入口类。这个类的位置很关键

从上往下扫描:因为我把这个类放在了controller包中,那么就只会扫描 controller包和子包中的类

那么service包中的类自然就扫描不到了



重新调整下这个类的位置: 将它放入到这个顶层的位置,哈哈问题终于解决了




<template> <div class="operation-container"> <!-- 顶部信息卡片 --> <el-card class="header-card"> <div class="header-content"> <div class="info-item"> <div class="label">问卷标题:</div> <div class="value">{{ detailData.dcWjTitle || '--' }}</div> </div> <div class="info-item"> <div class="label">被测评人:</div> <div class="value">{{ detailData.dcName || '--' }}</div> </div> <div class="info-item"> <div class="label">部门:</div> <div class="value">{{ detailData.dcDept || '--' }}</div> </div> </div> </el-card> <!-- 问卷问题区域 --> <el-card class="question-card" v-for="(question, index) in questions" :key="index"> <div class="question-header"> <div class="question-title">{{ question.id }}、{{ question.content }}</div> <el-tag type="success">已选择: {{ getOptionText(question, detailData[question.field]) }}</el-tag> </div> <div class="options-container"> <div v-for="(option, optIndex) in question.options" :key="optIndex" class="option-item" :class="{ 'selected': detailData[question.field] == option.value, 'disabled': detailData.state === '1' }" > <div class="option-label">{{ option.label }}</div> <div class="option-value">({{ option.value }})</div> </div> </div> </el-card> <!-- 底部操作按钮 --> <div class="action-buttons"> <el-button type="primary" size="large" @click="handleSubmit" :disabled="detailData.state === '1'" > {{ detailData.state === '1' ? '已提交' : '提交问卷' }} </el-button> <el-button size="large" @click="handleBack" > 返回列表 </el-button> </div> </div> </template> <script setup> import { ref, reactive, onMounted } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import axios from 'axios'; import { ElMessage } from 'element-plus'; const route = useRoute(); const router = useRouter(); // 环境变量管理API地址 const API_BASE = import.meta.env.VITE_API_BASE || 'http://172.26.26.43/dev-api'; // 问卷详情数据 const detailData = reactive({}); const loading = ref(false); const wjId = ref(null); // 问题配置 const questions = reactive([ { id: 1, field: 'no1', content: '被测评人员是否具有较高的"核心与看齐意识"能够坚持贯彻执行公司的决策部署', options: [ { label: '很不赞同', value: 1 }, { label: '不赞同', value: 2 }, { label: '一般', value: 3 }, { label: '赞同', value: 4 }, { label: '很赞同', value: 5 } ] }, // 其他问题配置(实际使用时需要补充完整) { id: 2, field: 'no2', content: '问题二内容...', options: [ // 选项配置... ] }, // 更多问题... ]); // 获取选项文本 const getOptionText = (question, value) => { const option = question.options.find(opt => opt.value == value); return option ? option.label : '未选择'; }; // 获取问卷ID onMounted(() => { wjId.value = route.params.id; if (wjId.value) { fetchDetail(); } else { ElMessage.error('未获取到问卷ID'); router.back(); } }); // 获取认证令牌 const getAuthToken = () => { const token = localStorage.getItem('token'); if (!token) { ElMessage.warning('请先登录'); router.push('/login'); return null; } return token; }; // 获取问卷详情 const fetchDetail = async () => { const token = getAuthToken(); if (!token) return; loading.value = true; try { const response = await axios.get(`${API_BASE}/wjdc/wj/${wjId.value}`, { headers: { 'Authorization': `Bearer ${token}` } }); if (response.data && response.data.code === 200) { Object.assign(detailData, response.data.data || {}); ElMessage.success('问卷数据加载成功'); } else { const errorMsg = response.data?.msg || '获取问卷详情失败'; ElMessage.error(errorMsg); } } catch (error) { console.error('获取问卷详情失败:', error); let errorMsg = '网络请求失败'; if (error.response) { if (error.response.status === 401) { errorMsg = '认证过期,请重新登录'; localStorage.removeItem('token'); router.push('/login'); } else if (error.response.data?.msg) { errorMsg = error.response.data.msg; } } ElMessage.error(`获取问卷详情失败: ${errorMsg}`); } finally { loading.value = false; } }; // 提交问卷 const handleSubmit = () => { ElMessage.success('问卷提交成功'); detailData.state = '1'; }; // 返回列表 const handleBack = () => { router.push({ name: 'Detail' }); }; </script> <style scoped> .operation-container { padding: 16px; max-width: 1200px; margin: 0 auto; } /* 顶部信息卡片 */ .header-card { border-radius: 12px; margin-bottom: 20px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); } .header-content { display: flex; flex-wrap: wrap; gap: 20px 40px; } .info-item { display: flex; align-items: center; min-width: 300px; } .label { font-weight: 600; color: #606266; font-size: 16px; min-width: 80px; } .value { font-size: 18px; color: #303133; font-weight: 500; } /* 问题卡片 */ .question-card { border-radius: 12px; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); } .question-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #eee; } .question-title { font-size: 18px; font-weight: 600; color: #1a1a1a; flex: 1; margin-right: 20px; } /* 选项容器 */ .options-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px; } .option-item { display: flex; align-items: center; padding: 12px 15px; border: 1px solid #dcdfe6; border-radius: 6px; transition: all 0.3s; cursor: pointer; } .option-item:hover:not(.disabled) { background-color: #f5f7fa; border-color: #c0c4cc; } .option-item.selected { background-color: #ecf5ff; border-color: #409eff; color: #409eff; } .option-item.disabled { cursor: not-allowed; opacity: 0.7; } .option-label { flex: 1; font-size: 16px; } .option-value { font-weight: 600; margin-left: 10px; min-width: 40px; text-align: center; } /* 操作按钮 */ .action-buttons { display: flex; justify-content: center; gap: 30px; margin-top: 30px; } /* 响应式设计 */ @media (max-width: 768px) { .header-content { flex-direction: column; gap: 15px; } .info-item { min-width: auto; width: 100%; } .question-header { flex-direction: column; align-items: flex-start; gap: 10px; } .options-container { grid-template-columns: 1fr; } .action-buttons { flex-direction: column; gap: 15px; } .action-buttons .el-button { width: 100%; } } @media (max-width: 480px) { .question-title { font-size: 16px; } .option-item { padding: 10px; } .option-label { font-size: 14px; } } </style> 帮我优化一下,每个问题的选项是一样的只是问题不同
最新发布
07-17
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值