* 用户登录成功之后的令牌(token)表 *
* * @author CLL * @since 2020-10-26 */ @Data public class LoginToken implements Serializable { private static final long serialVersionUID = 1L; /** * 自增主键 */ private Integer id; /** * 用户邮箱 */ private String email; /** * 登录成功之后的令牌 */ private String token; /** * 创建时间 * 注解@JsonFormat:标识返回数据的时候将已json格式返回 * 注解@DateTimeFormat:标识该对象接收数据的时候,将以指定格式接收 */ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime gmtCreate; } ``` > 登录令牌持久层接口 ```java package com.cll.prototype.api.user.mapper; import com.cll.prototype.api.user.entity.LoginToken; import org.apache.ibatis.annotations.Param; /** ** 用户登录成功之后的令牌(token)表 Mapper 接口 *
* * @author CLL * @since 2020-10-26 */ public interface LoginTokenMapper { /** * 新增用户登录成功之后的令牌信息 * @param loginToken 登录成功的令牌 * @return 新增记录数 */ int add(@Param("loginToken") LoginToken loginToken); /** * 根据令牌获取用户信息 * @param token 令牌 * @return 用户信息 */ LoginToken getByToken(@Param("token") String token); } ``` > 登录令牌mapper映射配置文件 ```xml* 用户登录成功之后的令牌(token)表 服务类 *
* * @author CLL * @since 2020-10-26 */ public interface ILoginTokenService { /** * 生成登录成功用户的token * @param email 用户邮箱 * @return 生成结果 */ AjaxResult generateLoginToken(String email); /** * 根据token获取用户信息 * @param token 登录之后的token * @return 用户名 */ AjaxResult getEmailByToken(String token); } ``` > 令牌持久层接口测试类 ```java package com.cll.prototype.user.mapper; import com.cll.prototype.api.user.entity.LoginToken; import com.cll.prototype.api.user.entity.User; import com.cll.prototype.api.user.mapper.LoginTokenMapper; import com.cll.prototype.api.user.mapper.UserMapper; import com.cll.prototype.common.util.UUIDUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.time.LocalDateTime; /** * 描述信息: * 用户持久层接口测试 * @author CLL * @version 1.0 * @date 2020/11/8 15:17 */ @SpringBootTest @RunWith(SpringJUnit4ClassRunner.class) public class LoginTokenMapperTest { private static final Logger logger = LoggerFactory.getLogger(LoginTokenMapperTest.class); @Autowired private LoginTokenMapper loginTokenMapper; @Test public void testAdd() throws Exception{ LoginToken loginToken = new LoginToken(); loginToken.setEmail("2203815100@qq.com"); loginToken.setToken(UUIDUtils.getInstance()); loginToken.setGmtCreate(LocalDateTime.now()); int insertRecord = loginTokenMapper.add(loginToken); logger.info("===>>> result = {}", insertRecord); } @Test public void testGetByToken() throws Exception{ LoginToken loginToken = loginTokenMapper.getByToken("f2b60f3f6fe1424e987c94bbd4fc154d"); logger.info("===>>> result = {}", loginToken); } } ``` > 用户实体类 ```java package com.cll.prototype.api.user.entity; import com.cll.prototype.common.util.LocalDateTimeConverter; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; /** ** 用户服务的表 *
* * @author CLL * @since 2020-10-26 */ @Data public class User implements Serializable { private static final long serialVersionUID = 1L; /** * 自增主键 */ private Integer id; /** * 邮箱 */ private String email; /** * 密码 */ private String password; /** * 创建时间 * 注解@JsonSerialize指定序列化方式返回给前台 */ @JsonSerialize(using = LocalDateTimeConverter.class) private LocalDateTime gmtCreate; } ``` > 用户持久层接口 ```java package com.cll.prototype.api.user.mapper; import com.cll.prototype.api.user.entity.User; import org.apache.ibatis.annotations.Param; /** ** 用户服务的表 Mapper 接口 *
* * @author CLL * @since 2020-10-26 */ public interface UserMapper { /** * 根据用户主键查询用户实体 * @param id 主键 * @return 查询结果 */ User getById(@Param("id") Integer id); /** * 新增用户 * @param user 用户实体 * @return 新增记录数 */ int add(@Param("user") User user); /** * 根据邮箱名查询用户 * @param email 邮箱 * @return 用户实体 */ User getByEmail(@Param("email") String email); } ``` > 用户mapper映射配置文件 ```xml* 用户服务的表 服务类 *
* * @author CLL * @since 2020-10-26 */ public interface IUserService { /** * 添加新用户 * @param email 邮箱号码 * @param password 密码 * @param confirmPassword 确认密码 * @param captcha 验证码 * @return 添加结果 */ AjaxResult add(String email, String password, String confirmPassword, String captcha); /** * 添加新用户 * @param user 用户实体 * @return 添加结果 */ AjaxResult add(User user); /** * 检测邮箱是否注册 * @param email 邮箱号码 * @return 检测结果.data:0表示邮箱没有注册;data:1:表示邮箱已经注册 */ AjaxResult isRegistry(String email); /** * 用户登录 * @param email 邮箱号 * @param password 密码 * @return 登录结果 */ AjaxResult login(String email, String password); } ``` > 用户持久层接口测试类 ```java package com.cll.prototype.user.mapper; import com.cll.prototype.api.user.entity.User; import com.cll.prototype.api.user.mapper.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.time.LocalDateTime; /** * 描述信息: * 用户持久层接口测试 * @author CLL * @version 1.0 * @date 2020/11/8 15:17 */ @SpringBootTest @RunWith(SpringJUnit4ClassRunner.class) public class UserMapperTest { private static final Logger logger = LoggerFactory.getLogger(UserMapperTest.class); @Autowired private UserMapper userMapper; @Test public void testGetById() throws Exception{ User user = userMapper.getById(1); logger.info("===>>> result = {}", user); } @Test public void testAdd() throws Exception{ User user = new User(); user.setEmail("794685750@qq.com"); user.setGmtCreate(LocalDateTime.now()); user.setPassword("123456"); int insertRecord = userMapper.add(user); logger.info("===>>> result = {}", insertRecord); } @Test public void testGetByEmail() throws Exception{ User user = userMapper.getByEmail("794685750@qq.com"); logger.info("===>>> result = {}", user); } } ``` > 用户模块添加服务层实现类和控制成 > jar包引入 ```xml* 用户服务的表 前端控制器 *
* * @author CLL * @since 2020-10-26 */ @RestController @RequestMapping("/user") public class UserController { private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class); @Autowired private IUserService userService; /** * 用户注册 * @param email 邮箱号 * @param password 密码 * @param confirmPassword 确认密码 * @param captcha 验证码 * @return 注册结果 */ @PostMapping(value = "/registry") public AjaxResult registry(@RequestParam("email") String email, @RequestParam("password") String password, @RequestParam("confirmPassword") String confirmPassword, @RequestParam("captcha") String captcha, HttpServletResponse response){ try { AjaxResult registryResult = userService.add(email, password, confirmPassword, captcha); if (null != registryResult && AjaxResultEnum.SUCCESS.getCode() == registryResult.getCode() && null != registryResult.getData()) { Cookie cookie = new Cookie("token", registryResult.getData().toString()); response.addCookie(cookie); } return registryResult; } catch (Exception e) { LOGGER.error("******用户注册抛出异常" + e.getMessage(), e); return AjaxResult.error(50, "注册失败"); } } /** * 检测邮箱是否注册 * @param email 邮箱号码 * @return 检测结果 */ @PostMapping(value = "/isRegistry") public AjaxResult isRegistry(@RequestParam("email") String email){ LOGGER.info("===>>> 检测邮箱是否已经注册。email = {}", email); try { return userService.isRegistry(email); } catch (Exception e) { LOGGER.error("****** 检测邮箱是否注册抛出异常" + e.getMessage(), e); return AjaxResult.error(52, "检测失败"); } } } ``` > 登录令牌服务层实现类 ```java package com.cll.prototype.user.service.impl; import com.cll.prototype.api.user.entity.LoginToken; import com.cll.prototype.api.user.mapper.LoginTokenMapper; import com.cll.prototype.api.user.service.ILoginTokenService; import com.cll.prototype.common.dto.AjaxResult; import com.cll.prototype.common.util.UUIDUtils; import com.cll.prototype.common.util.ValidateUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDateTime; /** * 描述信息: * 登录成功令牌服务层实现类 * @author CLL * @version 1.0 * @date 2020/11/8 15:57 */ @Service public class LoginTokenServiceImpl implements ILoginTokenService { @Autowired private LoginTokenMapper loginTokenMapper; @Override public AjaxResult generateLoginToken(String email) { if (StringUtils.isBlank(email)) { return AjaxResult.error(42, "参数不合法"); } if (!ValidateUtils.checkEmailAddress(email)) { return AjaxResult.error(46, "邮箱地址不合法"); } String token = UUIDUtils.getInstance(); LoginToken loginToken = new LoginToken(); loginToken.setEmail(email); loginToken.setToken(token); loginToken.setGmtCreate(LocalDateTime.now()); int addRecord = loginTokenMapper.add(loginToken); return 1 == addRecord ? AjaxResult.success(20, "登录成功", token) : AjaxResult.error("系统错误"); } @Override public AjaxResult getEmailByToken(String token) { LoginToken loginToken = loginTokenMapper.getByToken(token); if (null == loginToken) { return AjaxResult.error(43, "token不合法"); } return AjaxResult.success(20, "获取成功", loginToken.getEmail()); } } ``` > 登录令牌控制层 ```java package com.cll.prototype.user.controller; import com.cll.prototype.common.dictionary.AjaxResultEnum; import com.cll.prototype.common.dto.AjaxResult; import com.cll.prototype.api.user.service.ILoginTokenService; import com.cll.prototype.api.user.service.IUserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; /** ** 用户登录成功之后的令牌(token)表 前端控制器 *
* * @author CLL * @since 2020-10-26 */ @RestController @RequestMapping("/login_token") public class LoginTokenController { private static final Logger logger = LoggerFactory.getLogger(LoginTokenController.class); @Autowired private IUserService userService; @Autowired private ILoginTokenService loginTokenService; /** * 用户登录 * @param email 邮箱 * @param password 密码 * @return 登录结果.登录成功之后,生成token,存放到数据库中,并写入cookie中 */ @PostMapping(value = "/login") public AjaxResult login(@RequestParam("email") String email, @RequestParam("password") String password, HttpServletResponse response){ try { AjaxResult loginResult = userService.login(email, password); if (null != loginResult && AjaxResultEnum.SUCCESS.getCode() == loginResult.getCode() && null != loginResult.getData()) { Cookie cookie = new Cookie("token", loginResult.getData().toString()); response.addCookie(cookie); } return loginResult; } catch (Exception e) { logger.error("****** 用户登录抛出异常" + e.getMessage(), e); return AjaxResult.error(55, "用户登录抛出异常"); } } /** * 根据令牌获取用户邮箱号 * @param token 令牌 * @return 获取结果 */ @PostMapping(value = "/getEmailByToken") public AjaxResult getEmailByToken(@RequestParam("token") String token){ try { return loginTokenService.getEmailByToken(token); } catch (Exception e) { logger.error("****** 根据token获取用户信息抛出异常" + e.getMessage(), e); return AjaxResult.error(51, "获取用户信息失败"); } } } ``` > 将服务注册到Eureka注册中心上 > jar包引入 ```xml> * 验证码服务的表 > *
> * > * @author CLL > * @since 2020-10-26 > */ > @Data > public class AuthCaptcha implements Serializable { > > private static final long serialVersionUID = 1L; > > /** > * 自增主键 > */ > private Integer id; > > /** > * 接收验证码主体 > * 可以是邮箱号、手机号等 > */ > private String subject; > > /** > * 接收验证码主体类型 > * 1:邮箱 > * 2:手机号码 > */ > private Integer subjectType; > > /** > * 验证码 > */ > private String captcha; > > /** > * 验证码类型。1:注册验证码 > */ > private Integer type; > > /** > * 创建时间 > */ > private LocalDateTime gmtCreate; > > /** > * 验证码过期时间 > */ > private LocalDateTime gmtExpire; > > > } > ``` > > > 验证码持久层接口 > > ```java > package com.cll.prototype.api.captcha.mapper; > > import com.cll.prototype.api.captcha.entity.AuthCaptcha; > import org.apache.ibatis.annotations.Param; > > /** > *> * 验证码服务的表 Mapper 接口 > *
> * > * @author CLL > * @since 2020-10-26 > */ > public interface AuthCaptchaMapper { > > /** > * 获取邮箱最后一次发送的验证码 > * @param email 邮箱号 > * @return 最后一次记录 > */ > AuthCaptcha getLastByEmail(@Param("email") String email); > > /** > * 新增验证码记录 > * @param authCaptcha 验证码实体 > * @return 新增记录数 > */ > int add(@Param("authCaptcha") AuthCaptcha authCaptcha); > } > ``` > > > 验证码mapper映射配置文件 > > ```xml > > >> * 验证码服务的表 服务类 > *
> * > * @author CLL > * @since 2020-10-26 > */ > public interface IAuthCaptchaService { > > /** > * 生成验证码 > * 存储数据库 > * 发送邮件 > * @param email 邮箱 > * @return 执行结果 > */ > AjaxResult createRegisterCaptchaAndSendEmail(String email); > > /** > * 校验验证码是否有效 > * @param email 邮箱号码 > * @param captcha 验证码 > * @return 校验结果 > */ > AjaxResult checkCaptcha(String email, String captcha); > > } > ``` > > > 验证码持久层接口测试类 > > ```java > package com.cll.prototype.captcha.mapper; > > import com.cll.prototype.api.captcha.entity.AuthCaptcha; > import com.cll.prototype.api.captcha.mapper.AuthCaptchaMapper; > import com.cll.prototype.common.util.RandomUtils; > import org.junit.Test; > import org.junit.runner.RunWith; > import org.slf4j.Logger; > import org.slf4j.LoggerFactory; > import org.springframework.beans.factory.annotation.Autowired; > import org.springframework.boot.test.context.SpringBootTest; > import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; > > import java.time.LocalDateTime; > > /** > * 描述信息: > * > * @author CLL > * @version 1.0 > * @date 2020/11/8 17:30 > */ > @SpringBootTest > @RunWith(SpringJUnit4ClassRunner.class) > public class AuthCaptchaMapperTest { > > private static final Logger logger = LoggerFactory.getLogger(AuthCaptchaMapperTest.class); > > @Autowired > private AuthCaptchaMapper authCaptchaMapper; > > @Test > public void testAdd() throws Exception { > AuthCaptcha authCaptcha = new AuthCaptcha(); > authCaptcha.setCaptcha(RandomUtils.getRandomStr2(6)); > authCaptcha.setSubject("3302815100@qq.com"); > authCaptcha.setSubjectType(1); > authCaptcha.setType(1); > LocalDateTime now = LocalDateTime.now(); > authCaptcha.setGmtCreate(now); > authCaptcha.setGmtExpire(now.plusMinutes(10)); > int insertRecord = authCaptchaMapper.add(authCaptcha); > logger.info("===>>> result = {}", insertRecord); > } > > @Test > public void testGetLastByEmail() throws Exception { > AuthCaptcha last = authCaptchaMapper.getLastByEmail("3302815100@qq.com"); > logger.info("===>>> result = {}", last); > } > } > ``` > 创建项目 ```xml* 验证码服务的表 服务实现类 *
* * @author CLL * @since 2020-10-26 */ @Service public class AuthCaptchaServiceImpl implements IAuthCaptchaService { private static final Logger logger = LoggerFactory.getLogger(AuthCaptchaServiceImpl.class); @Autowired private AuthCaptchaMapper authCaptchaMapper; @Override public AjaxResult createRegisterCaptchaAndSendEmail(String email) { logger.info("===>>> 验证码服务开始生成验证码"); // 1.检验邮箱合法性 boolean checkEmailAddress = ValidateUtils.checkEmailAddress(email); if (!checkEmailAddress){ return AjaxResult.error(45, "邮箱不合法"); } // 2.检测验证码获取频率。必须间隔大于1分钟 AuthCaptcha last = authCaptchaMapper.getLastByEmail(email); if (null != last && LocalDateTime.now().isBefore(last.getGmtCreate().plusMinutes(1))) { return AjaxResult.error(46, "一分钟只能获取一次注册验证码"); } // 3.生成验证码 String captcha = RandomUtils.getRandomStr2(6); AuthCaptcha authCaptcha = new AuthCaptcha(); authCaptcha.setCaptcha(captcha); authCaptcha.setSubject(email); authCaptcha.setSubjectType(1); authCaptcha.setType(1); LocalDateTime now = LocalDateTime.now(); authCaptcha.setGmtCreate(now); authCaptcha.setGmtExpire(now.plusMinutes(10)); // 4.存储数据库 int insertRecord = authCaptchaMapper.add(authCaptcha); if (1 == insertRecord) { // 5.发送邮件 TODO 未实现远程调用 // return sendEmailLogControllerFeignClient.sendEmailCaptcha(email, captcha); return AjaxResult.error(); } return AjaxResult.error(51, "生成注册验证码失败"); } @Override public AjaxResult checkCaptcha(String email, String captcha) { if (StringUtils.isAnyBlank(email, captcha)) { return AjaxResult.error(41, "参数不合法"); } // 1.检测邮箱号是否合法 boolean emailAddress = ValidateUtils.checkEmailAddress(email); if (emailAddress) { AuthCaptcha last = authCaptchaMapper.getLastByEmail(email); if (null == last) { return AjaxResult.error(44, "请先获取验证码"); } if (LocalDateTime.now().isAfter(last.getGmtExpire())) { return AjaxResult.error(43, "验证码已过有效期,请重新获取"); } if (!captcha.equals(last.getCaptcha())) { return AjaxResult.error(45, "验证码不正确"); } return AjaxResult.success(20, "校验通过", 1); } return AjaxResult.error(42, "邮箱号码不合法"); } } ``` > 控制层开发 ```java package com.cll.prototype.captcha.controller; import com.cll.prototype.api.captcha.service.IAuthCaptchaService; import com.cll.prototype.common.dto.AjaxResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** ** 验证码服务的表 前端控制器 *
* * @author CLL * @since 2020-10-26 */ @RestController @RequestMapping("/auth_captcha") public class AuthCaptchaController { private static final Logger logger = LoggerFactory.getLogger(AuthCaptchaController.class); @Autowired private IAuthCaptchaService authCaptchaService; /** * 1. 生成验证码 * 2. 存储到数据库 * 3. 调用扇出邮箱微服务发送 * @param email 邮箱 * @return 发送结果 */ @PostMapping(value = "/createRegisterCaptcha") public AjaxResult createRegisterCaptcha(@RequestParam("email") String email){ logger.info("===>>> 验证码微服务接收到请求"); try { return authCaptchaService.createRegisterCaptchaAndSendEmail(email); } catch (Exception e) { logger.error("****** 获取注册验证码抛出异常" + e.getMessage(), e); return AjaxResult.error(51, "获取注册验证码异常"); } } /** * 校验验证码 * @param email 邮箱号码 * @param captcha 验证码 * @return 检测结果 */ @PostMapping(value = "/checkCaptcha") public AjaxResult checkCaptcha(@RequestParam("email") String email, @RequestParam("captcha") String captcha){ return authCaptchaService.checkCaptcha(email, captcha); } } ``` 7. 创建邮箱模块 > API模块填充 > 实体类 ```java package com.cll.prototype.api.email.entity; import java.time.LocalDateTime; import java.io.Serializable; import lombok.Data; /** ** *
* * @author CLL * @since 2020-10-27 */ @Data public class SendEmailLog implements Serializable { private static final long serialVersionUID = 1L; private Integer id; /** * 发件人 */ private String sender; /** * 收件人 */ private String receiver; /** * 邮件标题 */ private String subject; /** * 发送内容 */ private String content; /** * 1.文本;2.html;3.图片;4.附件;5.模板 */ private Integer type; /** * 发送时间 */ private LocalDateTime gmtCreate; /** * 发送结果 */ private Integer result; } ``` > 持久层接口 ```java package com.cll.prototype.api.email.mapper; import com.cll.prototype.api.email.entity.SendEmailLog; import org.apache.ibatis.annotations.Param; /** ** Mapper 接口 *
* * @author CLL * @since 2020-10-27 */ public interface SendEmailLogMapper { /** * 添加邮件发送日志 * @param sendEmailLog 日志 * @return 新增记录数 */ int add(@Param("sendEmailLog") SendEmailLog sendEmailLog); } ``` > 持久层mapper映射文件 ```xml* 服务类 *
* * @author CLL * @since 2020-10-27 */ public interface ISendEmailLogService { /** * 发送邮箱验证码并记录发送日志 * @param to 收件人 * @param subject 邮件主题 * @param captcha 验证码 * @return 发送结果 */ AjaxResult sendAndRecord(String to, String subject, String captcha); } ``` > 邮件模块 > JAR包引入 ```xml* 服务实现类 *
* * @author CLL * @since 2020-10-27 */ @Service public class SendEmailLogServiceImpl implements ISendEmailLogService { private static final Logger logger = LoggerFactory.getLogger(SendEmailLogServiceImpl.class); @Value("${spring.mail.username}") private String from; @Autowired private SendEmailLogMapper sendEmailLogMapper; @Autowired private IEmailService emailService; @Override public AjaxResult sendAndRecord(String to, String subject, String captcha) { logger.info("===>>> 发送邮件并记录发送日志"); HashMap* 前端控制器 *
* 邮件发送日志 * @author CLL * @since 2020-10-27 */ @RestController @RequestMapping("/send_email_log") public class SendEmailLogController { private static final Logger logger = LoggerFactory.getLogger(SendEmailLogController.class); @Autowired private ISendEmailLogService sendEmailLogService; @PostMapping(value = "/sendEmailCaptcha") public AjaxResult sendEmailCaptcha(@RequestParam("email") String email, @RequestParam("captcha") String captcha){ logger.info("===>>> 邮件服务发送注册验证码邮件"); return sendEmailLogService.sendAndRecord(email, "注册验证码", captcha); } } ``` > 持久层接口单元测试 ```java package com.cll.prototype.email.mapper; import com.cll.prototype.api.email.entity.SendEmailLog; import com.cll.prototype.api.email.mapper.SendEmailLogMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.time.LocalDateTime; /** * 描述信息: * * @author CLL * @version 1.0 * @date 2020/11/8 19:34 */ @SpringBootTest @RunWith(SpringJUnit4ClassRunner.class) public class SendEmailLogMapperTest { private static final Logger logger = LoggerFactory.getLogger(SendEmailLogMapperTest.class); @Autowired private SendEmailLogMapper sendEmailLogMapper; @Test public void testAdd() throws Exception { SendEmailLog sendEmailLog = new SendEmailLog(); sendEmailLog.setSender("3302815100@qq.com"); sendEmailLog.setReceiver("794685750@qq.com"); sendEmailLog.setSubject("注册验证码"); sendEmailLog.setContent("注册模板"); sendEmailLog.setType(5); sendEmailLog.setResult(20); sendEmailLog.setGmtCreate(LocalDateTime.now()); int insertRecord = sendEmailLogMapper.add(sendEmailLog); logger.info("===>>> result = {}", insertRecord); } } ``` 8. 用户模块添加Feign的远程调用 > 添加依赖 ```xml