diff --git a/README.md b/README.md index 5e88293..7942e77 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # forest - +![forest](src/main/resources/static/logo_size.jpg) 下一代的知识社区系统,为未来而建 ## 💡 简介 diff --git a/pom.xml b/pom.xml index 8edbd3b..c418103 100644 --- a/pom.xml +++ b/pom.xml @@ -88,19 +88,19 @@ com.github.pagehelper pagehelper - 5.1.10 + 5.2.0 com.alibaba fastjson - 1.2.67 + 1.2.76 org.apache.shiro shiro-spring - 1.4.1 + 1.7.1 diff --git a/src/main/java/com/rymcu/forest/answer/AnswerController.java b/src/main/java/com/rymcu/forest/answer/AnswerController.java index 605e189..92df131 100644 --- a/src/main/java/com/rymcu/forest/answer/AnswerController.java +++ b/src/main/java/com/rymcu/forest/answer/AnswerController.java @@ -2,7 +2,6 @@ package com.rymcu.forest.answer; import com.alibaba.fastjson.JSONObject; import com.rymcu.forest.core.result.GlobalResult; -import com.rymcu.forest.core.result.GlobalResultGenerator; import com.rymcu.forest.core.service.log.annotation.TransactionLogger; import com.rymcu.forest.dto.AnswerDTO; import com.rymcu.forest.entity.User; diff --git a/src/main/java/com/rymcu/forest/service/JavaMailService.java b/src/main/java/com/rymcu/forest/service/JavaMailService.java index 269cd20..761d3c6 100644 --- a/src/main/java/com/rymcu/forest/service/JavaMailService.java +++ b/src/main/java/com/rymcu/forest/service/JavaMailService.java @@ -1,5 +1,7 @@ package com.rymcu.forest.service; +import com.rymcu.forest.dto.NotificationDTO; + import javax.mail.MessagingException; /** @@ -12,6 +14,7 @@ public interface JavaMailService { * 发送验证码邮件 * @param email 收件人邮箱 * @return 执行结果 0:失败1:成功 + * @throws MessagingException * */ Integer sendEmailCode(String email) throws MessagingException; @@ -19,6 +22,15 @@ public interface JavaMailService { * 发送找回密码邮件 * @param email 收件人邮箱 * @return 执行结果 0:失败1:成功 + * @throws MessagingException * */ Integer sendForgetPasswordEmail(String email) throws MessagingException; + + /** + * 发送下消息通知 + * @param notification + * @return + * @throws MessagingException + */ + Integer sendNotification(NotificationDTO notification) throws MessagingException; } diff --git a/src/main/java/com/rymcu/forest/service/impl/JavaMailServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/JavaMailServiceImpl.java index 0b40654..fe4f4cc 100644 --- a/src/main/java/com/rymcu/forest/service/impl/JavaMailServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/JavaMailServiceImpl.java @@ -1,7 +1,11 @@ package com.rymcu.forest.service.impl; +import com.rymcu.forest.core.constant.NotificationConstant; import com.rymcu.forest.core.service.redis.RedisService; +import com.rymcu.forest.dto.NotificationDTO; +import com.rymcu.forest.entity.User; import com.rymcu.forest.service.JavaMailService; +import com.rymcu.forest.service.UserService; import com.rymcu.forest.util.Utils; import org.apache.commons.lang.time.StopWatch; import org.springframework.beans.factory.annotation.Value; @@ -34,6 +38,8 @@ public class JavaMailServiceImpl implements JavaMailService { private JavaMailSenderImpl mailSender; @Resource private RedisService redisService; + @Resource + private UserService userService; /** * thymeleaf模板引擎 */ @@ -53,12 +59,49 @@ public class JavaMailServiceImpl implements JavaMailService { @Override public Integer sendEmailCode(String email) throws MessagingException { - return sendCode(email,0); + return sendCode(email, 0); } @Override public Integer sendForgetPasswordEmail(String email) throws MessagingException { - return sendCode(email,1); + return sendCode(email, 1); + } + + @Override + public Integer sendNotification(NotificationDTO notification) throws MessagingException { + Properties props = new Properties(); + // 表示SMTP发送邮件,需要进行身份验证 + props.put("mail.smtp.auth", true); + props.put("mail.smtp.ssl.enable", true); + props.put("mail.smtp.host", SERVER_HOST); + props.put("mail.smtp.port", SERVER_PORT); + // 如果使用ssl,则去掉使用25端口的配置,进行如下配置, + props.put("mail.smtp.socketFactory.class", "com.rymcu.forest.util.MailSSLSocketFactory"); + props.put("mail.smtp.socketFactory.port", SERVER_PORT); + // 发件人的账号,填写控制台配置的发信地址,比如xxx@xxx.com + props.put("mail.user", USERNAME); + // 访问SMTP服务时需要提供的密码(在控制台选择发信地址进行设置) + props.put("mail.password", PASSWORD); + mailSender.setJavaMailProperties(props); + User user = userService.findById(String.valueOf(notification.getIdUser())); + if (NotificationConstant.Comment.equals(notification.getDataType())) { + String url = notification.getDataUrl(); + String thymeleafTemplatePath = "mail/commentNotification"; + Map thymeleafTemplateVariable = new HashMap(4); + thymeleafTemplateVariable.put("user", notification.getAuthor().getUserNickname()); + thymeleafTemplateVariable.put("articleTitle", notification.getDataTitle()); + thymeleafTemplateVariable.put("content", notification.getDataSummary()); + thymeleafTemplateVariable.put("url", url); + + sendTemplateEmail(USERNAME, + new String[]{user.getEmail()}, + new String[]{}, + "【RYMCU】 消息通知", + thymeleafTemplatePath, + thymeleafTemplateVariable); + return 1; + } + return 0; } private Integer sendCode(String to, Integer type) throws MessagingException { @@ -79,29 +122,29 @@ public class JavaMailServiceImpl implements JavaMailService { SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); simpleMailMessage.setFrom(USERNAME); simpleMailMessage.setTo(to); - if(type == 0) { + if (type == 0) { Integer code = Utils.genCode(); - redisService.set(to,code,5*60); + redisService.set(to, code, 5 * 60); simpleMailMessage.setSubject("新用户注册邮箱验证"); simpleMailMessage.setText("【RYMCU】您的校验码是 " + code + ",有效时间 5 分钟,请不要泄露验证码给其他人。如非本人操作,请忽略!"); mailSender.send(simpleMailMessage); return 1; - } else if(type == 1){ + } else if (type == 1) { String code = Utils.entryptPassword(to); String url = BASE_URL + "/forget-password?code=" + code; - redisService.set(code,to,15*60); + redisService.set(code, to, 15 * 60); - String thymeleafTemplatePath = "mail/forgetPasswordTemplate"; - Map thymeleafTemplateVariable = new HashMap(); - thymeleafTemplateVariable.put("url", url); + String thymeleafTemplatePath = "mail/forgetPasswordTemplate"; + Map thymeleafTemplateVariable = new HashMap(1); + thymeleafTemplateVariable.put("url", url); - sendTemplateEmail(USERNAME, - new String[] { to }, - new String[] {}, - "【RYMCU】 找回密码", - thymeleafTemplatePath, - thymeleafTemplateVariable); - return 1; + sendTemplateEmail(USERNAME, + new String[]{to}, + new String[]{}, + "【RYMCU】 找回密码", + thymeleafTemplatePath, + thymeleafTemplateVariable); + return 1; } return 0; } @@ -109,25 +152,19 @@ public class JavaMailServiceImpl implements JavaMailService { /** * 发送thymeleaf模板邮件 * - * @param deliver - * 发送人邮箱名 如: javalsj@163.com - * @param receivers - * 收件人,可多个收件人 如:11111@qq.com,2222@163.com - * @param carbonCopys - * 抄送人,可多个抄送人 如:33333@sohu.com - * @param subject - * 邮件主题 如:您收到一封高大上的邮件,请查收。 - * @param thymeleafTemplatePath - * 邮件模板 如:mail\mailTemplate.html。 - * @param thymeleafTemplateVariable - * 邮件模板变量集 + * @param deliver 发送人邮箱名 如: javalsj@163.com + * @param receivers 收件人,可多个收件人 如:11111@qq.com,2222@163.com + * @param carbonCopys 抄送人,可多个抄送人 如:33333@sohu.com + * @param subject 邮件主题 如:您收到一封高大上的邮件,请查收。 + * @param thymeleafTemplatePath 邮件模板 如:mail\mailTemplate.html。 + * @param thymeleafTemplateVariable 邮件模板变量集 */ public void sendTemplateEmail(String deliver, String[] receivers, String[] carbonCopys, String subject, String thymeleafTemplatePath, Map thymeleafTemplateVariable) throws MessagingException { String text = null; if (thymeleafTemplateVariable != null && thymeleafTemplateVariable.size() > 0) { Context context = new Context(); - thymeleafTemplateVariable.forEach((key, value)->context.setVariable(key, value)); + thymeleafTemplateVariable.forEach((key, value) -> context.setVariable(key, value)); text = templateEngine.process(thymeleafTemplatePath, context); } sendMimeMail(deliver, receivers, carbonCopys, subject, text, true, null); @@ -136,22 +173,15 @@ public class JavaMailServiceImpl implements JavaMailService { /** * 发送的邮件(支持带附件/html类型的邮件) * - * @param deliver - * 发送人邮箱名 如: javalsj@163.com - * @param receivers - * 收件人,可多个收件人 如:11111@qq.com,2222@163.com - * @param carbonCopys - * 抄送人,可多个抄送人 如:3333@sohu.com - * @param subject - * 邮件主题 如:您收到一封高大上的邮件,请查收。 - * @param text - * 邮件内容 如:测试邮件逗你玩的。 - * @param attachmentFilePaths - * 附件文件路径 如: - * 需要注意的是addInline函数中资源名称attchmentFileName需要与正文中cid:attchmentFileName对应起来 - * @throws Exception - * 邮件发送过程中的异常信息 + * @param deliver 发送人邮箱名 如: javalsj@163.com + * @param receivers 收件人,可多个收件人 如:11111@qq.com,2222@163.com + * @param carbonCopys 抄送人,可多个抄送人 如:3333@sohu.com + * @param subject 邮件主题 如:您收到一封高大上的邮件,请查收。 + * @param text 邮件内容 如:测试邮件逗你玩的。 + * @param attachmentFilePaths 附件文件路径 如: + * 需要注意的是addInline函数中资源名称attchmentFileName需要与正文中cid:attchmentFileName对应起来 + * @throws Exception 邮件发送过程中的异常信息 */ private void sendMimeMail(String deliver, String[] receivers, String[] carbonCopys, String subject, String text, boolean isHtml, String[] attachmentFilePaths) throws MessagingException { @@ -186,7 +216,6 @@ public class JavaMailServiceImpl implements JavaMailService { } mailSender.send(mimeMessage); stopWatch.stop(); - //logger.info("邮件发送成功, 花费时间{}秒", stopWatch.getStartTime()); } diff --git a/src/main/java/com/rymcu/forest/service/impl/NotificationServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/NotificationServiceImpl.java index 4883182..22b22d1 100644 --- a/src/main/java/com/rymcu/forest/service/impl/NotificationServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/NotificationServiceImpl.java @@ -1,22 +1,16 @@ package com.rymcu.forest.service.impl; import com.rymcu.forest.core.service.AbstractService; -import com.rymcu.forest.dto.ArticleDTO; -import com.rymcu.forest.dto.Author; import com.rymcu.forest.dto.NotificationDTO; -import com.rymcu.forest.entity.Comment; -import com.rymcu.forest.entity.Follow; import com.rymcu.forest.entity.Notification; -import com.rymcu.forest.entity.User; import com.rymcu.forest.mapper.NotificationMapper; -import com.rymcu.forest.service.*; +import com.rymcu.forest.service.NotificationService; import com.rymcu.forest.util.BeanCopierUtil; -import org.springframework.beans.factory.annotation.Value; +import com.rymcu.forest.util.NotificationUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -28,16 +22,6 @@ public class NotificationServiceImpl extends AbstractService imple @Resource private NotificationMapper notificationMapper; - @Resource - private ArticleService articleService; - @Resource - private CommentService commentService; - @Resource - private UserService userService; - @Resource - private FollowService followService; - @Value("${resource.domain}") - private String domain; private final static String unRead = "0"; @@ -51,7 +35,7 @@ public class NotificationServiceImpl extends AbstractService imple public List findNotifications(Integer idUser) { List list = notificationMapper.selectNotifications(idUser); list.forEach(notification -> { - NotificationDTO notificationDTO = genNotification(notification); + NotificationDTO notificationDTO = NotificationUtils.genNotification(notification); // 判断关联数据是否已删除 if (Objects.nonNull(notificationDTO.getAuthor())) { BeanCopierUtil.copy(notificationDTO, notification); @@ -71,84 +55,6 @@ public class NotificationServiceImpl extends AbstractService imple return list; } - private NotificationDTO genNotification(Notification notification) { - NotificationDTO notificationDTO = new NotificationDTO(); - BeanCopierUtil.copy(notification, notificationDTO); - ArticleDTO article; - Comment comment; - User user; - Follow follow; - switch (notification.getDataType()) { - case "0": - // 系统公告/帖子 - article = articleService.findArticleDTOById(notification.getDataId(), 0); - if (Objects.nonNull(article)) { - notificationDTO.setDataTitle("系统公告"); - notificationDTO.setDataUrl(article.getArticlePermalink()); - user = userService.findById(article.getArticleAuthorId().toString()); - notificationDTO.setAuthor(genAuthor(user)); - } - break; - case "1": - // 关注 - follow = followService.findById(notification.getDataId().toString()); - notificationDTO.setDataTitle("关注提醒"); - if (Objects.nonNull(follow)) { - user = userService.findById(follow.getFollowerId().toString()); - notificationDTO.setDataUrl(getFollowLink(follow.getFollowingType(), user.getNickname())); - notificationDTO.setAuthor(genAuthor(user)); - } - break; - case "2": - // 回帖 - comment = commentService.findById(notification.getDataId().toString()); - article = articleService.findArticleDTOById(comment.getCommentArticleId(), 0); - if (Objects.nonNull(article)) { - notificationDTO.setDataTitle(article.getArticleTitle()); - notificationDTO.setDataUrl(comment.getCommentSharpUrl()); - user = userService.findById(comment.getCommentAuthorId().toString()); - notificationDTO.setAuthor(genAuthor(user)); - } - break; - case "3": - // 关注用户发布文章 - case "4": - // 关注文章更新 - article = articleService.findArticleDTOById(notification.getDataId(), 0); - if (Objects.nonNull(article)) { - notificationDTO.setDataTitle("关注通知"); - notificationDTO.setDataUrl(article.getArticlePermalink()); - user = userService.findById(article.getArticleAuthorId().toString()); - notificationDTO.setAuthor(genAuthor(user)); - } - break; - default: - break; - } - return notificationDTO; - } - - private String getFollowLink(String followingType, String id) { - StringBuilder url = new StringBuilder(); - url.append(domain); - switch (followingType) { - case "0": - url = url.append("/user/").append(id); - break; - default: - url.append("/notification"); - } - return url.toString(); - } - - private Author genAuthor(User user) { - Author author = new Author(); - author.setUserNickname(user.getNickname()); - author.setUserAvatarURL(user.getAvatarUrl()); - author.setIdUser(user.getIdUser()); - return author; - } - @Override public Notification findNotification(Integer idUser, Integer dataId, String dataType) { return notificationMapper.selectNotification(idUser, dataId, dataType); diff --git a/src/main/java/com/rymcu/forest/util/NotificationUtils.java b/src/main/java/com/rymcu/forest/util/NotificationUtils.java index b301bdd..c6b0500 100644 --- a/src/main/java/com/rymcu/forest/util/NotificationUtils.java +++ b/src/main/java/com/rymcu/forest/util/NotificationUtils.java @@ -1,15 +1,17 @@ package com.rymcu.forest.util; import com.rymcu.forest.core.constant.NotificationConstant; +import com.rymcu.forest.dto.ArticleDTO; +import com.rymcu.forest.dto.Author; +import com.rymcu.forest.dto.NotificationDTO; +import com.rymcu.forest.entity.Comment; import com.rymcu.forest.entity.Follow; import com.rymcu.forest.entity.Notification; import com.rymcu.forest.entity.User; -import com.rymcu.forest.service.FollowService; -import com.rymcu.forest.service.NotificationService; -import com.rymcu.forest.service.UserService; +import com.rymcu.forest.service.*; -import javax.annotation.Resource; import java.util.List; +import java.util.Objects; import java.util.concurrent.*; /** @@ -19,12 +21,13 @@ import java.util.concurrent.*; */ public class NotificationUtils { - @Resource private static NotificationService notificationService = SpringContextHolder.getBean(NotificationService.class); - @Resource private static UserService userService = SpringContextHolder.getBean(UserService.class); - @Resource private static FollowService followService = SpringContextHolder.getBean(FollowService.class); + private static JavaMailService mailService = SpringContextHolder.getBean(JavaMailService.class); + + private static ArticleService articleService = SpringContextHolder.getBean(ArticleService.class); + private static CommentService commentService = SpringContextHolder.getBean(CommentService.class); public static void sendAnnouncement(Integer dataId, String dataType, String dataSummary) { ExecutorService executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); @@ -53,6 +56,11 @@ public class NotificationUtils { // TODO 记录操作失败数据 } } + if (NotificationConstant.Comment.equals(dataType)) { + notification = notificationService.findNotification(idUser, dataId, dataType); + NotificationDTO notificationDTO = genNotification(notification); + mailService.sendNotification(notificationDTO); + } } catch (Exception ex) { // TODO 记录操作失败数据 ex.printStackTrace(); @@ -83,4 +91,82 @@ public class NotificationUtils { return 0; }, executor); } + + public static NotificationDTO genNotification(Notification notification) { + NotificationDTO notificationDTO = new NotificationDTO(); + BeanCopierUtil.copy(notification, notificationDTO); + ArticleDTO article; + Comment comment; + User user; + Follow follow; + switch (notification.getDataType()) { + case "0": + // 系统公告/帖子 + article = articleService.findArticleDTOById(notification.getDataId(), 0); + if (Objects.nonNull(article)) { + notificationDTO.setDataTitle("系统公告"); + notificationDTO.setDataUrl(article.getArticlePermalink()); + user = userService.findById(article.getArticleAuthorId().toString()); + notificationDTO.setAuthor(genAuthor(user)); + } + break; + case "1": + // 关注 + follow = followService.findById(notification.getDataId().toString()); + notificationDTO.setDataTitle("关注提醒"); + if (Objects.nonNull(follow)) { + user = userService.findById(follow.getFollowerId().toString()); + notificationDTO.setDataUrl(getFollowLink(follow.getFollowingType(), user.getNickname())); + notificationDTO.setAuthor(genAuthor(user)); + } + break; + case "2": + // 回帖 + comment = commentService.findById(notification.getDataId().toString()); + article = articleService.findArticleDTOById(comment.getCommentArticleId(), 0); + if (Objects.nonNull(article)) { + notificationDTO.setDataTitle(article.getArticleTitle()); + notificationDTO.setDataUrl(comment.getCommentSharpUrl()); + user = userService.findById(comment.getCommentAuthorId().toString()); + notificationDTO.setAuthor(genAuthor(user)); + } + break; + case "3": + // 关注用户发布文章 + case "4": + // 关注文章更新 + article = articleService.findArticleDTOById(notification.getDataId(), 0); + if (Objects.nonNull(article)) { + notificationDTO.setDataTitle("关注通知"); + notificationDTO.setDataUrl(article.getArticlePermalink()); + user = userService.findById(article.getArticleAuthorId().toString()); + notificationDTO.setAuthor(genAuthor(user)); + } + break; + default: + break; + } + return notificationDTO; + } + + private static String getFollowLink(String followingType, String id) { + StringBuilder url = new StringBuilder(); + url.append(Utils.getProperty("resource.domain")); + switch (followingType) { + case "0": + url = url.append("/user/").append(id); + break; + default: + url.append("/notification"); + } + return url.toString(); + } + + private static Author genAuthor(User user) { + Author author = new Author(); + author.setUserNickname(user.getNickname()); + author.setUserAvatarURL(user.getAvatarUrl()); + author.setIdUser(user.getIdUser()); + return author; + } } diff --git a/src/main/resources/static/logo_size.jpg b/src/main/resources/static/logo_size.jpg new file mode 100644 index 0000000..f06a109 Binary files /dev/null and b/src/main/resources/static/logo_size.jpg differ diff --git a/src/main/resources/static/logo_size_invert.jpg b/src/main/resources/static/logo_size_invert.jpg new file mode 100644 index 0000000..d456de3 Binary files /dev/null and b/src/main/resources/static/logo_size_invert.jpg differ diff --git a/src/main/resources/templates/mail/commentNotification.html b/src/main/resources/templates/mail/commentNotification.html new file mode 100644 index 0000000..920498e --- /dev/null +++ b/src/main/resources/templates/mail/commentNotification.html @@ -0,0 +1,162 @@ + + + + RYMCU 消息通知 + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + +
+ Logo +
+ welcome image + +
+
+
+ + + + + + + + + +
+
+

+ 消息通知

+
+
+
+
+ 评论了您的文章《 》: +
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+ + \ No newline at end of file