diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..928d353 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,17 @@ + + + + + mysql.8 + true + com.mysql.cj.jdbc.Driver + jdbc:mysql://122.152.201.90:9912 + + + + + + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000..ba4dd71 --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 23331c7..263b13c 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,6 @@ 17 - 1.6.2 @@ -44,6 +43,16 @@ org.springframework.boot spring-boot-starter-mail + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.3 + + + com.mysql + mysql-connector-j + 8.3.0 + org.springframework.boot spring-boot-starter-thymeleaf @@ -59,8 +68,8 @@ com.sun.mail - javax.mail - ${mail.version} + jakarta.mail + 2.0.1 org.springframework.boot diff --git a/src/main/java/asia/yulinling/workflow/entity/User.java b/src/main/java/asia/yulinling/workflow/entity/User.java new file mode 100644 index 0000000..f1a2c4d --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/entity/User.java @@ -0,0 +1,77 @@ +package asia.yulinling.workflow.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +/** + *

+ * 用户实体类 + *

+ * + * @author yulinling + * @since 2025/6/4 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class User { + /** + * 主键id + */ + private Long id; + + /** + * 用户名 + */ + private String name; + + /** + * 加密后的密码 + */ + private String password; + + /** + * 加密使用盐 + */ + private String salt; + + /** + * 邮箱 + */ + private String email; + + /** + * 手机号 + */ + private String phone; + + /** + * 状态 -1:删除 0:警用 1:启用 + */ + private Integer status; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 上次登录时间 + */ + private Date lastLoginTime; + + /** + * 上次更新时间 + */ + private Date lastUpdateTime; +} diff --git a/src/main/java/asia/yulinling/workflow/mapper/UserMapper.java b/src/main/java/asia/yulinling/workflow/mapper/UserMapper.java new file mode 100644 index 0000000..5afb11c --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/mapper/UserMapper.java @@ -0,0 +1,55 @@ +package asia.yulinling.workflow.mapper; + +import asia.yulinling.workflow.entity.User; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + *

+ * 用户Mapper + *

