异步调用
为了让@Async注解能够生效,还需要在Spring Boot的主程序中配置 @EnableAsync
@Async
public void doTaskOne() throws Exception {
// 同上内容,省略
}
异步回调
@Async
public Future<String> doTaskOne() throws Exception {
System.out.println("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");
return new AsyncResult<>("任务一完成");
}
log4j
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>
创建Spring Boot工程时,我们引入了spring-boot-starter,其中包含了spring-boot-starter-logging,该依赖内容就是Spring Boot默认的日志框架Logback,所以我们在引入log4j之前,需要先排除该包的依赖,再引入log4j的依赖
Spring Boot中对log4j进行多环境不同日志级别的控制
在log4j.properties文件中,以
属性替代levellog4j.category.com.cn=
{logging.level.com.cn}, file1
而日志级别可配置到不同环境的属性文件中
如在 application-dev.properties 配置 logging.level.com.cn=DEBUG
如在 application-test.properties 配置 logging.level.com.cn=INFO
AOP
引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
spring.aop.auto属性默认是开启的,也就是说只要引入了AOP依赖后,默认已经增加了@EnableAspectJAutoProxy
而当我们需要使用CGLIB来实现AOP的时候,需要配置spring.aop.proxy-target-class=true,不然默认使用的是标准Java的实现
实现AOP的切面主要有以下几个要素:
- 使用@Aspect注解将一个java类定义为切面类
- 使用@Pointcut定义一个切入点,可以是一个规则表达式,比如例中某个package下的所有函数,也可以是一个注解等
- 根据需要在切入点不同位置的切入内容
使用@Before在切入点开始处切入内容
使用@After在切入点结尾处切入内容
使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容
使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑
@Aspect
@Component
public class WebLogAspect {
private Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
@Pointcut("execution(public * com.hujha.spring.boot.demo1.web..*.*(..))")
public void webLog(){}
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
logger.info("URL : " + request.getRequestURL().toString());
logger.info("HTTP_METHOD : " + request.getMethod());
logger.info("IP : " + request.getRemoteAddr());
logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
}
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret) throws Throwable {
// 处理完请求,返回内容
logger.info("RESPONSE : " + ret);
}
}
@Order(i) 设置优先级
i的值越小,优先级越高
邮件支持
spring.mail.host=smtp.qq.com
spring.mail.username=999
spring.mail.password=999
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
package com.hujha.spring.boot.demo1;
import java.io.File;
import java.util.Map;
import javax.mail.internet.MimeMessage;
import org.apache.commons.collections.map.HashedMap;
import org.apache.velocity.app.VelocityEngine;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.ui.velocity.VelocityEngineUtils;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = StudBoot1Application.class)
public class ApplicationTests {
@Autowired
private JavaMailSender mailSender;
@Autowired
VelocityEngine velocityEngine;
@Test
public void sendSimpleMail() throws Exception {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("2323@qq.com");
message.setTo("2323@chanjet.com");
message.setSubject("主题:简单邮件");
message.setText("测试邮件内容");
mailSender.send(message);
}
@Test
public void sendAttachmentsMail() throws Exception {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom("2323@qq.com");
helper.setTo("2323@qq.com");
helper.setSubject("主题:有附件");
helper.setText("有附件的邮件");
FileSystemResource file = new FileSystemResource(new File("weixin.jpg"));
helper.addAttachment("附件-1.jpg", file);
helper.addAttachment("附件-2.jpg", file);
mailSender.send(mimeMessage);
}
@Test
public void sendInlineMail() throws Exception {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom("232@qq.com");
helper.setTo("23@qq.com");
helper.setSubject("主题:嵌入静态资源");
helper.setText("<html><body><img src=\"cid:weixin\" ></body></html>", true);
FileSystemResource file = new FileSystemResource(new File("weixin.jpg"));
helper.addInline("weixin", file);
mailSender.send(mimeMessage);
}
@Test
public void sendTemplateMail() throws Exception {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom("223@qq.com");
helper.setTo("23@qq.com");
helper.setSubject("主题:模板邮件");
Map<String, Object> model = new HashedMap();
model.put("username", "didi");
String text = VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine, "template.vm", "UTF-8", model);
helper.setText(text, true);
mailSender.send(mimeMessage);
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-velocity</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
模板template.vm:
<html>
<body>
<h3>你好, ${username}, 这是一封模板邮件!</h3>
</body>
</html>
事务
在声明事务时,只需要通过value属性指定配置的事务管理器名即可,例如:@Transactional(value=”transactionManagerPrimary”)。
除了指定不同的事务管理器之后,还能对事务进行隔离级别和传播行为的控制,下面分别详细解释:
@Transactional(isolation = Isolation.DEFAULT)
@Transactional(propagation = Propagation.REQUIRED)