pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>dgut-campus-recruiting-helper</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>student-module</artifactId><dependencies><!--        common--><dependency><groupId>org.example</groupId><artifactId>public-commons</artifactId><version>1.0-SNAPSHOT</version></dependency><!--        springboot-web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--nacos客户端--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--fegin组件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- Feign Client for loadBalancing --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-loadbalancer</artifactId></dependency><!--        注解--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version><scope>provided</scope></dependency><!--        容错组件sentinel--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!--        单元测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--        mybatis-plus依赖--><!--        <dependency>--><!--            <groupId>com.baomidou</groupId>--><!--            <artifactId>mybatis-plus-boot-starter</artifactId>--><!--            <version>3.4.2</version>--><!--        </dependency>--><!--        com.mysql.cj.jdbc.Driver 驱动--><!--        <dependency>--><!--            <groupId>mysql</groupId>--><!--            <artifactId>mysql-connector-java</artifactId>--><!--            <version>8.0.19</version>--><!--        </dependency>--><!--      knife4j接口文档  --><!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-micro-spring-boot-starter --><!--        <dependency>--><!--            <groupId>com.github.xiaoymin</groupId>--><!--            <artifactId>knife4j-micro-spring-boot-starter</artifactId>--><!--            <version>3.0.2</version>--><!--        </dependency>--><dependency><groupId>com.alibaba.cloud</groupId><!-- 里面已经集成服务间调用X-id的传递,包括FeignClient的重写,如果在之前自定义封装过Feign,注意启动冲突--><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><!--去除低版本--><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><!-- 添加 seata starter ,与服务端保持一致--><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.4.1</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.6.2</version></dependency></dependencies><!--    打包--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><!-- 指定该Main Class为全局的唯一入口 --><mainClass>com.student.module.StudentApplication</mainClass><layout>ZIP</layout></configuration><executions><execution><goals><goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中--></goals></execution></executions></plugin></plugins></build>
</project>

controller

package com.student.module.controller;import com.commons.annotation.VerifyEmailCode;
import com.commons.constant.ReqParameterConstant;
import com.commons.exception.CustomerException;
import com.student.module.service.StudentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;@RestController
@Api(tags = "学生端接口")
@RequestMapping("/student")
public class StudentController {@Resource(name = "studentService")private StudentService studentService;/*** 测试接口** @param request* @return*/@ApiOperation(value = "user hello接口", notes = "测试token解析用户名")@GetMapping("/hello")public String hello(HttpServletRequest request) {return studentService.hello(request);}/*** 测试接口** @param msg* @return*/@ApiOperation(value = "测试接口", notes = "studentMapper与iStudentService的测试")@ApiImplicitParams({@ApiImplicitParam(value = "信息", name = "msg", required = true, paramType = "path")})@GetMapping("/test/{msg}")public Map<String, Object> test(@PathVariable("msg") String msg) {return studentService.test(msg);}/*** 学生账号注册接口* 该接口应为公开接口** @param parameters* @return* @throws CustomerException*/@ApiOperation(value = "学生注册",notes = "携带验证码把学生注册的信息传递给该接口,先核对邮箱地址与验证码是否正确,若正确则执行注册逻辑,若错误则返回错误信息")@VerifyEmailCode(type = ReqParameterConstant.FORM)@ApiImplicitParams({@ApiImplicitParam(value = "邮箱", name = "email", required = true, paramType = "query"),@ApiImplicitParam(value = "验证码", name = "code", required = true, paramType = "query"),@ApiImplicitParam(value = "密码", name = "password", required = true, paramType = "query")})@PostMapping("/register")public Map<String, Object> register(@RequestParam Map<String, String> parameters) throws CustomerException {return studentService.register(parameters);}/*** 修改密码接口* 需要旧密码 oldPwd 验证,旧密码通过则更新新密码 newPwd 到数据库* 撤销 redis 缓存该用户的所有有效 token** @param request* @param oldPwd* @param newPwd* @return*/@ApiOperation(value = "更新学生账号密码",notes = "需要在旧密码的校验,新密码二次校验需在前端完成")@GetMapping("/changePassword")public Map<String, Object> changePassword(HttpServletRequest request, @RequestParam("oldPwd") String oldPwd, @RequestParam("newPwd") String newPwd) throws CustomerException {return studentService.changePassword(request, oldPwd, newPwd);}/*** 学生信息更新接口** @param request* @param parameters* @return* @throws CustomerException*/@ApiOperation(value = "学生信息更新",notes = "携带验证码把学生更新的信息传递给该接口,先核对邮箱地址与验证码是否正确,若正确则执行更新逻辑,若错误则返回错误信息")@ApiImplicitParams({@ApiImplicitParam(value = "学生参数组", name = "Map<key,value>", required = true, paramType = "query"),@ApiImplicitParam(value = "验证码", name = "code", required = true, paramType = "query"),})@VerifyEmailCode(type = ReqParameterConstant.FORM)@GetMapping("/updateInfo")public Map<String, Object> updateInfo(HttpServletRequest request, @RequestParam Map<String, String> parameters) throws CustomerException {return studentService.updateInfo(request, parameters);}/*** 学生用户获取自身信息** @param request* @return*/@ApiOperation(value = "学生信息获取",notes = "返回某个学生的信息")@GetMapping("/getInfo")public Map<String, Object> getInfo(HttpServletRequest request) {return studentService.getInfo(request);}}