+ * + * @author yulinling + * @since 2025/6/4 + */ +@Mapper +@Component +public interface UserMapper { + + /** + * 查询所有用户 + * + * @return 用户列表 + */ + @Select("SELECT * FROM orm_user") + List selectAllUser(); + + /** + * 根据id查询用户 + * + * @param id 主键id + * @return 当前id的用户,不存在则是{@code null} + */ + @Select("SELECT * FROM orm_user WHERE id = #{id}") + User selectUserById(@Param("id")Long id); + + /** + * 保存用户 + * + * @param user 用户 + * @return 成功 - {@code 1} 失败 - {@code 0} + */ + int saveUser(@Param("user") User user); + + /** + * 删除用户 + * + * @param id 主键id + * @return 成功 - {@code 1} 失败 - {@code 0} + */ + int deleteById(@Param("id")Long id); +} diff --git a/src/main/java/asia/yulinling/workflow/service/MailService.java b/src/main/java/asia/yulinling/workflow/service/MailService.java index 57f8cee..5caf3b5 100644 --- a/src/main/java/asia/yulinling/workflow/service/MailService.java +++ b/src/main/java/asia/yulinling/workflow/service/MailService.java @@ -1,6 +1,6 @@ package asia.yulinling.workflow.service; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; /** *

@@ -8,7 +8,7 @@ import javax.mail.MessagingException; *

* * @author yulinling - * @date Create in 2025/6/3 22:49 + * @since Create in 2025/6/3 22:49 */ public interface MailService { /** @@ -46,14 +46,15 @@ public interface MailService { void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) throws MessagingException; /** - * 发送带附件邮件 + * 发送正文带静态资源的邮件 * * @param to 收件人地址 * @param subject 邮件主题 * @param content 邮件内容 * @param rscPath 静态资源地址 + * @param rscId 静态资源id * @param cc 抄送地址 * @throws MessagingException 邮件发送异常 */ - void sendResourceMail(String to, String subject, String content, String rscPath, String... cc) throws MessagingException; + void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException; } diff --git a/src/main/java/asia/yulinling/workflow/service/impl/MailServiceImpl.java b/src/main/java/asia/yulinling/workflow/service/impl/MailServiceImpl.java index 5a3046b..4e34dfa 100644 --- a/src/main/java/asia/yulinling/workflow/service/impl/MailServiceImpl.java +++ b/src/main/java/asia/yulinling/workflow/service/impl/MailServiceImpl.java @@ -4,11 +4,15 @@ import asia.yulinling.workflow.service.MailService; import cn.hutool.core.util.ArrayUtil; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; -import javax.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; +import jakarta.mail.MessagingException; +import java.io.File; /** *

@@ -36,6 +40,7 @@ public class MailServiceImpl implements MailService { @Override public void sendSimpleMail(String to, String subject, String content, String... cc) { SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(from); message.setTo(to); message.setSubject(subject); @@ -43,6 +48,7 @@ public class MailServiceImpl implements MailService { if (ArrayUtil.isNotEmpty(cc)) { message.setCc(cc); } + mailSender.send(message); } @@ -57,7 +63,18 @@ public class MailServiceImpl implements MailService { */ @Override public void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + if (ArrayUtil.isNotEmpty(cc)) { + helper.setCc(cc); + } + + mailSender.send(message); } /** @@ -72,21 +89,47 @@ public class MailServiceImpl implements MailService { */ @Override public void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) throws MessagingException { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + if (ArrayUtil.isNotEmpty(cc)) { + helper.setCc(cc); + } + FileSystemResource file = new FileSystemResource(new File(filePath)); + helper.addAttachment(file.getFilename(), file); + + mailSender.send(message); } /** - * 发送带附件邮件 + * 发送正文带静态资源的邮件 * * @param to 收件人地址 * @param subject 邮件主题 * @param content 邮件内容 * @param rscPath 静态资源地址 + * @param rscId 静态资源id * @param cc 抄送地址 * @throws MessagingException 邮件发送异常 */ - @Override - public void sendResourceMail(String to, String subject, String content, String rscPath, String... cc) throws MessagingException { + public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + if (ArrayUtil.isNotEmpty(cc)) { + helper.setCc(cc); + } + FileSystemResource file = new FileSystemResource(new File(rscPath)); + helper.addAttachment(rscId, file); + + mailSender.send(message); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1285551..97ee4a3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,33 @@ + +# mysql?? +spring.datasource.url=jdbc:mysql://122.152.201.90:9912/workflow?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8 +spring.datasource.username=root +spring.datasource.password=0andrx +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.sql.init.mode=always +spring.sql.init.continue-on-error=true +spring.sql.init.schema-locations=classpath:db/schema.sql +spring.sql.init.data-locations=classpath:db/data.sql +# ????? +spring.datasource.hikari.minimum-idle=5 +spring.datasource.hikari.connection-test-query=SELECT 1 +spring.datasource.hikari.maximum-pool-size=20 +spring.datasource.hikari.auto-commit=true +spring.datasource.hikari.idle-timeout=30000 +spring.datasource.hikari.pool-name=MyAppHikariCP +spring.datasource.hikari.max-lifetime=300000 +spring.datasource.hikari.connection-timeout=30000 + +# mybatis?? +mybatis.configuration.map-underscore-to-camel-case=true +mybatis.mapper-locations=classpath:mapper/*.xml +mybatis.type-aliases-package=asia/yulinling/workflow/entity + +# log?? +logging.level.asia.yulinling=debug +logging.level.asia.yulinling.workflow.mapper=trace + +# mail?? spring.mail.host=smtp.qq.com spring.mail.port=587 spring.mail.username=2712495353@qq.com diff --git a/src/main/resources/db/data.sql b/src/main/resources/db/data.sql new file mode 100644 index 0000000..405ab59 --- /dev/null +++ b/src/main/resources/db/data.sql @@ -0,0 +1,2 @@ +INSERT INTO `orm_user`(`id`,`name`,`password`,`salt`,`email`,`phone`) VALUES (1, 'user_1', 'ff342e862e7c3285cdc07e56d6b8973b', '412365a109674b2dbb1981ed561a4c70', 'user1@xkcoding.com', '17300000001'); +INSERT INTO `orm_user`(`id`,`name`,`password`,`salt`,`email`,`phone`) VALUES (2, 'user_2', '6c6bf02c8d5d3d128f34b1700cb1e32c', 'fcbdd0e8a9404a5585ea4e01d0e4d7a0', 'user2@xkcoding.com', '17300000002'); \ No newline at end of file diff --git a/src/main/resources/db/schema.sql b/src/main/resources/db/schema.sql new file mode 100644 index 0000000..e2abd42 --- /dev/null +++ b/src/main/resources/db/schema.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `orm_user`; +CREATE TABLE `orm_user` ( + `id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键', + `name` VARCHAR(32) NOT NULL UNIQUE COMMENT '用户名', + `password` VARCHAR(32) NOT NULL COMMENT '加密后的密码', + `salt` VARCHAR(32) NOT NULL COMMENT '加密使用的盐', + `email` VARCHAR(32) NOT NULL UNIQUE COMMENT '邮箱', + `phone` VARCHAR(15) NOT NULL UNIQUE COMMENT '手机号码', + `status` INT(2) NOT NULL DEFAULT 1 COMMENT '状态,-1:逻辑删除,0:禁用,1:启用', + `create_time` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间', + `last_login_time` DATETIME DEFAULT NULL COMMENT '上次登录时间', + `last_update_time` DATETIME NOT NULL DEFAULT NOW() COMMENT '上次更新时间' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Spring Boot Demo Orm 系列示例表'; diff --git a/src/main/resources/email/test.html b/src/main/resources/email/test.html new file mode 100644 index 0000000..6d3140b --- /dev/null +++ b/src/main/resources/email/test.html @@ -0,0 +1,22 @@ + + + + + Test Title + + +

+

+ 欢迎使用 TEST HTML + - Powered By +

+ + + + Spring Boot入门首选 + + + +
+ + \ No newline at end of file diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..ce88300 --- /dev/null +++ b/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,28 @@ + + + + + INSERT INTO `orm_user` (`name`, + `password`, + `salt`, + `email`, + `phone`, + `status`, + `create_time`, + `last_login_time`, + `last_update_time`) + VALUES (#{user.name}, + #{user.password}, + #{user.salt}, + #{user.email}, + #{user.phone}, + #{user.status}, + #{user.createTime}, + #{user.lastLoginTime}, + #{user.lastUpdateTime}) + + + + DELETE FROM `orm_user` WHERE id = #{id} + + \ No newline at end of file diff --git a/src/main/resources/static/GitHub.ico b/src/main/resources/static/GitHub.ico new file mode 100644 index 0000000..f220ff0 Binary files /dev/null and b/src/main/resources/static/GitHub.ico differ diff --git a/src/main/resources/templates/welcome.html b/src/main/resources/templates/welcome.html new file mode 100644 index 0000000..8cb8bd9 --- /dev/null +++ b/src/main/resources/templates/welcome.html @@ -0,0 +1,22 @@ + + + + + Title + + +
+

+ 欢迎使用 + - Powered By +

+ + + + Spring Boot入门首选 + + + +
+ + \ No newline at end of file diff --git a/src/test/java/asia/yulinling/workflow/mapper/UserMapperTest.java b/src/test/java/asia/yulinling/workflow/mapper/UserMapperTest.java new file mode 100644 index 0000000..a4892f6 --- /dev/null +++ b/src/test/java/asia/yulinling/workflow/mapper/UserMapperTest.java @@ -0,0 +1,73 @@ +package asia.yulinling.workflow.mapper; + +import asia.yulinling.workflow.WorkFlowMainTests; +import asia.yulinling.workflow.entity.User; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.IdUtil; +import cn.hutool.crypto.SecureUtil; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 用户Mapper测试 + *

+ * + * @author yulinling + * @since 2025/6/4 + */ +@Slf4j +public class UserMapperTest extends WorkFlowMainTests { + @Autowired + private UserMapper userMapper; + + @Test + public void selectAllUser() { + List users = userMapper.selectAllUser(); + Assert.assertTrue(CollUtil.isNotEmpty(users)); + log.info("users={}", users); + } + + @Test + public void selectUserById() { + User user = userMapper.selectUserById(1L); + Assert.assertNotNull(user); + log.info("user={}", user); + } + + @Test + @Transactional + @Rollback + public void saveUser() { + String salt = IdUtil.simpleUUID(); + User user = User.builder() + .name("yulinling_test") + .password(SecureUtil.md5("123456" + salt)) + .salt(salt) + .email("2712495353@qq.com") + .phone("17770898274") + .status(1) + .lastLoginTime(new DateTime()) + .createTime(new DateTime()) + .lastUpdateTime(new DateTime()) + .build(); + + int i = userMapper.saveUser(user); + Assert.assertEquals(1, i); + } + + @Test + @Transactional + @Rollback + public void deleteById() { + int i = userMapper.deleteById(1L); + Assert.assertEquals(1, i); + } +} diff --git a/src/test/java/asia/yulinling/workflow/service/EmailServiceTest.java b/src/test/java/asia/yulinling/workflow/service/EmailServiceTest.java new file mode 100644 index 0000000..01d5e00 --- /dev/null +++ b/src/test/java/asia/yulinling/workflow/service/EmailServiceTest.java @@ -0,0 +1,101 @@ +package asia.yulinling.workflow.service; + +import asia.yulinling.workflow.WorkFlowMainTests; +import cn.hutool.core.io.resource.ResourceUtil; +import jakarta.mail.MessagingException; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.thymeleaf.context.Context; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver; + +import java.net.URL; + +/** + *

+ * 邮件测试 + *

+ * + * @author yulinling + * @date 2025/6/4 + */ +public class EmailServiceTest extends WorkFlowMainTests { + @Autowired + private MailService mailService; + @Autowired + private TemplateEngine templateEngine; + @Autowired + private ApplicationContext applicationContext; + + /** + * 测试简单邮件 + */ + @Test + public void sendSimpleMail() { + mailService.sendSimpleMail("rsgltzyd@hotmail.com", "test", "test content"); + } + + /** + * 测试发送HTML邮件 + * + * @throws MessagingException 邮件异常 + */ + @Test + public void sendHtmlMail() throws MessagingException { + Context context = new Context(); + context.setVariable("project", "mail test"); + context.setVariable("author", "yulinlng"); + context.setVariable("url", "https://github.com/xkcoding/spring-boot-demo"); + + String emailTemplate = templateEngine.process("welcome", context); + + mailService.sendHtmlMail("rsgltzyd@hotmail.com", "test", emailTemplate); + } + + /** + * 测试自定义模板HTML邮件 + * + * @throws MessagingException 邮件异常 + */ + @Test + public void sendHtmlMail2() throws MessagingException { + + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setCacheable(false); + resolver.setPrefix("classpath:/email/"); + resolver.setSuffix(".html"); + + templateEngine.setTemplateResolver(resolver); + + Context context = new Context(); + context.setVariable("project", "mail test"); + context.setVariable("author", "yulinlng"); + context.setVariable("url", "https://github.com/xkcoding/spring-boot-demo"); + + String emailTemplate = templateEngine.process("test", context); + + mailService.sendHtmlMail("rsgltzyd@hotmail.com", "test", emailTemplate); + } + + /** + * 测试附件邮件 + * + * @throws MessagingException + */ + @Test + public void sendAttachmentsMail() throws MessagingException { + URL resource = ResourceUtil.getResource("static/GitHub.ico"); + mailService.sendAttachmentsMail("rsgltzyd@hotmail.com", "test", "邮件中有附件,请注意查收", resource.getPath()); + } + + @Test + public void sendResourceMail() throws MessagingException { + String rscId = "rscId"; + String content = ""; + URL resource = ResourceUtil.getResource("static/GitHub.ico"); + + mailService.sendResourceMail("rsgltzyd@hotmail.com", "test", content, resource.getPath(), rscId); + } +}