02教师信息的新增功能

Views: 0

逻辑

前端操作:

管理员点击”新增”按钮 弹出空白表单,填写教师信息(用户名、姓名、性别等) 点击”保存”按钮提交

后端处理:

// 1. 检查用户名是否已存在(防重复) Teacher dbTeacher = teacherMapper.selectByUsername(teacher.getUsername()); if(已存在){ 直接报错:”用户名已存在” }

// 2. 设置默认值: if(没填密码){ 自动设置密码为”123456″ } 强制设置角色为”TEACHER”

// 3. 保存到数据库 teacherMapper.insert(teacher);

结果反馈:

成功:提示”新增成功”,列表自动刷新显示新教师 失败:提示具体原因

关键处理点

唯一性校验:通过用户名检查教师是否已存在 默认值设置: 密码为空时自动设为”123456″ 角色固定设为”TEACHER” 异常处理:用户名存在时抛出业务异常 数据流向:Controller → Service → Mapper → DB(数据库)

创建教师信息表

CREATE TABLE `teacher` (
 `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
 `username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
 `password` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密码',
 `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '姓名',
 `sex` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '性别',
 `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '职称',
 `speciality_id` int DEFAULT NULL COMMENT '专业id',
 `role` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '角色',
 `avatar` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '头像',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='教师信息';

idea中Mac快捷键

替换

get,set方法:

找到插件GenerateAllSetter

一键调用一个对象的所有的set方法,get方法等 在方法上生成两个对象的转换

快捷键:control+enter

导包:

自动导包/修复导包问题:⌘ + Enter 优化导包(移除未使用的):⌃ + ⌥ + O 手动导包提示:⌘ + N

entity—teacher

public class Teacher extends Account {
   private Integer id;
   private String username;
   private String password;
   private String name;
   private String sex;
   private String title;
   private Integer specialityId;
   private String specialityName;
   private String role;
   private String avatar;

//get和set方法
   @Override
   public Integer getId() {
       return id;
  }

   @Override
   public void setId(Integer id) {
       this.id = id;
  }

   @Override
   public String getUsername() {
       return username;
  }

   @Override
   public void setUsername(String username) {
       this.username = username;
  }

   @Override
   public String getPassword() {
       return password;
  }

   @Override
   public void setPassword(String password) {
       this.password = password;
  }

   @Override
   public String getName() {
       return name;
  }

   @Override
   public void setName(String name) {
       this.name = name;
  }

   public String getSex() {
       return sex;
  }

   public void setSex(String sex) {
       this.sex = sex;
  }

   public String getTitle() {
       return title;
  }

   public void setTitle(String title) {
       this.title = title;
  }

   public Integer getSpecialityId() {
       return specialityId;
  }

   public void setSpecialityId(Integer specialityId) {
       this.specialityId = specialityId;
  }

   @Override
   public String getRole() {
       return role;
  }

   @Override
   public void setRole(String role) {
       this.role = role;
  }

   @Override
   public String getAvatar() {
       return avatar;
  }
   @Override
   public void setAvatar(String avatar) {
       this.avatar = avatar;
  }

   public String getSpecialityName() {
       return specialityName;
  }
   public void setSpecialityName(String specialityName) {
       this.specialityName = specialityName;
  }
}

解决前端vue里面没有错警告

比如

设置(setting)里面——修改html里面

前端添加教师信息

<el-menu-item index="/teacher">
<el-icon><Avatar /></el-icon>
/*图标在 https://element-plus.org/ 里面找*/
<span>教师信息</span>
</el-menu-item>

现在前端也有教师信息菜单了,图标也可以更改

配置路由,加一个teacher信息

{ path: 'teacher', component: () => import('@/views/manager/teacher.vue')},

在manager下面新建一个Teacher.vue

vue

<template>
 <div>
     <!-- 新增按钮 可以参考Admin.vue里面的内容 -->
   <div class="card" style="margin-bottom: 5px">
     <div style="margin-bottom: 10px">
       <!-- 新增教师按钮,点击触发handleAdd方法 -->
       <el-button type="primary" @click="handleAdd">新增</el-button>
     </div>
   </div>
   <!-- 教师信息弹窗对话框 -->
   <el-dialog title="教师信息" width="40%" v-model="data.formVisible" :close-on-click-modal="false" destroy-on-close>
     <el-form :model="data.form" label-width="100px" style="padding-right: 50px">
       <!--prop v-model 里面要与后端保持一致不然接收不到   -->
       <el-form-item label="账号" prop="username">
         <el-input v-model="data.form.username" autocomplete="off" placeholder="请输入账号"/>
       </el-form-item>
       <el-form-item label="姓名" prop="name">
         <el-input v-model="data.form.name" autocomplete="off" placeholder="请输入姓名"/>
       </el-form-item>
       <el-form-item label="性别" prop="sex">
         <el-select v-model="data.form.sex" placeholder="请选择性别" style="width: 100%">
           <el-option label="男" value="男"></el-option>
           <el-option label="女" value="女"></el-option>
         </el-select>
       </el-form-item>
       <el-form-item label="职称" prop="title">
         <el-select v-model="data.form.title" placeholder="请选择职称" style="width: 100%">
           <el-option label="讲师" value="讲师"></el-option>
           <el-option label="副教授" value="副教授"></el-option>
           <el-option label="教授" value="教授"></el-option>
         </el-select>
       </el-form-item>
     </el-form>
     <!-- 弹窗取消,保存     -->
     <template #footer>
     <span class="dialog-footer">
       <el-button @click="data.formVisible = false">取 消</el-button>
       <el-button type="primary" @click="save">保 存</el-button>
     </span>
     </template>
   </el-dialog>
   </div>
</template>

<script setup>
//导包
import {reactive} from "vue";
import request from "@/utils/request";
import {ElMessage} from "element-plus";

const data = reactive({
 // 教师信息弹窗对话框
 formVisible: false,
 // 教师信息表单数据
 form: {
},
})
// 新增教师按钮点击事件
const handleAdd = () => {
 // 清空教师信息表单数据
 data.form = {

}
 // 打开教师信息弹窗对话框
 data.formVisible = true
}
const save = () => {
 // 调用后端接口保存教师信息
 // 这里可以使用axios或者其他请求库发送请求
 // 例如:axios.post('/api/teacher/add', data.form)
 request.post('/teacher/add', data.form).then(res => {
   if (res.code === '200') {
     // 保存成功,提示用户
     ElMessage.success('操作成功')
     // 关闭教师信息弹窗对话框
     data.formVisible = false
  }else {
     // 保存失败,提示用户
     ElMessage.error(res.msg)
  }
})
}
</script>

Controller—TeacherController


/**
* 教师模块前端操作接口入口
* 拿到数据后,调用service层的方法,返回结果
* 前端调用接口时,需要传入参数,调用service层的方法,返回结果
**/@RestController

@RequestMapping("/teacher")
public class TeacherController {
   @Resource
//   注入TeacherService
   private TeacherService teacherService;

   /**
    * 新增教师
    * */
   @PostMapping("/add")
   public Result add(@RequestBody Teacher teacher){
       teacherService.add(teacher);
       return Result.success();
  }
}

Service—TeacherService 核心逻辑

package com.example.service;

import cn.hutool.core.util.ObjectUtil;
import com.example.entity.Teacher;
import com.example.exception.CustomException;
import com.example.mapper.TeacherMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
/**
* 教师模块业务逻辑接口
* 要把数据往数据库里存,调用mapper层的方法,返回结果
* 业务逻辑接口调用mapper层的方法,返回结果
*/
@Service
public class TeacherService {
//   注入TeacherMapper
   @Resource
   private TeacherMapper teacherMapper;
   /**
    * 新增教师
    */
   public void add(Teacher teacher) {
       // ToDo 新增教师逻辑处理
       // 检查教师是否已经存在,检查用户唯一性
       Teacher dbTeacher = teacherMapper.selectByUsername(teacher.getUsername());
       if (ObjectUtil.isNotEmpty(dbTeacher)) {
           throw new CustomException("用户名已存在");
      }
//       如果没有密码,就设置密码为123456
       if(ObjectUtil.isEmpty(teacher.getPassword())){
           teacher.setPassword("123456");
      }
     // 固定角色
       teacher.setRole("TEACHER");
     // 持久化操作
       teacherMapper.insert(teacher);
  }
}

mapper—TeacherMapper

package com.example.mapper;

//接口

import com.example.entity.Teacher;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface TeacherMapper {
//   新增教师
   void insert(Teacher teacher);
   @Select("select * from teacher where username = #{username}")
   Teacher selectByUsername(String username);
}

TeacherMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.TeacherMapper">
   <insert id="insert" parameterType="com.example.entity.Teacher" useGeneratedKeys="true">
      insert into teacher (username, password, name,sex,title,speciality_id,role,avatar)
      values (#{username}, #{password}, #{name}, #{sex}, #{title}, #{specialityId}, #{role}, #{avatar})
   </insert>
</mapper>

简单逻辑在mapper可以用注解,复杂逻辑用xml namespace 对应mapper接口的全类名 1. 映射文件的位置必须和mapper接口的包结构相同 2. 映射文件的名称必须和mapper接口的名称相同 3. 映射文件的后缀名必须是.xml 1. 映射文件中的sql语句的id必须和mapper接口中的方法名相同 2. 映射文件中的sql语句的参数类型必须和mapper接口中的方法参数类型相同 3. 映射文件中的sql语句的返回值类型必须和mapper接口中的方法返回值类型相同

1. Controller(控制层)

  • 职责
    • 接收客户端请求(HTTP/RPC等),解析参数(如URL、Body、Header)。
    • 调用 Service 层处理业务逻辑。
    • 返回响应(JSON/XML等)或视图(如HTML)。
  • 特点
    • 轻量级,仅做请求转发和参数校验,不包含业务逻辑
    • 通常使用 @Controller@RestController 注解(Spring中)。

2. Service(业务逻辑层)

  • 职责
    • 处理核心业务逻辑(如订单创建、用户权限校验)。
    • 协调多个 Mapper 操作(事务管理)。
    • 调用外部服务(如支付接口、消息队列)。
  • 特点
    • 使用 @Service 注解,是业务逻辑的集中点
    • 可能涉及事务(@Transactional)。

3. Mapper(数据访问层,或称DAO)

  • 职责
    • 直接操作数据库(CRUD),执行SQL语句。
    • 与数据库表一一对应(如MyBatis的 @Mapper 或JPA的Repository)。
  • 特点
    • 无业务逻辑,仅做数据持久化。
    • 使用 @Mapper(MyBatis)或继承 JpaRepository(Spring Data JPA)。

三者的协作流程

  1. 请求入口
    • 客户端 → Controller(接收请求) → 调用 Service
  2. 业务处理
    • Service 处理逻辑 → 调用 Mapper 读写数据库。
  3. 数据持久化
    • Mapper 执行SQL → 返回数据给 ServiceService 返回结果给 Controller
  4. 响应输出
    • Controller 将结果封装为响应 → 返回客户端。

关键原则

  • 单向依赖ControllerServiceMapper(禁止反向依赖或跨层调用)。
  • 职责隔离
    • Controller 不管业务,Service 不管SQL,Mapper 只管数据库。
  • 复用性: 一个 Service 可能被多个 Controller 调用,一个 Mapper 可能被多个 Service 调用。

通过这种分层设计,系统更易于维护、扩展和测试,符合高内聚低耦合的软件工程原则

先写前端然后写后端——ControllerServiceMapper

版权声明

本网站名称:学海拾茜
本文链接:https://www.61lyf.top/02%e6%95%99%e5%b8%88%e4%bf%a1%e6%81%af%e7%9a%84%e6%96%b0%e5%a2%9e%e5%8a%9f%e8%83%bd/
本网站的文章部分内容可能来源于网络,仅供学习与参考,如有侵权,请联系站长进行核实删除。
转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处并附带原文链接!!!
站长邮箱:cyg1900@outlook.com 或studygod825@qq.com ,如不方便留言可邮件联系。
暂无评论

发送评论 编辑评论


				
上一篇
下一篇