Service & ServiceImpl

package com.student.module.service;import com.commons.exception.CustomerException;
import org.springframework.web.bind.annotation.RequestParam;import javax.servlet.http.HttpServletRequest;
import java.util.Map;public interface StudentService {String hello(HttpServletRequest request);Map<String, Object> test(String msg);Map<String, Object> register(Map<String, String> parameters) throws CustomerException;Map<String, Object> changePassword(HttpServletRequest request, String oldPwd, String newPwd) throws CustomerException;Map<String, Object> updateInfo(HttpServletRequest request, Map<String, String> parameters) throws CustomerException;Map<String, Object> getInfo(HttpServletRequest request);
}package com.student.module.service.impl;import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.commons.constant.MySQLMessageConstant;
import com.commons.constant.ResultMsgConstant;
import com.commons.enums.RolesEnum;
import com.commons.exception.CustomerException;
import com.commons.student.entity.Student;
import com.commons.student.mapper.StudentMapper;
import com.commons.student.service.IStudentService;
import com.commons.util.EmailCodeUtil;
import com.student.module.constant.RedisConstant;
import com.student.module.service.StudentService;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Service("studentService")
public class StudentServiceImpl implements StudentService {private final Logger log = LogManager.getLogger(StudentServiceImpl.class.getName());@Resource(name = "messageSource")private MessageSource messageSource;@Resourceprivate RedisTemplate<String, Object> redisTemplate;@Resource(name = "passwordEncoder")private PasswordEncoder passwordEncoder;@Autowiredprivate StudentMapper studentMapper;@Autowiredprivate IStudentService iStudentService;@Overridepublic String hello(HttpServletRequest request) {return "hello," + request.getHeader("username");}@Overridepublic Map<String, Object> test(String msg) {// 返回信息Map<String, Object> result = new HashMap<>();Student testStudent = new Student();testStudent.setOpenid("23");testStudent.setNickname("yushanma");testStudent.setPassword("123456");testStudent.setSno("123");testStudent.setUsername("mvp.sam");iStudentService.save(testStudent);// 构造查询实体Student queryUser = new Student();queryUser.setUsername("mvp.sam");QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>(queryUser);//执行查询Student student = studentMapper.selectOne(studentQueryWrapper);if (student == null) {log.info("student obj is null");} else {log.info("student obj => {}", student);}List<Student> studentList = studentMapper.selectList(null);studentList.forEach(System.out::println);studentList.forEach(System.out::println);String str = JSON.toJSONString(studentList);// 指定删除Map<String, Object> columnMap = new HashMap<>();columnMap.put("username", "mvp.sam");if (iStudentService.removeByMap(columnMap)) {log.info("remove success");} else {log.info("remove fail");}// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.SUCCESS_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.SUCCESS_MSG);// 信息result.put(ResultMsgConstant.RESULT_DATA, str);// 数据return result;}@Override@GlobalTransactionalpublic Map<String, Object> register(Map<String, String> parameters) throws CustomerException {// 返回信息Map<String, Object> result = new HashMap<>();// 获取 邮箱 验证码String email = parameters.get("username");String code = parameters.get(ResultMsgConstant.RESULT_CODE);// 验证逻辑if (EmailCodeUtil.checkCode(email, code)) {// 检查是否已经注册,不允许重复注册Student queryStudent = new Student();queryStudent.setUsername(email);QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>(queryStudent);Student studentResult = studentMapper.selectOne(studentQueryWrapper);// 用户未注册if (studentResult == null) {// 构建注册对象,加密字段已交付 mybatis plus 完成,默认的雪花算法生成 idStudent student = new Student();student = JSON.parseObject(JSON.toJSONString(parameters), Student.class);// 注册时间自动填充// 密码加密student.setPassword(passwordEncoder.encode(student.getPassword()));// 角色student.setRoles(RolesEnum.STUDENT.getRole());// 写入数据库并检验结果if (studentMapper.insert(student) == MySQLMessageConstant.OPERATE_FAIL) {log.error(messageSource.getMessage(MySQLMessageConstant.INSERT_FAIL, null, LocaleContextHolder.getLocale()));throw new CustomerException(messageSource.getMessage(MySQLMessageConstant.INSERT_FAIL, null, LocaleContextHolder.getLocale()));}// 销毁验证码,就算不手动销毁也会在5分钟后自动销毁,手动销毁是因为不允许一个验证码反复使用EmailCodeUtil.destroyCode(email, code);// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.SUCCESS_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.SUCCESS_MSG);// 信息} else {// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.FAIL_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.USER_EXISTS_MSG);// 信息}} else {// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.FAIL_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.CODE_ERROR_MSG);// 信息}return result;}@Override@GlobalTransactionalpublic Map<String, Object> changePassword(HttpServletRequest request, String oldPwd, String newPwd) throws CustomerException {// 从 header 获取 usernameString username = request.getHeader("username");Student student = new Student();student.setUsername(username);// 先查询该学生信息QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>(student);Student studentResult = studentMapper.selectOne(studentQueryWrapper);// 返回信息Map<String, Object> result = new HashMap<>();// 如果旧密码匹配,则更新密码,销毁 redis 中该 user 所有有效的 token// 第一个参数为明文,第二个参数为密文if (passwordEncoder.matches(oldPwd, studentResult.getPassword())) {student.setId(studentResult.getId());// 密码需要加密student.setPassword(passwordEncoder.encode(newPwd));// 通过 id 更新if (studentMapper.updateById(student) == MySQLMessageConstant.OPERATE_FAIL) {log.error(messageSource.getMessage(MySQLMessageConstant.UPDATE_FAIL, null, LocaleContextHolder.getLocale()));throw new CustomerException(messageSource.getMessage(MySQLMessageConstant.UPDATE_FAIL, null, LocaleContextHolder.getLocale()));}// 销毁所有有效 tokenObject object = redisTemplate.opsForHash().get(RedisConstant.USERID_TOKEN_MAP, username);List<String> userToken = Convert.toList(String.class, object);redisTemplate.opsForHash().delete(RedisConstant.USERID_TOKEN_MAP, username);userToken.forEach(p -> redisTemplate.delete(p));result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.SUCCESS_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.SUCCESS_MSG);// 信息} else {result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.FAIL_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.OLD_PWD_ERROR_MSG);// 信息}return result;}@Override@GlobalTransactionalpublic Map<String, Object> updateInfo(HttpServletRequest request, Map<String, String> parameters) throws CustomerException {// 返回信息Map<String, Object> result = new HashMap<>();// 获取 邮箱 验证码String email = request.getHeader("username");String code = parameters.get(ResultMsgConstant.RESULT_CODE);// 验证逻辑if (EmailCodeUtil.checkCode(email, code)) {// 判断更新信息是否合法,是否与数据库记录冲突// 构造查询实体Student queryUser = new Student();queryUser.setUsername(email);QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>(queryUser);//执行查询Student studentResult = studentMapper.selectOne(studentQueryWrapper);if (studentResult != null) {// 构建更新对象Student student = JSON.parseObject(JSON.toJSONString(parameters), Student.class);// student idstudent.setId(studentResult.getId());// 防止学生权限被修改student.setRoles(studentResult.getRoles());// 写入数据库并检验结果if (studentMapper.updateById(student) == MySQLMessageConstant.OPERATE_FAIL) {log.error(messageSource.getMessage(MySQLMessageConstant.UPDATE_FAIL, null, LocaleContextHolder.getLocale()));throw new CustomerException(messageSource.getMessage(MySQLMessageConstant.UPDATE_FAIL, null, LocaleContextHolder.getLocale()));}// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.SUCCESS_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.SUCCESS_MSG);// 信息EmailCodeUtil.destroyCode(email, code);} else {// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.SUCCESS_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.USER_NOT_FOUND_MSG);// 信息}} else {// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.FAIL_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.CODE_ERROR_MSG);// 信息}return result;}@Overridepublic Map<String, Object> getInfo(HttpServletRequest request) {// 返回信息Map<String, Object> result = new HashMap<>();// 构造查询实体条件QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();studentQueryWrapper.select("id", "login_time", "nickname", "sno", "status", "username", "sid").eq("username", request.getHeader("username"));//执行查询Student student = studentMapper.selectOne(studentQueryWrapper);// 返回信息if (student == null) {// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.SUCCESS_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.SUCCESS_MSG);// 信息result.put(ResultMsgConstant.RESULT_DATA, ResultMsgConstant.EMPTY_DATA);// 数据} else {// 返回信息result.put(ResultMsgConstant.RESULT_CODE, ResultMsgConstant.SUCCESS_CODE);// 状态码result.put(ResultMsgConstant.RESULT_MSG, ResultMsgConstant.SUCCESS_MSG);// 信息result.put(ResultMsgConstant.RESULT_DATA, JSONObject.toJSON(student));// 数据}return result;}
}

其他配置与 SchoolAdmin 模块类似:

(十五、Student 模块实现)莞工校招助手【微服务应用】相关推荐

