项目搭建(序)
准备pojo
数据库5张表,对应5个实体类,再加一个登陆提交的实体类,一共6个。
注意:
1.实体类属性驼峰命名
2.java类型-数据库类型:char-char,String-varchar,Integer-int
package com.atguigu.myzhxy.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_admin")
public class Admin {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String name;
private char gender;
private String password;
private String email;
private String telephone;
private String address;
private String portraitPath;// 头像的图片路径
}
package com.atguigu.myzhxy.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @project: sms
* @description: 班级信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_clazz")
public class Clazz {
//班级信息
@TableId(value = "id",type = IdType.AUTO)
private Integer id; //班级Id
private String name; //班级名称
private String number; //班级人数
private String introducation; //班级介绍
//班主任信息
private String headmaster; //班主任姓名
private String telephone; //班主任电话
private String email; //班主任邮箱
//所属年级
private String gradeName; //班级所属年级
}
package com.atguigu.myzhxy.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @project: sms
* @description: 年级及年级主任信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_grade")
public class Grade {
//年级信息
@TableId(value = "id",type = IdType.AUTO)
private Integer id; //年级ID
private String name; //年级名称
private String introducation; //年级介绍
//年级主任信息
private String manager; //年级主任姓名
private String email; //年级主任邮箱
private String telephone; //年级主任电话
}
package com.atguigu.myzhxy.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @project: sms
* @description: 学生信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_student")
public class Student {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String sno;
private String name;
private char gender = '男';//default
private String password;
private String email;
private String telephone;
private String address;
private String introducation;
private String portraitPath;//存储头像的项目路径
private String clazzName;//班级名称
}
package com.atguigu.myzhxy.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @project: sms
* @description: 教师信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_teacher")
public class Teacher {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String tno;
private String name;
private char gender;
private String password;
private String email;
private String telephone;
private String address;
private String clazzName;
private String portraitPath;//存储头像的项目路径
// @TableLogic
// private Integer isDeleted;
}
package com.atguigu.myzhxy.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @project: ssm_sms
* @description: 用户登录表单信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginForm {
private String username;
private String password;
private String verifiCode;
private Integer userType;
}
准备mapper
5个表格,5个mapper。
package com.atguigu.myzhxy.mapper;
import com.atguigu.myzhxy.pojo.Admin;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface AdminMapper extends BaseMapper<Admin> {
}
package com.atguigu.myzhxy.mapper;
import com.atguigu.myzhxy.pojo.Clazz;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface ClazzMapper extends BaseMapper<Clazz> {
}
package com.atguigu.myzhxy.mapper;
import com.atguigu.myzhxy.pojo.Grade;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface GradeMapper extends BaseMapper<Grade> {
}
package com.atguigu.myzhxy.mapper;
import com.atguigu.myzhxy.pojo.Student;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentMapper extends BaseMapper<Student> {
}
package com.atguigu.myzhxy.mapper;
import com.atguigu.myzhxy.pojo.Teacher;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface TeacherMapper extends BaseMapper<Teacher> {
}
准备service
接口
package com.atguigu.myzhxy.service;
import com.atguigu.myzhxy.pojo.Admin;
import com.baomidou.mybatisplus.extension.service.IService;
public interface AdminService extends IService<Admin> {
}
package com.atguigu.myzhxy.service;
import com.atguigu.myzhxy.pojo.Clazz;
import com.baomidou.mybatisplus.extension.service.IService;
public interface ClazzService extends IService<Clazz> {
}
package com.atguigu.myzhxy.service;
import com.atguigu.myzhxy.pojo.Grade;
import com.baomidou.mybatisplus.extension.service.IService;
public interface GradeService extends IService<Grade> {
}
package com.atguigu.myzhxy.service;
import com.atguigu.myzhxy.pojo.Student;
import com.baomidou.mybatisplus.extension.service.IService;
public interface StudentService extends IService<Student> {
}
package com.atguigu.myzhxy.service;
import com.atguigu.myzhxy.pojo.Teacher;
import com.baomidou.mybatisplus.extension.service.IService;
public interface TeacherService extends IService<Teacher> {
}
实现类
因为接口继承了IService,所以实现类实现XxxxService 时会报错,说有很多IService的方法没实现,这时候就要继承一个ServiceImpl。
package com.atguigu.myzhxy.service.impl;
import com.atguigu.myzhxy.mapper.AdminMapper;
import com.atguigu.myzhxy.pojo.Admin;
import com.atguigu.myzhxy.service.AdminService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("adminServiceImpl")
@Transactional
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {
}
package com.atguigu.myzhxy.service.impl;
import com.atguigu.myzhxy.mapper.ClazzMapper;
import com.atguigu.myzhxy.pojo.Clazz;
import com.atguigu.myzhxy.service.ClazzService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class ClazzServiceImpl extends ServiceImpl<ClazzMapper, Clazz> implements ClazzService {
}
package com.atguigu.myzhxy.service.impl;
import com.atguigu.myzhxy.mapper.GradeMapper;
import com.atguigu.myzhxy.pojo.Grade;
import com.atguigu.myzhxy.service.GradeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class GradeServiceImpl extends ServiceImpl<GradeMapper, Grade> implements GradeService {
}
package com.atguigu.myzhxy.service.impl;
import com.atguigu.myzhxy.mapper.StudentMapper;
import com.atguigu.myzhxy.pojo.Student;
import com.atguigu.myzhxy.service.StudentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("stuService")
@Transactional
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
}
package com.atguigu.myzhxy.service.impl;
import com.atguigu.myzhxy.mapper.TeacherMapper;
import com.atguigu.myzhxy.pojo.Teacher;
import com.atguigu.myzhxy.service.TeacherService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("teaService")
@Transactional
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {
}
准备controller
业务的开发需要前端给url,这里前端我们直接打包好了丢到了static里面,改不了了,所以url不要问为什么这么写,是这个项目规定的哈哈。
5个表格对应的5个controller,加一个杂项的SystemController
package com.atguigu.myzhxy.controller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
@Api(tags = "管理员控制器")
@RestController
@RequestMapping("/sms/adminController")
public class AdminController {
}
package com.atguigu.myzhxy.controller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
@Api(tags = "班级管理器")
@RestController
@RequestMapping("/sms/clazzController")
public class ClazzController {
}
package com.atguigu.myzhxy.controller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
@Api(tags = "年级控制器")
@RestController
@RequestMapping("/sms/gradeController")
public class GradeController {
}
package com.atguigu.myzhxy.controller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
@Api(tags = "学生控制器")
@RestController
@RequestMapping("/sms/studentController")
public class StudentController {
}
package com.atguigu.myzhxy.controller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
@Api(tags = "教师控制器")
@RestController
@RequestMapping("/sms/teacherController")
public class TeacherController {
}
package com.atguigu.myzhxy.controller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
@Api(tags = "系统控制器")
@RestController
@RequestMapping("/sms/system")
public class SystemController {
}
业务开发
业务的开发需要前端给url,这里前端我们直接打包好了丢到了static里面,改不了了,所以url不要问为什么这么写,是这个项目规定的哈哈。
获得验证码
浏览器开发者工具看到请求路径:
放到SystemController里:
@GetMapping("/getVerifiCodeImage")
public void getVerifiCodeImage(HttpServletRequest request, HttpServletResponse response) {
//获取验证码图片
BufferedImage verifiCodeImage = CreateVerifiCodeImage.getVerifiCodeImage();
//获取图片上的验证码文本
String verifiCode =new String(CreateVerifiCodeImage.getVerifiCode()) ;
//将验证码文本放入session域,为验证做准备
HttpSession session = request.getSession();
session.setAttribute("verifiCode",verifiCode);
//将验证码图片响应给浏览器
try {
ImageIO.write(verifiCodeImage,"jpg",response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
登录校验
systemController:
@PostMapping("/login")
public Result login(@RequestBody LoginForm loginForm, HttpServletRequest request) {
//验证码校验
HttpSession session = request.getSession();
String sessionVerifiCode = (String) session.getAttribute("verifiCode");
String loginVerifiCode = loginForm.getVerifiCode();
if ("".equals(sessionVerifiCode) || null == sessionVerifiCode) {
return Result.fail().message("验证码失效,请刷新后重试!");
}
if (!sessionVerifiCode.equals(loginVerifiCode)) {
return Result.fail().message("验证码有误,请重新填写验证码!");
}
//验证码校验完后移除
session.removeAttribute("verifiCode");
//存放data的对象
Map<String, Object> map = new LinkedHashMap<>();
//分用户类型校验登录信息
switch (loginForm.getUserType()) {
case 1:
//调用service层查找符合的对象
Admin admin = adminService.login(loginForm);
if (null != admin) {
//生成token,按照格式返回前台
String token = JwtHelper.createToken(admin.getId().longValue(), 1);
map.put("token", token);
return Result.ok(map);
} else {
return Result.fail().message("用户名密码有误");
}
case 2:
//调用service层查找符合的对象
Student student = studentService.login(loginForm);
if (null != student) {
//生成token,按照格式返回前台
String token = JwtHelper.createToken(student.getId().longValue(), 2);
map.put("token", token);
return Result.ok(map);
} else {
return Result.fail().message("用户名密码有误");
}
case 3:
//调用service层查找符合的对象
Teacher teacher = teacherService.login(loginForm);
if (null != teacher) {
//生成token,按照格式返回前台
String token = JwtHelper.createToken(teacher.getId().longValue(), 3);
map.put("token", token);
return Result.ok(map);
} else {
return Result.fail().message("用户名密码有误");
}
default:
return Result.fail().message("无此类型用户!");
}
}
@GetMapping("/getInfo")
public Result getInfo(@RequestHeader("token") String token) {
//判断token是否过期
boolean expiration = JwtHelper.isExpiration(token);
if (expiration) {
return Result.build(null, ResultCodeEnum.TOKEN_ERROR);
}
//解析出用户id和type
Long userId = JwtHelper.getUserId(token);
Integer type = JwtHelper.getUserType(token);
//准备一个临时存储对象的map集合
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
//根据userId和type查询具体信息
switch (type) {
case 1:
Admin admin = adminService.getById(userId);
map.put("userTpye",1);
map.put("user",admin);
break;
case 2:
Student student = studentService.getById(userId);
map.put("userTpye",2);
map.put("user",student);
break;
case 3:
Teacher teacher = teacherService.getById(userId);
map.put("userTpye",3);
map.put("user",teacher);
break;
}
return Result.ok(map).message("成功");
}
AdminService:
Admin login(LoginForm loginForm);
AdminServiceImpl:
@Override
public Admin login(LoginForm loginForm) {
QueryWrapper<Admin> wrapper = new QueryWrapper<>();
wrapper.eq("name",loginForm.getUsername());
wrapper.eq("password", MD5.encrypt(loginForm.getPassword()));
Admin admin = adminMapper.selectOne(wrapper);
return admin;
}
同理,StudentService和TeacherService接口和相应的实现类按照admin的来写。
还有登录用户头像图片的问题,要从static-images里面复制到:
但程序不是从这里直接读的,要编译到target里面才生效:
所以要用maven:clean-compile。
年级管理
查询年级信息:条件+分页
请求url:
1代表第一页,3代表每页3条记录,还带了个路径参数。
需要的响应结果:
这个响应结果的data就是mybatisplus的Page类。
GradeController:
@GetMapping("/getGrades/{pageNo}/{pageSize}")
public Result getGrades(
@PathVariable("pageNo") Integer pageNo,
@PathVariable("pageSize") Integer pageSize,
@RequestParam("gradeName") String gradeName
) {
//分页+条件查询
Page<Grade> page = new Page<>(pageNo, pageSize);
IPage<Grade> pageRs = gradeService.getGradeByOpr(page, gradeName);
//封装Result对象,返回
return Result.ok(pageRs);
}
GradeService:
IPage<Grade> getGradeByOpr(Page<Grade> page, String gradeName);
GradeServiceImpl:
@Override
public IPage<Grade> getGradeByOpr(Page<Grade> page, String gradeName) {
QueryWrapper<Grade> wrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(gradeName)) {
wrapper.like("name", gradeName);
}
//根据id降序排列
wrapper.orderByDesc("id");
Page<Grade> gradePage = gradeMapper.selectPage(page, wrapper);
return gradePage;
}
添加与修改
请求格式:
请求参数:
json格式,@RequestBody来接收
就是一个Grade对象。
响应:
GradeController:
@PostMapping("/saveOrUpdateGrade")
public Result saveOrUpdateGrade(@RequestBody Grade grade){
//调用服务层方法进行增加或修改
//saveOrUpdate方法是IService接口自带,可以不用实现了
gradeService.saveOrUpdate(grade);
return Result.ok();
}
删除:单个+批量
请求路径:
请求参数:
数组类型
@GetMapping("/deleteGrade")
public Result deleteGrade(@RequestBody List<Integer> ids){
//IService自带批量删除方法
gradeService.removeByIds(ids);
return Result.ok();
}
swagger2的注解使用
打开http://localhost:9001/swagger-ui.html
可以看到有两个参数:用户ID和临时用户ID是啥?
是因为在swagger2的配置文件里有这个:
注释掉就可以。
学生管理
头像上传
请求路径:
请求参数:
响应:
SystemController:
@PostMapping("/headerImgUpload")
public Result headerImageUpload(@RequestPart("multipartFile") MultipartFile multipartFile) {
//生成新名操作
//新名前缀
String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();
//获取旧名
String originalFilename = multipartFile.getOriginalFilename();
//找到.的位置
int i = originalFilename.lastIndexOf(".");
//从.的位置开始截取,作为后缀
String suffix = originalFilename.substring(i);
//拼接uuid和旧名后缀作为新名
String newFileName=uuid+suffix;
//保存文件操作:理论上这里应该是将文件发送到第三方/独立的文件服务器上存储,但这里简单一点,直接存到target/classes/public/upload下面
String portraitPath = "F:/project/learn/myzhxy/target/classes/public/upload/" + newFileName;
try {
//文件传输到指定位置
multipartFile.transferTo(new File(portraitPath));
} catch (IOException e) {
e.printStackTrace();
}
//响应文件路径
String path = "upload/" + newFileName;
return Result.ok(path);
}