目标:
1:springboot 整合 mail
2: mail 使用freemark 实现模板动态生成(就是通过字符串生成模板,不需要在工程中写入固定模板)
3: springboot 整合aop 实现日志记录
4:使用工厂模式 处理调度不同的邮件类型
5:实现异步 发送,
6:失败 三次重试
Configuration configuration = String templateString = "" + "" StringTemplateLoader templateLoader = templateLoader.putTemplate("template", templateString); Template template = configuration.getTemplate("template", "utf-8" Map
这个是邮件的目录以及设计思路(各个类的作用)
1 然后就贴点有意思的代码 2 3 异步 4 import java.util.concurrent.Executor; 5 import java.util.concurrent.ThreadPoolExecutor; 6 7 import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.context.annotation.Configuration;10 import org.springframework.scheduling.annotation.AsyncConfigurer;11 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;12 13 @Configuration14 public class ThreadPoolTaskConfig implements AsyncConfigurer {15 16 @Bean("taskExecutor")17 @Override18 public Executor getAsyncExecutor() {19 ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();20 threadPoolTaskExecutor.setQueueCapacity(200); // ‘队列容量21 threadPoolTaskExecutor.setCorePoolSize(5); // ’核心线程数量22 threadPoolTaskExecutor.setMaxPoolSize(100); // ‘最大线程数量23 threadPoolTaskExecutor.setKeepAliveSeconds(300); // ’允许线程空闲时间24 // ’用于被拒绝任务的处理程序,它直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务25 threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());26 threadPoolTaskExecutor.initialize(); // ‘重新初始化27 return threadPoolTaskExecutor;28 }29 30 @Override31 public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {32 // TODO Auto-generated method stub33 return null;34 }35 36 }37 38 异步的使用39 @Async("taskExecutor")40 public void sendMail(Integer templateId, String subject, String mailType, String to, String cc,41 Map mailTemplateParam, String attachmentFilename, DataSource dataSource) {42 43 }
1 aop 2 3 这是依赖 4 5 org.springframework.boot 6 spring-boot-starter-aop 7 8 9 这是注解开启10 @EnableAspectJAutoProxy11 12 这是配置13 spring.aop.auto=true14 15 这是注解声明16 import java.lang.annotation.Documented;17 import java.lang.annotation.ElementType;18 import java.lang.annotation.Retention;19 import java.lang.annotation.RetentionPolicy;20 import java.lang.annotation.Target;21 22 @Target({ ElementType.METHOD, ElementType.TYPE })23 @Retention(RetentionPolicy.RUNTIME)24 @Documented25 public @interface MailSendLog {26 27 }28 29 这是注解的实现也就切面30 31 import java.lang.reflect.Method;32 import java.security.Principal;33 import java.util.Date;34 import java.util.HashMap;35 import java.util.Map;36 37 import javax.annotation.Resource;38 import javax.servlet.http.HttpServletRequest;39 40 import org.aspectj.lang.JoinPoint;41 import org.aspectj.lang.ProceedingJoinPoint;42 import org.aspectj.lang.annotation.Around;43 import org.aspectj.lang.annotation.Aspect;44 import org.aspectj.lang.annotation.Before;45 import org.aspectj.lang.annotation.Pointcut;46 import org.aspectj.lang.reflect.MethodSignature;47 import org.springframework.core.DefaultParameterNameDiscoverer;48 import org.springframework.core.ParameterNameDiscoverer;49 import org.springframework.stereotype.Component;50 51 import com.sony.sie.hrevaluate.model.MailSendLogModel;52 import com.sony.sie.hrevaluate.service.MailSendLogService;53 54 @Aspect55 @Component56 public class MailSendLogAspect {57 58 //这是切点 是声明的绝对路径59 @Pointcut("@annotation(com.sony.sie.hrevaluate.mail.annotation.MailSendLog)")60 public void annotationPointCut() {61 62 }63 64 //这是注解增强65 @Around("annotationPointCut()")66 public void Around(ProceedingJoinPoint joinPoint) throws Throwable {67 saveMailSendLog(joinPoint);68 }69 70 //这里写一个和切点相关的工具类,可以获取方法中的参数,反射的原理71 private void saveMailSendLog(ProceedingJoinPoint joinPoint) throws Throwable {72 /*73 * mail sender74 */75 String sender = "";76 77 /**78 * mail send result79 */80 String res = (String) joinPoint.proceed();81 82 /*83 * mail parameter84 */85 Object[] args = joinPoint.getArgs();86 ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();87 MethodSignature signature = (MethodSignature) joinPoint.getSignature();88 Method method = signature.getMethod();89 String[] parameterNames = pnd.getParameterNames(method);90 MapparamMap = new HashMap<>(32);91 for (int i = 0; i < parameterNames.length; i++) {92 paramMap.put(parameterNames[i], args[i]);93 }94 }
备注1:本来想使用策略模式的,但是策略模式需要借助接口才能实现,所以就用了抽象类,实现工厂模式2:失败重试三次就是用do while 控制3:从方法到异步方法也是需要时间的,尽量提前点4:整合freemark实现动态生成模板的核心已经写了,至于整合freemark网上很多就啰嗦啦5:下一步整合定时任务再配合邮件做一个完整的模块