Commit 9e2b3f66ade564783f9e357fd044b5a96a78e0e7
1 parent
97a1d2ed
feat(shop): 添加邮件发送功能并优化产品关联逻辑
- 新增邮件发送相关配置和代码,实现邮件发送功能 - 优化产品关联逻辑,解决空指针异常问题 - 更新数据库连接配置
Showing
11 changed files
with
253 additions
and
23 deletions
admin/src/main/resources/application-test.yml
@@ -57,9 +57,9 @@ spring: | @@ -57,9 +57,9 @@ spring: | ||
57 | testWhileIdle: true | 57 | testWhileIdle: true |
58 | testOnBorrow: true | 58 | testOnBorrow: true |
59 | testOnReturn: true | 59 | testOnReturn: true |
60 | - password: 123456 | 60 | + password: canrd@2024 |
61 | time-between-eviction-runs-millis: 1000 | 61 | time-between-eviction-runs-millis: 1000 |
62 | - url: jdbc:mysql://159.75.211.11:3306/canrd?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true | 62 | + url: jdbc:mysql://39.108.227.113:3307/canrd?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true |
63 | username: root | 63 | username: root |
64 | redis: | 64 | redis: |
65 | database: 3 | 65 | database: 3 |
admin/src/main/resources/application.yml
shop/pom.xml
@@ -43,6 +43,10 @@ | @@ -43,6 +43,10 @@ | ||
43 | </dependency> | 43 | </dependency> |
44 | <dependency> | 44 | <dependency> |
45 | <groupId>org.springframework.boot</groupId> | 45 | <groupId>org.springframework.boot</groupId> |
46 | + <artifactId>spring-boot-starter-mail</artifactId> | ||
47 | + </dependency> | ||
48 | + <dependency> | ||
49 | + <groupId>org.springframework.boot</groupId> | ||
46 | <artifactId>spring-boot-starter-freemarker</artifactId> | 50 | <artifactId>spring-boot-starter-freemarker</artifactId> |
47 | <version>3.3.5</version> | 51 | <version>3.3.5</version> |
48 | </dependency> | 52 | </dependency> |
shop/src/main/java/com/canrd/shop/controller/EmailController.java
0 → 100644
1 | +package com.canrd.shop.controller; | ||
2 | + | ||
3 | +import com.canrd.shop.common.constant.ServerResult; | ||
4 | +import com.canrd.shop.module.dto.SendTextEmailDto; | ||
5 | +import com.canrd.shop.service.IEmailService; | ||
6 | +import org.springframework.beans.factory.annotation.Autowired; | ||
7 | +import org.springframework.validation.annotation.Validated; | ||
8 | +import org.springframework.web.bind.annotation.*; | ||
9 | + | ||
10 | +/** | ||
11 | + * @author zgt | ||
12 | + * @project canrd-services | ||
13 | + * @description | ||
14 | + * @date 2024/12/27 | ||
15 | + */ | ||
16 | +@RestController | ||
17 | +@RequestMapping("/email") | ||
18 | +public class EmailController { | ||
19 | + @Autowired | ||
20 | + private IEmailService emailService; | ||
21 | + | ||
22 | + /** | ||
23 | + * 发送邮件到配置账号 | ||
24 | + * @param dto | ||
25 | + * @return | ||
26 | + */ | ||
27 | + @PostMapping("/send") | ||
28 | + public ServerResult send(@Validated @RequestBody SendTextEmailDto dto){ | ||
29 | + String content ="姓名:"+ dto.getFirstName()+" " + dto.getLastName()+"\n" +"邮箱:"+ dto.getEmail()+"\n"+"消息:"+dto.getMessage(); | ||
30 | + emailService.sendTo(content); | ||
31 | + return ServerResult.success(); | ||
32 | + } | ||
33 | +} |
shop/src/main/java/com/canrd/shop/module/dto/SendTextEmailDto.java
0 → 100644
1 | +package com.canrd.shop.module.dto; | ||
2 | + | ||
3 | +import lombok.*; | ||
4 | +import lombok.experimental.SuperBuilder; | ||
5 | + | ||
6 | +import javax.validation.constraints.Email; | ||
7 | +import javax.validation.constraints.NotNull; | ||
8 | + | ||
9 | +/** | ||
10 | + * @author zgt | ||
11 | + * @project canrd-services | ||
12 | + * @description | ||
13 | + * @date 2024/12/27 | ||
14 | + */ | ||
15 | +@Data | ||
16 | +@AllArgsConstructor | ||
17 | +@ToString | ||
18 | +@NoArgsConstructor | ||
19 | +@EqualsAndHashCode(callSuper = false) | ||
20 | +@SuperBuilder | ||
21 | +public class SendTextEmailDto { | ||
22 | + | ||
23 | + private String firstName; | ||
24 | + | ||
25 | + private String lastName; | ||
26 | + | ||
27 | |||
28 | + private String email; | ||
29 | + @NotNull | ||
30 | + private String message; | ||
31 | + | ||
32 | + private String subject; | ||
33 | + | ||
34 | +} |
shop/src/main/java/com/canrd/shop/service/IEmailService.java
0 → 100644
1 | +package com.canrd.shop.service; | ||
2 | + | ||
3 | +import java.io.File; | ||
4 | +import java.util.List; | ||
5 | + | ||
6 | +public interface IEmailService { | ||
7 | + | ||
8 | + | ||
9 | + | ||
10 | + /** | ||
11 | + * 邮件发送 | ||
12 | + * | ||
13 | + * @param name 发送人名称 | ||
14 | + * @param to 发送对象 | ||
15 | + * @param subject 主题 | ||
16 | + * @param content 内容 | ||
17 | + * @param isHtml 是否为html | ||
18 | + * @param cc 抄送,多人用逗号隔开 | ||
19 | + * @param bcc 密送,多人用逗号隔开 | ||
20 | + * @param files 文件 | ||
21 | + */ | ||
22 | + void send(String name, String to, String subject, String content, Boolean isHtml, String cc, String bcc, List<File> files); | ||
23 | + | ||
24 | + | ||
25 | + void sendText(String name, String to, String subject, String content); | ||
26 | + | ||
27 | + void sendHtml(String name, String to, String subject, String content); | ||
28 | + | ||
29 | + void sendTo(String content); | ||
30 | +} |
shop/src/main/java/com/canrd/shop/service/impl/EmailServiceImpl.java
0 → 100644
1 | +package com.canrd.shop.service.impl; | ||
2 | + | ||
3 | +import cn.hutool.core.collection.CollectionUtil; | ||
4 | +import com.canrd.shop.common.exception.BusinessException; | ||
5 | +import com.canrd.shop.service.IEmailService; | ||
6 | +import lombok.extern.slf4j.Slf4j; | ||
7 | +import org.apache.commons.lang3.StringUtils; | ||
8 | +import org.springframework.beans.factory.annotation.Autowired; | ||
9 | +import org.springframework.beans.factory.annotation.Value; | ||
10 | +import org.springframework.mail.javamail.JavaMailSender; | ||
11 | +import org.springframework.mail.javamail.MimeMessageHelper; | ||
12 | +import org.springframework.stereotype.Service; | ||
13 | + | ||
14 | +import javax.mail.internet.InternetAddress; | ||
15 | +import java.io.File; | ||
16 | +import java.util.Date; | ||
17 | +import java.util.List; | ||
18 | + | ||
19 | +/** | ||
20 | + * @author zgt | ||
21 | + * @project canrd-services | ||
22 | + * @description | ||
23 | + * @date 2024/12/27 | ||
24 | + */ | ||
25 | +@Slf4j | ||
26 | +@Service | ||
27 | +public class EmailServiceImpl implements IEmailService { | ||
28 | + | ||
29 | + @Value("${mail.to}") | ||
30 | + private String to; | ||
31 | + | ||
32 | + @Autowired | ||
33 | + private JavaMailSender javaMailSender;//注入邮件工具类 | ||
34 | + | ||
35 | + @Value("${spring.mail.username}") | ||
36 | + private String from; | ||
37 | + @Override | ||
38 | + public void send(String name, String to, String subject, String content, Boolean isHtml, String cc, String bcc, List<File> files) { | ||
39 | + | ||
40 | + if (StringUtils.isAnyBlank(from, to, subject, content)) { | ||
41 | + throw new BusinessException("发送人,接收人,主题,内容均不可为空"); | ||
42 | + } | ||
43 | + try { | ||
44 | + //true表示支持复杂类型 | ||
45 | + MimeMessageHelper messageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(), true); | ||
46 | + //邮件发信人 | ||
47 | + messageHelper.setFrom(new InternetAddress(name + "<" + from + ">")); | ||
48 | + //邮件收信人 | ||
49 | + messageHelper.setTo(to.split(",")); | ||
50 | + //邮件主题 | ||
51 | + messageHelper.setSubject(subject); | ||
52 | + //邮件内容 | ||
53 | + messageHelper.setText(content, isHtml); | ||
54 | + //抄送 | ||
55 | + if (!StringUtils.isEmpty(cc)) { | ||
56 | + messageHelper.setCc(cc.split(",")); | ||
57 | + } | ||
58 | + //密送 | ||
59 | + if (!StringUtils.isEmpty(bcc)) { | ||
60 | + messageHelper.setCc(bcc.split(",")); | ||
61 | + } | ||
62 | + //添加邮件附件 | ||
63 | + if (CollectionUtil.isNotEmpty(files)) { | ||
64 | + for (File file : files) { | ||
65 | + messageHelper.addAttachment(file.getName(), file); | ||
66 | + } | ||
67 | + } | ||
68 | + // 邮件发送时间 | ||
69 | + messageHelper.setSentDate(new Date()); | ||
70 | + //正式发送邮件 | ||
71 | + javaMailSender.send(messageHelper.getMimeMessage()); | ||
72 | + } catch (Exception e) { | ||
73 | + throw new BusinessException("邮件发送失败", e); | ||
74 | + } | ||
75 | + } | ||
76 | + | ||
77 | + | ||
78 | + @Override | ||
79 | + public void sendText(String name, String to, String subject, String content) { | ||
80 | + this.send(name, to, subject, content, false, null, null, null); | ||
81 | + } | ||
82 | + | ||
83 | + @Override | ||
84 | + public void sendHtml(String name, String to, String subject, String content) { | ||
85 | + this.send(name, to, subject, content, true, null, null, null); | ||
86 | + } | ||
87 | + | ||
88 | + @Override | ||
89 | + public void sendTo(String content) { | ||
90 | + this.send(from, to, "客户咨询", content, false, null, null, null); | ||
91 | + } | ||
92 | + | ||
93 | +} | ||
94 | + | ||
95 | + |
shop/src/main/java/com/canrd/shop/service/impl/ProductServiceImpl.java
@@ -234,13 +234,31 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductDO> im | @@ -234,13 +234,31 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductDO> im | ||
234 | .collect(Collectors.toList()); | 234 | .collect(Collectors.toList()); |
235 | List<String> collect = productCategoryRelationService.lambdaQuery() | 235 | List<String> collect = productCategoryRelationService.lambdaQuery() |
236 | .select(Productcategoryrelation::getProductId) | 236 | .select(Productcategoryrelation::getProductId) |
237 | - .in(Productcategoryrelation::getCategoryId, cateIds) | ||
238 | - .notIn(Productcategoryrelation::getProductId,productVO.getRelatedProductIds()) | 237 | + .func(wrapper -> { |
238 | + if (CollUtil.isEmpty(cateIds)){ | ||
239 | + wrapper.apply("1!=1"); | ||
240 | + }else { | ||
241 | + wrapper.in(Productcategoryrelation::getCategoryId, cateIds); | ||
242 | + } | ||
243 | + }) | ||
244 | + .func(wrapper -> { | ||
245 | + if (CollUtil.isEmpty(productVO.getRelatedProductIds())){ | ||
246 | + wrapper.apply("1!=1"); | ||
247 | + }else { | ||
248 | + wrapper.notIn(Productcategoryrelation::getProductId,productVO.getRelatedProductIds()); | ||
249 | + } | ||
250 | + }) | ||
239 | .list().stream() | 251 | .list().stream() |
240 | .map(Productcategoryrelation::getProductId) | 252 | .map(Productcategoryrelation::getProductId) |
241 | .collect(Collectors.toList()); | 253 | .collect(Collectors.toList()); |
242 | List<String> records = this.lambdaQuery() | 254 | List<String> records = this.lambdaQuery() |
243 | - .in(ProductDO::getId, collect) | 255 | + .func(wrapper -> { |
256 | + if (CollUtil.isEmpty(collect)){ | ||
257 | + wrapper.apply("1!=1"); | ||
258 | + }else { | ||
259 | + wrapper.in(ProductDO::getId, collect); | ||
260 | + } | ||
261 | + }) | ||
244 | .eq(ProductDO::getIsmarketable, true) | 262 | .eq(ProductDO::getIsmarketable, true) |
245 | .select(ProductDO::getId) | 263 | .select(ProductDO::getId) |
246 | .page(new Page<>(1, 10 - productVO.getRelatedProductIds().size())).getRecords().stream() | 264 | .page(new Page<>(1, 10 - productVO.getRelatedProductIds().size())).getRecords().stream() |
@@ -248,13 +266,6 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductDO> im | @@ -248,13 +266,6 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductDO> im | ||
248 | productVO.getRelatedProductIds().addAll(records); | 266 | productVO.getRelatedProductIds().addAll(records); |
249 | } | 267 | } |
250 | 268 | ||
251 | -// List<JournalCategoryRelation> journalCategoryRelations = journalCategoryService.lambdaQuery() | ||
252 | -// .in(JournalCategoryRelation::getCategoryId, categoryIds) | ||
253 | -// .list(); | ||
254 | -// List<Long> journalIds = journalCategoryRelations.stream().map(JournalCategoryRelation::getJournalId).collect(Collectors.toList()); | ||
255 | -// List<Journal> journals = journalService.lambdaQuery() | ||
256 | -// .in(Journal::getId, journalIds) | ||
257 | -// .list(); | ||
258 | List<JournalCategoryRelation> journalCategoryRelations = null; | 269 | List<JournalCategoryRelation> journalCategoryRelations = null; |
259 | if (categoryIds != null && !categoryIds.isEmpty()) { | 270 | if (categoryIds != null && !categoryIds.isEmpty()) { |
260 | // 查询 journalCategoryRelations,仅在 categoryIds 不为空时执行 | 271 | // 查询 journalCategoryRelations,仅在 categoryIds 不为空时执行 |
shop/src/main/resources/application-test.yml
@@ -57,14 +57,14 @@ spring: | @@ -57,14 +57,14 @@ spring: | ||
57 | testWhileIdle: true | 57 | testWhileIdle: true |
58 | testOnBorrow: true | 58 | testOnBorrow: true |
59 | testOnReturn: true | 59 | testOnReturn: true |
60 | - password: canrd@2024 | 60 | + password: 123456 |
61 | time-between-eviction-runs-millis: 1000 | 61 | time-between-eviction-runs-millis: 1000 |
62 | - url: jdbc:mysql://39.108.227.113:3307/canrd_overseas?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true | 62 | + url: jdbc:mysql://192.168.31.242:13306/canrd_overseas?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true |
63 | username: root | 63 | username: root |
64 | 64 | ||
65 | 65 | ||
66 | -logging: | ||
67 | - config: classpath:log4j2-dev.xml | 66 | +#logging: |
67 | +# config: classpath:log4j2-dev.xml | ||
68 | 68 | ||
69 | 69 | ||
70 | static-html: | 70 | static-html: |
shop/src/main/resources/application.yml
@@ -8,3 +8,22 @@ spring: | @@ -8,3 +8,22 @@ spring: | ||
8 | throw-exception-if-no-handler-found: true | 8 | throw-exception-if-no-handler-found: true |
9 | resources: | 9 | resources: |
10 | add-mappings: false | 10 | add-mappings: false |
11 | + mail: | ||
12 | + host: smtp.mxhichina.com | ||
13 | + port: 465 | ||
14 | + username: overseas@canrd.com | ||
15 | + password: Canrd@overseas | ||
16 | + protocol: smtps | ||
17 | + properties: | ||
18 | + mail: | ||
19 | + smtp: | ||
20 | + auth: true | ||
21 | + starttls: | ||
22 | + enable: true | ||
23 | + required: true | ||
24 | + socketFactory: | ||
25 | + port: 465 | ||
26 | + class: javax.net.ssl.SSLSocketFactory | ||
27 | + | ||
28 | +mail: | ||
29 | + to: contact@canrd.com |
shop/src/test/java/com/canrd/shop/TranslateTest.java
@@ -16,12 +16,7 @@ import com.canrd.shop.module.dto.ProductCategoryDO; | @@ -16,12 +16,7 @@ import com.canrd.shop.module.dto.ProductCategoryDO; | ||
16 | import com.canrd.shop.module.dto.ProductDO; | 16 | import com.canrd.shop.module.dto.ProductDO; |
17 | import com.canrd.shop.module.dto.ProductFunctionDO; | 17 | import com.canrd.shop.module.dto.ProductFunctionDO; |
18 | import com.canrd.shop.module.dto.TicketTypeDO; | 18 | import com.canrd.shop.module.dto.TicketTypeDO; |
19 | -import com.canrd.shop.service.ProductAttributeMapStoreService; | ||
20 | -import com.canrd.shop.service.ProductAttributeService; | ||
21 | -import com.canrd.shop.service.ProductCategoryService; | ||
22 | -import com.canrd.shop.service.ProductFunctionService; | ||
23 | -import com.canrd.shop.service.ProductService; | ||
24 | -import com.canrd.shop.service.TicketTypeService; | 19 | +import com.canrd.shop.service.*; |
25 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
26 | import org.apache.commons.io.FileUtils; | 21 | import org.apache.commons.io.FileUtils; |
27 | import org.junit.Test; | 22 | import org.junit.Test; |
@@ -75,6 +70,14 @@ public class TranslateTest { | @@ -75,6 +70,14 @@ public class TranslateTest { | ||
75 | @Autowired | 70 | @Autowired |
76 | private ChatGptUtil chatGptUtil; | 71 | private ChatGptUtil chatGptUtil; |
77 | 72 | ||
73 | + @Autowired | ||
74 | + private IEmailService emailService; | ||
75 | + | ||
76 | + @Test | ||
77 | + public void translateProductAttributeMapStoreTest(){ | ||
78 | + emailService.sendText("zgt","2100047874@qq.com","test","测试一下"); | ||
79 | + return; | ||
80 | + } | ||
78 | @Test | 81 | @Test |
79 | public void translateTicketTypeTest(){ | 82 | public void translateTicketTypeTest(){ |
80 | List<TicketTypeDO> ticketTypeDOS = ticketTypeService.list(); | 83 | List<TicketTypeDO> ticketTypeDOS = ticketTypeService.list(); |
@@ -130,6 +133,7 @@ public class TranslateTest { | @@ -130,6 +133,7 @@ public class TranslateTest { | ||
130 | }); | 133 | }); |
131 | } | 134 | } |
132 | 135 | ||
136 | + | ||
133 | @Test | 137 | @Test |
134 | public void translateFunctionTest(){ | 138 | public void translateFunctionTest(){ |
135 | List<ProductFunctionDO> productFunctionDOS = productFunctionService.list(); | 139 | List<ProductFunctionDO> productFunctionDOS = productFunctionService.list(); |