实现学生管理
新增学生
接口设计
请求路径:/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 {
//学生id
private 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 {
@Autowired
private StudentService studentService;
@Autowired
private 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 {
@Autowired
private 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
*/
@Override
public 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 设置创建人的id
student.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
*/
@ExceptionHandler
public Result exceptionHandler(BaseException ex){
log.error("异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}
/**
* 捕获用户名重复
* */
@ExceptionHandler
public 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令牌添加到全局参数中
检查一下添加上了没
然后开始测试
检查数据库添加上了没
学生分页查询
接口设计
请求路劲:/admin/student/page
请求方式:GET
请求参数:请求参数类型为Query,和前面的不一样,这是直接在网络地址上连接的
name 员工姓名;page 页码;pageSize 每页记录数
返回参数:
代码开发
DTO类设计
接收前端传来的数据
sems-pojo/src/main/java/com/ljc/dto/StudentPageQueryDTO.java
package com.ljc.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class StudentPageQueryDTO implements Serializable {
//学生姓名
private String name;
//页码
private int page;
//每页显示记录数
private int pageSize;
}
封装分页查询(特定返回给前端的实体类,后面所有分页查询都用得到)
分页查询后端返回的对象类型为: Result<PageResult>
sems-common/src/main/java/com/ljc/result/PageResult.java
package com.ljc.result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* 封装分页查询结果
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
private long total; //总记录数
private List records; //当前页数据集合
}
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.dto.StudentPageQueryDTO;
import com.ljc.entity.Student;
import com.ljc.properties.JwtProperties;
import com.ljc.result.PageResult;
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.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/admin/student")
@Slf4j
public class StudentController {
@Autowired
private StudentService studentService;
@Autowired
private 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();
}
/**
* 学生分页查询
* @param studentPageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("学生分页查询")
public Result<PageResult> page(/*因为前端参数类型是Query,所以不需要注解*/StudentPageQueryDTO studentPageQueryDTO){
log.info("学生分页查询:{}",studentPageQueryDTO);
PageResult pageResult = studentService.page(studentPageQueryDTO);
return Result.success(pageResult);
}
}
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.dto.StudentPageQueryDTO;
import com.ljc.entity.Student;
import com.ljc.result.PageResult;
public interface StudentService {
/**
* 学生登录
* @param studentLoginDTO
* @return
*/
Student login(StudentLoginDTO studentLoginDTO);
/**
* 新增学生
* @param studentDTO
*/
void save(StudentDTO studentDTO);
/**
* 学生分页查询
* @param studentPageQueryDTO
* @return
*/
PageResult page(StudentPageQueryDTO studentPageQueryDTO);
}
ServiceImpl层
sems-server/src/main/java/com/ljc/service/impl/StudentServiceImpl.java
package com.ljc.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
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.dto.StudentPageQueryDTO;
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.result.PageResult;
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;
import java.util.List;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private 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
*/
@Override
public 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 设置创建人的id
student.setCreateUser(BaseContext.getCurrentId());
student.setUpdateUser(BaseContext.getCurrentId());
//4 调用mapper层数据,连接数据库,对数据库进行操作
studentMapper.insert(student);
}
/**
* 学生分页查询
* @param studentPageQueryDTO
* @return
*/
@Override
public PageResult page(StudentPageQueryDTO studentPageQueryDTO) {
//1. 设置分页参数
//第一个参数是分页查询的当前页码,第二个是当前页需要展示的数据大小
PageHelper.startPage(studentPageQueryDTO.getPage(),studentPageQueryDTO.getPageSize());
//2. 执行查询、
Page<Student> page = studentMapper.pageQuery(studentPageQueryDTO);
//3. 使用PageInfo封装分页结果
long total = page.getTotal();
List<Student> records = page.getResult();
//4. 返回封装的PageResult对象
return new PageResult(total,records);
}
}
mapper层
sems-server/src/main/java/com/ljc/mapper/StudentMapper.java
package com.ljc.mapper;
import com.github.pagehelper.Page;
import com.ljc.dto.StudentPageQueryDTO;
import com.ljc.entity.Student;
import com.ljc.result.PageResult;
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);
/**
* 学生分页查询
* @param studentPageQueryDTO
* @return
*/
//查询在xml文件里面动态查询;
Page<Student> pageQuery(StudentPageQueryDTO studentPageQueryDTO);
}
sems-server/src/main/resources/mapper/StudentMapper.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.ljc.mapper.StudentMapper">
<select id="pageQuery" resultType="com.ljc.entity.Student" parameterType="com.ljc.dto.StudentPageQueryDTO">
select * from student
<where>
<if test="name != null and name != ''">
and name like concat('%',#{name},'%')
</if>
</where>
order by create_time desc
</select>
</mapper>
日期统一格式
在WebMvcConfiguration中扩展SpringMVC的消息转换器,统一对日期类型进行格式处理
sems-server/src/main/java/com/ljc/config/WebMvcConfiguration.java
package com.ljc.config;
import com.ljc.interceptor.JwtTokenAdminInterceptor;
import com.ljc.json.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.List;
/**
* 配置类,注册web层相关组件
*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Autowired
private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
/**
* 注册自定义拦截器
*
* @param registry
*/
protected void addInterceptors(InterceptorRegistry registry) {
log.info("开始注册自定义拦截器...");
registry.addInterceptor(jwtTokenAdminInterceptor)
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/student/login");
}
/**
* 通过knife4j生成接口文档
* @return
*/
@Bean
public Docket docket() {
ApiInfo apiInfo = new ApiInfoBuilder()
.title("体育器材项目接口文档")
.version("1.0")
.description("体育器材项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.ljc.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
/**
* 设置静态资源映射
* @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* 扩展Spring MVC框架的消息转化器
* @param converters
*/
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器...");
//创建一个消息转换器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
//需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
converter.setObjectMapper(new JacksonObjectMapper());
//将自己的消息转化器加入容器中
converters.add(0,converter);
}
}
同时定义一个时间格式类(把常见的都写进去)
sems-common/src/main/java/com/ljc/json/JacksonObjectMapper.java
package com.ljc.json;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
//public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
测试
PS:如果token过期了,记得去用户登录里重新获取
启用禁用学生状态
接口设计
请求路径:/admin/student/status/{status}
请求方法:POST
请求参数:Header:application/json
路径参数:status
query:id
返回参数:code;msg;data
代码开发
controller层
sems-server/src/main/java/com/ljc/controller/student/StudentController.java
/**
* 启用禁用学生状态
* @param status
* @param id
* @return
*/
@GetMapping("/status/{status}")
@ApiOperation("启用禁止学生状态")
public Result startOrStopStatus(@PathVariable Integer status,Long id){
log.info("启用禁用学生状态:{},{}",status,id);
studentService.starOrStopStatus(status,id);
return Result.success();
}
service层
sems-server/src/main/java/com/ljc/service/StudentService.java
/**
* 启用禁用学生状态
* @param status
* @param id
*/
void starOrStopStatus(Integer status, Long id);
serviceImpl层
sems-server/src/main/java/com/ljc/service/impl/StudentServiceImpl.java
/**
* 启用禁用学生状态
* @param status
* @param id
*/
@Override
public void starOrStopStatus(Integer status, Long id) {
Student student = Student
.builder()
.id(id)
.status(status)
.build();
studentMapper.updata(student);
}
mapper层
sems-server/src/main/java/com/ljc/mapper/StudentMapper.java
/**
* 启用禁用学生状态
* @param student
*/
void updata(Student student);
sems-server/src/main/resources/mapper/StudentMapper.xml
<update id="updata" parameterType="com.ljc.entity.Student">
update student
<set>
<if test="name != null">name = #{name},</if>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="sex != null">sex = #{sex},</if>
<if test="idNumber != null">id_Number = #{idNumber},</if>
<if test="updateTime != null">update_Time = #{updateTime},</if>
<if test="updateUser != null">update_User = #{updateUser},</if>
<if test="status != null">status = #{status},</if>
</set>
where id = #{id}
</update>
测试
编辑学生信息
接口设计
根据id查询学生
请求路径:/admin/student/{id}
请求方法:GET
请求参数:id
返回数据:code;msg;data(student类)
编辑学生信息
请求路径:/admin/student
请求方法:PUT
请求参数:Headers:application/json
Body:id,idNumber,name,phone,sex,username
返回数据:code;msg;data
代码开发
根据id查询学生
controller层
sems-server/src/main/java/com/ljc/controller/student/StudentController.java
/**
* 根据id查询学生信息
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询学生信息")
public Result<Student> getById(@PathVariable Long id){
log.info("根据id查询学生信息:{}",id);
Student student = studentService.getById(id);
return Result.success(student);
}
service层
sems-server/src/main/java/com/ljc/service/StudentService.java
/**
* 根据id查询学生信息
* @param id
* @return
*/
Student getById(Long id);
ServiceImpl层
sems-server/src/main/java/com/ljc/service/impl/StudentServiceImpl.java
/**
* 根据id查询学生信息
* @param id
* @return
*/
@Override
public Student getById(Long id) {
//根据mapper层查询数据
Student student = studentMapper.getById(id);
//将查询回来的密码进行保护
student.setPassword("*****");
return student;
}
mapper层
sems-server/src/main/java/com/ljc/mapper/StudentMapper.java
/**
* 根据id查询学生信息
* @param id
* @return
*/
@Select("select * from student where id = #{id}")
Student getById(Long id);
测试
编辑学生信息
controller层
sems-server/src/main/java/com/ljc/controller/student/StudentController.java
/**
* 编辑学生信息
* @param studentDTO
* @return
*/
@PutMapping
@ApiOperation("编辑学生信息")
public Result update(@RequestBody StudentDTO studentDTO){
log.info("编辑学生信息:{}", studentDTO);
studentService.update(studentDTO);
return Result.success();
}
service层
sems-server/src/main/java/com/ljc/service/StudentService.java
/**
* 编辑学生信息
* @param studentDTO
*/
void update(StudentDTO studentDTO);
ServiceImpl层
sems-server/src/main/java/com/ljc/service/impl/StudentServiceImpl.java
/**
* 编辑学生信息
* @param studentDTO
*/
@Override
public void update(StudentDTO studentDTO) {
Student student = new Student();
BeanUtils.copyProperties(studentDTO,student);
//补充前端没有传回来的数据
student.setUpdateTime(LocalDateTime.now());
student.setUpdateUser(BaseContext.getCurrentId());
studentMapper.updata(student);//之前启用禁用学生状态板块以及实现;
}
测试
目前为止整体代码
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.dto.StudentPageQueryDTO;
import com.ljc.entity.Student;
import com.ljc.properties.JwtProperties;
import com.ljc.result.PageResult;
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.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/admin/student")
@Slf4j
public class StudentController {
@Autowired
private StudentService studentService;
@Autowired
private 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();
}
/**
* 学生分页查询
* @param studentPageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("学生分页查询")
public Result<PageResult> page(/*因为前端参数类型是Query,所以不需要注解*/StudentPageQueryDTO studentPageQueryDTO){
log.info("学生分页查询:{}",studentPageQueryDTO);
PageResult pageResult = studentService.page(studentPageQueryDTO);
return Result.success(pageResult);
}
/**
* 启用禁用学生状态
* @param status
* @param id
* @return
*/
@GetMapping("/status/{status}")
@ApiOperation("启用禁止学生状态")
public Result startOrStopStatus(@PathVariable Integer status,Long id){
log.info("启用禁用学生状态:{},{}",status,id);
studentService.starOrStopStatus(status,id);
return Result.success();
}
/**
* 根据id查询学生信息
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询学生信息")
public Result<Student> getById(@PathVariable Long id){
log.info("根据id查询学生信息:{}",id);
Student student = studentService.getById(id);
return Result.success(student);
}
/**
* 编辑学生信息
* @param studentDTO
* @return
*/
@PutMapping
@ApiOperation("编辑学生信息")
public Result update(@RequestBody StudentDTO studentDTO){
log.info("编辑学生信息:{}", studentDTO);
studentService.update(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.dto.StudentPageQueryDTO;
import com.ljc.entity.Student;
import com.ljc.result.PageResult;
public interface StudentService {
/**
* 学生登录
* @param studentLoginDTO
* @return
*/
Student login(StudentLoginDTO studentLoginDTO);
/**
* 新增学生
* @param studentDTO
*/
void save(StudentDTO studentDTO);
/**
* 学生分页查询
* @param studentPageQueryDTO
* @return
*/
PageResult page(StudentPageQueryDTO studentPageQueryDTO);
/**
* 启用禁用学生状态
* @param status
* @param id
*/
void starOrStopStatus(Integer status, Long id);
/**
* 根据id查询学生信息
* @param id
* @return
*/
Student getById(Long id);
/**
* 编辑学生信息
* @param studentDTO
*/
void update(StudentDTO studentDTO);
}
serviceImpl层
sems-server/src/main/java/com/ljc/service/impl/StudentServiceImpl.java
package com.ljc.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
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.dto.StudentPageQueryDTO;
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.result.PageResult;
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;
import java.util.List;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private 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
*/
@Override
public 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 设置创建人的id
student.setCreateUser(BaseContext.getCurrentId());
student.setUpdateUser(BaseContext.getCurrentId());
//4 调用mapper层数据,连接数据库,对数据库进行操作
studentMapper.insert(student);
}
/**
* 学生分页查询
* @param studentPageQueryDTO
* @return
*/
@Override
public PageResult page(StudentPageQueryDTO studentPageQueryDTO) {
//1. 设置分页参数
//第一个参数是分页查询的当前页码,第二个是当前页需要展示的数据大小
PageHelper.startPage(studentPageQueryDTO.getPage(),studentPageQueryDTO.getPageSize());
//2. 执行查询、
Page<Student> page = studentMapper.pageQuery(studentPageQueryDTO);
//3. 使用PageInfo封装分页结果
long total = page.getTotal();
List<Student> records = page.getResult();
//4. 返回封装的PageResult对象
return new PageResult(total,records);
}
/**
* 启用禁用学生状态
* @param status
* @param id
*/
@Override
public void starOrStopStatus(Integer status, Long id) {
Student student = Student
.builder()
.id(id)
.status(status)
.build();
studentMapper.updata(student);
}
/**
* 根据id查询学生信息
* @param id
* @return
*/
@Override
public Student getById(Long id) {
//根据mapper层查询数据
Student student = studentMapper.getById(id);
//将查询回来的密码进行保护
student.setPassword("*****");
return student;
}
/**
* 编辑学生信息
* @param studentDTO
*/
@Override
public void update(StudentDTO studentDTO) {
Student student = new Student();
BeanUtils.copyProperties(studentDTO,student);
//补充前端没有传回来的数据
student.setUpdateTime(LocalDateTime.now());
student.setUpdateUser(BaseContext.getCurrentId());
studentMapper.updata(student);//之前启用禁用学生状态板块以及实现;
}
}
mapper层
sems-server/src/main/java/com/ljc/mapper/StudentMapper.java
package com.ljc.mapper;
import com.github.pagehelper.Page;
import com.ljc.dto.StudentPageQueryDTO;
import com.ljc.entity.Student;
import com.ljc.result.PageResult;
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);
/**
* 学生分页查询
* @param studentPageQueryDTO
* @return
*/
//查询在xml文件里面动态查询;
Page<Student> pageQuery(StudentPageQueryDTO studentPageQueryDTO);
/**
* 启用禁用学生状态
* @param student
*/
void updata(Student student);
/**
* 根据id查询学生信息
* @param id
* @return
*/
@Select("select * from student where id = #{id}")
Student getById(Long id);
}
sems-server/src/main/resources/mapper/StudentMapper.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.ljc.mapper.StudentMapper">
<update id="updata" parameterType="com.ljc.entity.Student">
update student
<set>
<if test="name != null">name = #{name},</if>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="sex != null">sex = #{sex},</if>
<if test="idNumber != null">id_Number = #{idNumber},</if>
<if test="updateTime != null">update_Time = #{updateTime},</if>
<if test="updateUser != null">update_User = #{updateUser},</if>
<if test="status != null">status = #{status},</if>
</set>
where id = #{id}
</update>
<select id="pageQuery" resultType="com.ljc.entity.Student" parameterType="com.ljc.dto.StudentPageQueryDTO">
select * from student
<where>
<if test="name != null and name != ''">
and name like concat('%',#{name},'%')
</if>
</where>
order by create_time desc
</select>
</mapper>
学生管理版本基本搞定,现在去完成前端相关的板块