开始尝试从0写一个项目--后端(二)
实现学生管理
新增学生
接口设计
请求路径:/admin/student
请求方法:POST
请求参数:请求头:Headers:"Content-Type": "application/json"
请求体:Body:
id 学生id
idNumber 学生身份证
name 名字
phone 电话号码
sex 性别
username 用户名
返回数据:Result
student表设计
字段名 | 数据类型 | 说明 | 备注 |
id | bigint | 主键 | 自增 |
name | varchar(32) | 姓名 | |
username | varchar(32) | 用户名 | 唯一 |
password | varchar(64) | 密码 | |
phone | varchar(11) | 手机号 | |
sex | varchar(2) | 性别 | |
id_number | varchar(18) | 身份证号 | |
status | Int | 账号状态 | 1正常 0锁定 |
create_time | Datetime | 创建时间 | |
update_time | datetime | 最后修改时间 | |
create_user | bigint | 创建人id | |
update_user | bigint | 最后修改人id |
代码开发
设计DTO类接收前端传来的参数
sems-pojo/src/main/java/com/ljc/dto/StudentDTO.java
package com.ljc.dto;import lombok.Data;import java.io.Serializable;@Data
public class StudentDTO implements Serializable {//学生idprivate Long id;//用户名private String username;//姓名private String name;//电话private String phone;//性别private String sex;//身份证号private String idNumber;}
controller层
sems-server/src/main/java/com/ljc/controller/student/StudentController.java
package com.ljc.controller.student;import com.ljc.constant.JwtClaimsConstant;
import com.ljc.dto.StudentDTO;
import com.ljc.dto.StudentLoginDTO;
import com.ljc.entity.Student;
import com.ljc.properties.JwtProperties;
import com.ljc.result.Result;
import com.ljc.service.StudentService;
import com.ljc.utils.JwtUtil;
import com.ljc.vo.StudentLoginVO;import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/admin/student")
@Slf4j
public class StudentController {@Autowiredprivate StudentService studentService;@Autowiredprivate JwtProperties jwtProperties;/*** 登录** @param studentLoginDTO* @return*/@ApiOperation("用户登录")@PostMapping("/login")public Result<StudentLoginVO> login(@RequestBody StudentLoginDTO studentLoginDTO) {log.info("学生登录:{}", studentLoginDTO);Student student = studentService.login(studentLoginDTO);//登录成功后,生成jwt令牌Map<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.EMP_ID, student.getId());String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);StudentLoginVO studentLoginVO = StudentLoginVO.builder().id(student.getId()).userName(student.getUsername()).name(student.getName()).token(token).build();return Result.success(studentLoginVO);}/*** 退出** @return*/@ApiOperation("用户退出")@PostMapping("/logout")public Result<String> logout() {return Result.success();}/*** 新增学生* @param studentDTO* @return*/@PostMapping@ApiOperation("新增学生")public Result save(@RequestBody StudentDTO studentDTO){//日志,现在进行的是新增学生功能log.info("新增学生:{}", studentDTO);//调用service层(处理层)的方法进行新增studentService.save(studentDTO);return Result.success();}}
Service层
sems-server/src/main/java/com/ljc/service/StudentService.java
package com.ljc.service;import com.ljc.dto.StudentDTO;
import com.ljc.dto.StudentLoginDTO;
import com.ljc.entity.Student;public interface StudentService {/*** 学生登录* @param studentLoginDTO* @return*/Student login(StudentLoginDTO studentLoginDTO);/*** 新增学生* @param studentDTO*/void save(StudentDTO studentDTO);
}
ServiceImpl层
sems-server/src/main/java/com/ljc/service/impl/StudentServiceImpl.java
package com.ljc.service.impl;import com.ljc.constant.MessageConstant;
import com.ljc.constant.PasswordConstant;
import com.ljc.constant.StatusConstant;
import com.ljc.context.BaseContext;
import com.ljc.dto.StudentDTO;
import com.ljc.dto.StudentLoginDTO;
import com.ljc.entity.Student;
import com.ljc.exception.AccountLockedException;
import com.ljc.exception.AccountNotFoundException;
import com.ljc.exception.PasswordErrorException;
import com.ljc.mapper.StudentMapper;
import com.ljc.service.StudentService;import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;import java.time.LocalDateTime;@Service
public class StudentServiceImpl implements StudentService {@Autowiredprivate StudentMapper studentMapper;/*** 学生登录** @param studentLoginDTO* @return*/public Student login(StudentLoginDTO studentLoginDTO) {String username = studentLoginDTO.getUsername();String password = studentLoginDTO.getPassword();//1、根据用户名查询数据库中的数据Student student = studentMapper.getByUsername(username);//2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)if (student == null) {//账号不存在throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);}//密码比对// 进行md5加密,然后再进行比对password = DigestUtils.md5DigestAsHex(password.getBytes());if (!password.equals(student.getPassword())) {//密码错误throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);}if (student.getStatus() == StatusConstant.DISABLE) {//账号被锁定throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);}//3、返回实体对象return student;}/**** 新增学生* @param studentDTO*/@Overridepublic void save(StudentDTO studentDTO) {//1. 创建一个学生对象Student student = new Student();//2. 将前端传后来的参数,即就是封装在DTO里面的数据转移到学生对象中//调用对象属性拷贝,括号里面参数,前面的是需要传递的数据,后面的是接收的数据BeanUtils.copyProperties(studentDTO,student);//3. 补充student里面的数据,前端没有传递回来的//3.1 前端没有传递账号状态,现在给设置账号状态:默认为正常,正常为1,异常为0;//由于1太不美观了,创建一个常量类/*student.setStatus(1);*/student.setStatus(StatusConstant.ENABLE);//3.2 设置密码:默认为123456,进行MD5加密//密码也设置一个常量:PasswordConstant.DEFAULT_PASSWORD/*student.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));*/student.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));//3.3 设置创建时间和修改时间: 为当前时间student.setCreateTime(LocalDateTime.now());student.setUpdateTime(LocalDateTime.now());//3.4 设置创建人的idstudent.setCreateUser(BaseContext.getCurrentId());student.setUpdateUser(BaseContext.getCurrentId());//4 调用mapper层数据,连接数据库,对数据库进行操作studentMapper.insert(student);}}
mapper层
sems-server/src/main/java/com/ljc/mapper/StudentMapper.java
package com.ljc.mapper;import com.ljc.entity.Student;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface StudentMapper {/*** 根据用户名查询学生* @param username* @return*/@Select("select * from student where username = #{username}")Student getByUsername(String username);/*** 新增学生* @param student*/@Insert("insert into student (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user,status) " +"values " +"(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")void insert(Student student);
}
补充代码
这里面有几个常量值,和一个ThreadLocal来获取jwt令牌里面的用户名
封装了 ThreadLocal 操作的工具类:
sems-common/src/main/java/com/ljc/context/BaseContext.java
package com.ljc.context;public class BaseContext {public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static void setCurrentId(Long id) {threadLocal.set(id);}public static Long getCurrentId() {return threadLocal.get();}public static void removeCurrentId() {threadLocal.remove();}}
常量类
密码
sems-common/src/main/java/com/ljc/constant/PasswordConstant.java
package com.ljc.constant;/*** 密码常量*/
public class PasswordConstant {public static final String DEFAULT_PASSWORD = "123456";}
补充用户名重复常量
sems-common/src/main/java/com/ljc/constant/MessageConstant.java
package com.ljc.constant;/*** 信息提示常量类*/
public class MessageConstant {public static final String PASSWORD_ERROR = "密码错误";public static final String ACCOUNT_NOT_FOUND = "账号不存在";public static final String ACCOUNT_LOCKED = "账号被锁定";public static final String UNKNOWN_ERROR = "未知错误";public static final String USER_NOT_LOGIN = "用户未登录";public static final String CATEGORY_BE_RELATED_BY_SETMEAL = "当前分类关联了套餐,不能删除";public static final String CATEGORY_BE_RELATED_BY_DISH = "当前分类关联了菜品,不能删除";public static final String SHOPPING_CART_IS_NULL = "购物车数据为空,不能下单";public static final String ADDRESS_BOOK_IS_NULL = "用户地址为空,不能下单";public static final String LOGIN_FAILED = "登录失败";public static final String UPLOAD_FAILED = "文件上传失败";public static final String SETMEAL_ENABLE_FAILED = "套餐内包含未启售菜品,无法启售";public static final String PASSWORD_EDIT_FAILED = "密码修改失败";public static final String DISH_ON_SALE = "起售中的菜品不能删除";public static final String SETMEAL_ON_SALE = "起售中的套餐不能删除";public static final String DISH_BE_RELATED_BY_SETMEAL = "当前菜品关联了套餐,不能删除";public static final String ORDER_STATUS_ERROR = "订单状态错误";public static final String ORDER_NOT_FOUND = "订单不存在";public static final String ALREADY_EXISTS = "已存在";
}
处理用户名重复的异常
sems-server/src/main/java/com/ljc/handler/GlobalExceptionHandler.java
package com.ljc.handler;import com.ljc.constant.MessageConstant;
import com.ljc.exception.BaseException;
import com.ljc.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import java.sql.SQLIntegrityConstraintViolationException;/*** 全局异常处理器,处理项目中抛出的业务异常*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {/*** 捕获业务异常* @param ex* @return*/@ExceptionHandlerpublic Result exceptionHandler(BaseException ex){log.error("异常信息:{}", ex.getMessage());return Result.error(ex.getMessage());}/*** 捕获用户名重复* */@ExceptionHandlerpublic Result exceptionHandler(SQLIntegrityConstraintViolationException ex){//Duplicate entry 'zhangsan' for key 'employee.idx_username'//获取异常信息String massage = ex.getMessage();//以” “分割异常信息;if (massage.contains("Duplicate entry")){String[] split = massage.split(" ");String name = split[2];String msg = name+ MessageConstant.ALREADY_EXISTS;//已存在已有常量,尽量避免字符串return Result.error(msg);}else {return Result.error(MessageConstant.UNKNOWN_ERROR);}}}
测试
完成后进入swagger界面测试一下
因为需要进行jwt令牌检测,所以
使用admin用户登录获取令牌
将合法的JWT令牌添加到全局参数中
检查一下添加上了没
然后开始测试
检查数据库添加上了没
学生分页查询
开发到这里我发现还得先开发前端,前端明确后,后端才有针对性,所以先完成前端代码。
麻了,前端一点不会啊,工期有点长了.....................
相关文章:

开始尝试从0写一个项目--后端(二)
实现学生管理 新增学生 接口设计 请求路径:/admin/student 请求方法:POST 请求参数:请求头:Headers:"Content-Type": "application/json" 请求体:Body: id 学生id …...

【图解大数据技术】Hive、HBase
【图解大数据技术】Hive、HBase Hive数据仓库Hive的执行流程Hive架构数据导入Hive HBaseHBase简介HBase架构HBase的列式存储HBase建表流程HBase数据写入流程HBase数据读取流程 Hive Hive是基于Hadoop的一个数据仓库工具,Hive的数据存储在HDFS上,底层基于…...
composables 目录下的文件(web前端)
composables 目录通常用于存放可组合的函数或逻辑,这些函数或逻辑可以在不同的组件中复用。具体来说,composables 目录下的文件通常包含以下内容: 组合式函数 (Composable Functions): 这些函数利用 Vue 3 的组合式 API࿰…...

使用Python绘制堆积柱形图
使用Python绘制堆积柱形图 堆积柱形图效果代码 堆积柱形图 堆积柱形图(Stacked Bar Chart)是一种数据可视化图表,用于显示不同类别的数值在某一变量上的累积情况。每一个柱状条显示多个子类别的数值,子类别的数值在柱状条上堆积在…...

DP:二维费用背包问题
文章目录 🎵二维费用背包问题🎶引言🎶问题定义🎶动态规划思想🎶状态定义和状态转移方程🎶初始条件和边界情况 🎵例题🎶1.一和零🎶2.盈利计划 🎵总结 …...
C语言标准库中的函数
由于C语言标准库中的函数非常多,我将按类别列出一些常见函数及其作用。请注意,这里不可能列出所有函数,但我会尽量覆盖主要的类别和函数。 ### 标准输入输出 - printf: 格式化输出到标准输出(通常是屏幕)。 - scanf: …...

Qt5.9.9 关于界面拖动导致QModbusRTU(QModbusTCP没有测试过)离线的问题
问题锁定 参考网友的思路: Qt5.9 Modbus request timeout 0x5异常解决 网友认为是Qt的bug, 我也认同;网友认为可以更新模块, 我也认同, 我也编译了Qt5.15.0的code并成功安装到Qt5.9.9中进行使用,界面拖…...
API的定义理解
前言 在程序员的日常工作中,“API”这个词在程序员的口中重复的次数,绝对是名列前茅的。 但是对刚开始工作的新人来说,API这个概念还是比较模糊。 确实,API这个概念是随着语义环境而不一样的,所以会让人迷惑。 下面…...
启航IT之旅:高考假期预习指南
标题:启航IT之旅:高考假期预习指南 随着高考的落幕,许多有志于IT领域的学子们即将踏上新的学习旅程。这个假期,是他们探索IT世界的黄金时期。本文将为准IT新生们提供一份全面的预习指南,帮助他们为未来的学习和职业生…...
HarmonyOS开发:循环渲染ForEach
需求: 创建多个列表组件,并实现点赞功能 语言: ArkTS 平台: DevEco Studio ForEach 接口描述 ForEach( arr: Array, itemGenerator: (item: Object, index: number) > void, keyGenerator?: (item: Object, index: number) &…...
构建工程化:多种不同的工程体系如何编写MakeFile
源码分析 核心MakeFile 这个 Makefile 是一个复杂的构建脚本,用于管理和构建一个大型项目。它包括多个目标、条件判断和递归调用 make 命令来处理多个子项目和子目录。让我们逐部分进行详细解析。 伪目标和变量定义 .PHONY: all clean install build test init.…...
聚焦从业人员疏散逃生避险意识能力提升,推动生产经营单位每年至少组织开展(疏散逃生演练,让全体从业人员熟知逃生通道、安全出口及应急处置要求,形成常态化机制。
聚焦从业人员疏散逃生避险意识能力提升,推动生产经营单位每年至少组织开展(疏散逃生演练,让全体从业人员熟知逃生通道、安全出口及应急处置要求,形成常态化机制。完整试题答案查看 A.三次B.两次C.一次 综合运用“四不两直”、明察暗访、 ()、…...

【手机取证】如何使用360加固助手给apk加固
文章关键词:手机取证、电子数据取证、数据恢复 一、前言 APP加固是对APP代码逻辑的一种保护。原理是将应用文件进行某种形式的转换,包括不限于隐藏,混淆,加密等操作,进一步保护软件的利益不受损坏,下面给…...
Vue的介绍
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
MySql数据库常用指令合集
MySql数据库常用指令合集 一、创建数据库db11.创建表 字段---表头 student_no,username,sex2.新增单条插入多条插入3.删除4.更新5.查询5.1.查询该表全部信息5.2.查询该表中username,并且要求名字为zhangsan性别女,还可以用(or) 6.…...
ArcGIS Pro SDK (七)编辑 13 注解
ArcGIS Pro SDK (七)编辑 13 注解 文章目录 ArcGIS Pro SDK (七)编辑 13 注解1 注释构建工具2 以编程方式启动编辑批注3 更新批注文本4 修改批注形状5 修改批注文本图形6 接地到网格 环境:Visual Studio 2022 .NET6 …...
模拟面试001-Java开发工程师+简历+问题+回答
模拟面试001-Java开发工程师简历问题回答 目录 模拟面试001-Java开发工程师简历问题回答面试简历面试官题问求职者回答1. 关于Java编程和技术栈2. 关于XX在线购物平台项目3. 关于XX企业资源规划系统项目4. 团队协作与项目管理5. 个人发展与职业规划 参考资料 面试简历 **个人信…...

微信小程序 ——入门介绍及简单的小程序编写
目录 一、小程序入门 1.1 什么是小程序 1.2 小程序的优点 1.3 小程序注册 1.4 安装开发工具 1.5 创建第一个小程序 二、小程序目录结构及入门案例 2.1 目录结构 2.2 入门案例 2.2.1 创建界面 2.2.2 设置标题 2.2.3 编写WXML文件 2.2.4 编写JS文件 2.2.5 编写WXSS…...
ubuntu20.04安装lio-sam
1、依赖功能包安装 sudo apt install ros-noetic-robot-state-publisher sudo apt-get install ros-noetic-robot-localization libmetis-dev 2、boost版本 boost版本查看:cat /usr/include/boost/version.hpp | grep "BOOST_LIB_VERSION" boost版本为1.…...

Kafka系列之Kafka知识超强总结
一、Kafka简介 Kafka是什么 Kafka是一种高吞吐量的分布式发布订阅消息系统(消息引擎系统),它可以处理消费者在网站中的所有动作流数据。 这种动作(网页浏览, 搜索和其他用户的行动)是在现代网络上的许多社…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...