  1. (二、模块设计)莞工校招助手【微服务应用】

    父工程 dgut-campus-recruiting-helper 公共模块 public-commons(接口与实体类.实现类) 微服务模块 校方管理员 admin-module,端口 807X(8 ...

  2. (十、Seata 分布式事务)莞工校招助手【微服务应用】

    参考 官方文档 下载 Seata 官方下载地址 我使用的是 1.4.1 版本: 进入conf目录,调整下面的配置文件 registry.conf 设置使用 Nacos 注册中心: registry { ...

  3. (七、api接口安全设计)莞工校招助手【微服务应用】

    参考 API安全接口安全设计 参考 系列学习互联网安全架构第 3 篇 -- 自定义注解,防止表单重复提交 参考 安全|API接口安全性设计(防篡改和重复调用) 参考 API接口安全设计 参考 数据加密 ...

  4. (十一、采用 Sentinel 服务容错)莞工校招助手【微服务应用】

    参考 Sentinel-Wiki 微服务集成 Sentinel <!-- 容错组件sentinel --><dependency><groupId>com.alib ...

  5. (十四、SchoolAdmin 模块实现)莞工校招助手【微服务应用】

    常规的增删查改. pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&quo ...

  6. 《深入理解 Spring Cloud 与微服务构建》第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统

    <深入理解 Spring Cloud 与微服务构建>第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统 文章目录 <深入理解 Spring Cl ...

  7. GO微服务实战第五节 为什么说 Service Meh 是下一代微服务架构?

    在前面第 2 课时我们介绍过,Service Mesh(服务网格) 是云原生的代表技术之一,并且在后面的组件案例实践中,Service Mesh 也是其中的"主角",因此我们非常有 ...

  8. Linux netfilter 学习笔记 之十五 netfilter模块添加一个match

    通过这段时间的学习,基本上熟悉了netfilter模块,为了进一步加深对netfilter的认识以及理解iptables与netfilter的联系,准备添加一个match模块. 在看到网关产品会有一个 ...

  9. Python学习日记(十五) collections模块

    在内置函数(dict.list.set.tuple)的基础上,collections模块还提供了几个其他的数据类型:Counter.deque.defaultdict.namedtuple和Order ...

最新文章

  1. Python import 的用法
  2. 这样出ORACLE的面试题
  3. js中match、replace方法中使用正则表达式
  4. Centos 配置mailx使用外部smtp发送邮件
  5. 【学术相关】西湖大学教授:都说不唯论文,那我们发表论文是为了什么?
  6. android如何监听按钮,Android – 两个onClick监听器和一个按钮
  7. Linux 命令之 iostat 命令-监视系统输入输出设备和 cpu 的使用情况
  8. selenium web的自动化测试工具
  9. nginx access.log 忽略favicon.ico訪问记录的方法
  10. (查看dll函数名和参数)通过VS自带的dumpbin查看dll包含的函数
  11. 免费HTML5期末大作业:我的家乡网站设计——可根据百度百科--曹县
  12. Android Studio 报错:Incompatible types
  13. 详解:什么是NVMe?
  14. gps测距+java_GPS测距会高估你的移动距离
  15. 76.0.3809.100版本的谷歌浏览器对应能用的chromedriver版本
  16. Linux上配置BIP语言编译器及引擎
  17. Linux内核部件分析 设备驱动模型之driver ---mark 详细
  18. 【KCP】UDP可靠性传输
  19. 智慧树大数据分析python答案_智慧树大数据分析的python基础答案
  20. JAVA中一些术语的中英文对照

热门文章

  1. 许嵩新歌《想象之中》首发 全新思想大碟将发行
  2. linux 解压zip压缩包命令
  3. 视频制作,如何添加滚动字幕
  4. 如何使用Movavi Picverse修复​​模糊图片?
  5. ff14服务器稳定,ff14服务器选择
  6. 管理学十一(选人、用人、优秀员工特征与避免流失)
  7. 2020全球CEO年薪大榜:劈柴哥年入2.8亿美元登顶
  8. 【Python基础】Python全栈体系(一)
  9. 联发科MT6779(Helio P90)基带处理器介绍
  10. php没有游戏经验,王者荣耀最强脑洞玩家诞生,没有十年游戏经验,谁也想不出这些ID...