pringBoot使用Thymeleaf模板(2019-09-25)
2017年的时候就接触了SpringBoot,但是从接触之初到最近基本是没有用过Thymeleaf的,一方面自己觉得SpringBoot单纯用作接口开发就行了,另一方面自己也略懂前端,通常会用静态Html或者Vue和Angular来做一些小测试。
但是最近因为在做自己个人网站,其中一个模块是项目展示,准备展示的第一个项目就是邮件的发送,邮件发送的接口很早之前就封装过,剩下就是页面了,一开始想的是写html通过ajax访问接口,但是数据渲染又很麻烦,要通过JQ去渲染,而如果通过Vue,我又觉得太麻烦,搭建Vue,配置代理,压缩打包文件等等,所以感觉给自己造成挺大的负担,于是想到Thymeleaf这个模板,在网上搜索一些知识,就决定结合Thymeleaf来做邮件项目的页面,这样数据输出页面可以使用模板的表达式,相比纯html的数据渲染要简单,相比Vue又不那么重。
其使用方言很简单,通过th:text="..."就可以对后端返回数据进行渲染。
而且其表达式语法有五种类型
${...} : 变量表达式。 *{...} : 选择表达式。 #{...} : 消息 (i18n) 表达式。 @{...} : 链接 (URL) 表达式。 ~{...} : 片段表达式。
其他相关概念可以去网上看Thymeleaf教程,下面说一下SpringBoot使用Thymeleaf模板的过程
关于Thymeleaf的原理简单的说就是通过Controller找到响应的模板文件,然后根据模板表达式算法把 Controller 输出的对象匹配到模板表达式中,从而展示了页面。
使用的过程挺简单:
首先引入依赖
<!--引入thymeleaf的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
然后修改配置文件(如果你习惯空格再换行,那就注意下面的注释)
# 默认路径,注意不能少反斜杠,也不能在反斜杠后面多一些空格 spring.thymeleaf.prefix=classpath:/templates/ # 后缀 spring.thymeleaf.suffix=.html # 缓存 spring.thymeleaf.cache=false
template下建立index.html,然后书写Controller
项目名称:01-spring-boot-MVC
@SpringBootApplication 用在 SpringBoot 项目的启动程序上,整个 SpringBoot 只有且必须有一个这样的注解,是项目的入口程序。
如下代码所示:
源代码:src/main/java/com/springboot/codingstudty/MainApplication.java
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run (Demo01Application.class, args);
}
}
复制代码
@SpringBootApplication 是以下 3 个注解的整合:
@Configuration
@EnableAutoConfiguration
@ComponentScan
复制代码
@SpringBootApplication 同等于这 3 个注解,以上清单也有介绍。
@Controller 是让 URL 请求返回具体的页面,如返回 html、jsp 页面等。这个注解在类头上添加。
如下是“http://localhost 跳转到 index.html”示例,需要 3 步骤完成。
(1)要让 SpringBoot 中能访问到 HTML、JSP 等页面,需要在 application.properties 配置
源代码:src/main/resources/application.properties
#默认找到 static 下,只需如下配置即可:
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
复制代码
(2)在 static 下创建 index.html
源代码:src/main/resources/static/index.html
<div>
<h3>首页</h3>
<div>首页的内容。。。。。</div>
</div>
复制代码
(3)编写 CodingStudyIndexController 控制器
源代码:
src/main/java/com/springboot/codingstudty/controller/CodingStudyIndexController.java
@Controller
public class CodingStudyIndexController {
}
复制代码
(4)配合@RequestMapping 进行具体页面跳转控制:
跳转到 index.html 页面
源代码:
src/main/java/com/springboot/codingstudty/controller/CodingStudyIndexController.java
/**
* 没有数据渲染的返回
* @return
*/
@RequestMapping("/")
public String index01() {
return "index";
}
复制代码
注意:Controller 数据渲染到页面上需要返回 ModelAndView 类型,如下:
源代码:
src/main/java/com/springboot/codingstudty/controller/CodingStudyIndexController.java
/**
* 返回 ModelAndView
* 通过 ModelAndView 可以带入数据,并渲染到页面
* @return
*/
@RequestMapping("/index")
public ModelAndView index(){
ModelAndView modelAndView=new ModelAndView ();
//可以设置数据
String data="这个数据来自 IndexController...";
modelAndView.addObject("data",data);
//跳转到 index.html 页面
modelAndView.setViewName ("index");
return modelAndView;
}
复制代码
此时,在 index.html 页面获取 data 数据,有多种方案。
由于第一种方案的语法简单,使用频率高,下面简单说第一种方案。
在 pom.xml 中引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
复制代码
在 application.properties 配置:
##################freemarker 模板配置
#后缀
spring.freemarker.suffix=.html
#默认在 templates 下
spring.freemarker.template-loader-path=classpath:/static/
#req 访问 request
spring.freemarker.request-context-attribute=req
spring.freemarker.content-type=text/html
spring.freemarker.enabled=true
复制代码
这样配置之后,在 index.html 中获取 data 数据的代码是:
<div>
<h3>首页</h3>
<div>首页的内容.${data}</div>
</div>
复制代码
由于本章重点不是介绍 freemarker 如何使用,这里点到为止。
还有一些注意的地方:让@Controller 能找到页面的前提是需要配置路径,配置映射 HTML页面有多种方案,下面介绍四种方案:
1)默认放在 static 下:
#映射 html 页面
#========1、默认===============================#默认找到 static 下,只需如下配置即可:
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
复制代码
2)指向新的路径,如 views 路径下
#当然可以改变 static-locations 映射路径,如下:
#========2、会在 views 下找文件====================spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
spring.resources.static-locations=classpath:/views/
复制代码
3)指向新的路劲,如 public 路径下
#========3、会在 public 下找文件====================spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
spring.resources.static-locations=classpath:/public/
复制代码
4)指向新的路劲,如 ENTA-INF/resource 下
#========4、会在/META-INF/resources/下找文件======spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
spring.resources.static-locations=classpath:/META-INF/resources/
复制代码
不管怎么设置,以上路径必须在 src/main/resource 下.
@RestController 是 新 增 的 注 解 , 是 @Controller 和 @ResponseBody 组 合 。
@RestController 注解后,其方法内再配合@RequestMapping,即可返回 Json 格式的数据。
(1) 新建 CodingStudyRestController 控制器:
源代码:
src/main/java/com/springboot/codingstudty/controller/CodingStudyRestController.java
@RestController
public class CodingStudyRestController {
/**
* 假设是获取用户信息
* @return
*/
@GetMapping("user")
public Map<String,Object> getUser() {
//模拟一个用户
Map<String,Object> user=new HashMap<>();
user.put ("id",1);
user.put ("name","张三");
user.put ("age",18);
//返回这个用户
return user;
}
}
复制代码
运行结果:
@RequestMapping 注解要在 Controller 控制器中的方法头使用,如下:
源代码:src/main/java/com/springboot/codingstudty/controller/CodingStudyIndexController.java
@RequestMapping("/index")
public ModelAndView index(){
ModelAndView modelAndView=new ModelAndView ();
//可以设置数据
String data="这个数据来自 IndexController...";
modelAndView.addObject("data",data);
//跳转到 index.html 页面
modelAndView.setViewName ("index");
return modelAndView;
}
复制代码
Spring Boot 有 GetMapping、PostMapping、PutMapping、DeleteMapping 代替它。
在参数前面设置,格式是:
@RequestParam(value=“变量名”, required=true/false, defaultVale=默认值 )
复制代码
设置 required=false
举例,新建 RequestParamController 控制器:
源代码:
src/main/java/com/springboot/codingstudty/controller/RequestParamController.java
@GetMapping("param")
public String param(
@RequestParam("id") String id,
@RequestParam(value="name", required=false) String name,
@RequestParam(value="age", required=false) int age){
String data="";
try {
//返回ID,NAME,age
data="id=" + id + ",name=" + name + ",age=" + age;
} catch (Exceptione){
data=e.getMessage();
}
return data;
}
复制代码
第一参数:如下 url 必须有 id 这个参数,否则报错(即:?id=1)。
@RequestParam("id") String id
复制代码
第二个参数:如下 url 可以没有 userName 这个参数,请求不报错。
@RequestParam(value="userName", required=false) String userName
复制代码
第三个参数:如下设置 required=false,age 不传值,此时 age 等于 null,因 int 是基础类型不能接收 null 所以报错,所以一般可以使用 Integer 声明,避免错误。
@RequestParam(value="age", required=false) int age
复制代码
运行结果:
新建 PathVariableController 控制器类。
源代码:
src/main/java/com/springboot/codingstudty/controller/PathVariableController.java
在参数前面设置,格式是:
@PathVariable(value=“变量名”, required=true/false)
复制代码
抛出异常(可选配置)
具体方法:
@GetMapping("path/{id}/{name}")
public String pathVar(
@PathVariable("id") String id,
@PathVariable(value="name",required=false) String userName){
return "id="+id+",userName="+userName;
}
复制代码
传递参数:如:http://localhost:8086/path/1/张三
注意:请求路径必须是完整,否则报错。
运行结果
以下@GetMapping、@PostMapping、@PutMapping、@DeleteMapping 测试示例,新建一个控制器类:UserController
源代码:
src/main/java/com/springboot/codingstudty/controller/UserController.java
@GetMapping 是一个组合注解,是@RequestMapping(method=RequestMethod.GET)的缩写,只接收前端 get 请求。
@GetMapping
public Map<String,Object> getUser() {
Map<String,Object> user=new HashMap<>();
user.put("id",1);
user.put("name","ming206");
return user;
}
复制代码
@PostMapping 是一个组合注解,是@RequestMapping(method=RequestMethod.POST)的缩写,只接收前端 post 提交,一般用于数据的新增。
@PostMapping
public boolean insert(@RequestBody User user) {
//insert ...
return true;
}
复制代码
@PutMapping 是一个组合注解,是@RequestMapping(method=RequestMethod.PUT)的缩写,只接收前端 PUT 提交,一般用于数据的修改。
@PutMapping
public boolean update(@RequestBody User user) {
//update .....
return true;
}
复制代码
@DeleteMapping 是一个组合注解,是@RequestMapping(method=RequestMethod.DELETE)的缩写,只接收前端 DELETE 提交,用于数据删除。
@DeleteMapping
public boolean del(@PathVariable("id") String id) {
System.out.println(id);
//delete ....
return true;
}
复制代码
@ResponseBody 注解通常使用在控制层(controller)的方法上,其作用是将方法的返回值以特定的格式写入到 response 的 body 区域,进而将数据返回给客户端。当方法上面没有写 ResponseBody,底层会将方法的返回值封装为 ModelAndView 对象。
在 Spring Boot 的@RestController 中就不需要再加这个注解了,上面提到@RestController是@controller 和@ResponseBody 的组合,请阅读 RestController。
如下是在@Controller 修饰的类(控制器类)里的方法体前面加这个注解:
源代码:src/main/java/com/springboot/codingstudty/controller/UserViewController.java
@GetMapping("json")
@ResponseBody
public Map<String,Object> getJson(){
//模拟一个用户
Map<String,Object> user=new HashMap<> ();
user.put ("id",100);
user.put("name","ResponseBody");
user.put("age",25);
//返回这个用户
return user;
}
复制代码
运行结果:
@RequestBody 主要用来接收前端传递给后端的 json 字符串中的数据的(请求体中的数据的);GET 方式无请求体,所以使用@RequestBody 接收数据时,前端不能使用 GET 方式提交数据,而是用 POST 方式进行提交。
在后端的同一个接收方法里,@RequestBody 与@RequestParam()可以同时使用,@RequestBody 最多只能有一个,而@RequestParam()可以有多个。
举例:
源代码:src/main/java/com/springboot/codingstudty/controller/UserController.java
@PutMapping
public boolean update(@RequestBody User user) {
//update .....
return true;
}
@PostMapping("save")
public String save(
@RequestParam("id") String id,
@RequestParam(value="age", required=false) int age,
@RequestBody User user){
return "id="+id+",age="+age+"。user 对象==>"+user.toString ();
}
复制代码
User 模型:
@Data
public class User {
int id;
String name;
String age;
}
复制代码
运行结果:
以上 API 测试工具是 PostMan
前后端分离之后前端 Ajax 请求后端经常碰到的问题就是跨域问题。可以有多种方式解决这个问题,下面介绍 2 个解决方法:
方法 1:在方法头加@CrossOrigin 注解
@GetMapping("isCheck")
@CrossOrigin
public R<List<Resource>> selectAll(@RequestParam("ids") String ids) {
return R.ok (this.resourceService.getListByIds (ids));
}
复制代码
方法 2:使用过滤器设置:
源代码: src/main/java/com/springboot/codingstudty/configuration/AccessControlAllowOriginFilter.java
package com.springboot.codingstudty.configuration;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 解决跨域问题
*/
@Configuration
public class AccessControlAllowOriginFilter implements Filter {
@Override
public void doFilter( ServletRequest req,
ServletResponse res,
FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response=(HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(req, response);
}
public void init(FilterConfig filterConfig) {
System.out.println("初始化配置......");
}
public void destroy() {
System.out.println("销毁......");
}
}
复制代码
@Configuration 是定义配置类,一般在该类内部通过@bean 注册,也就是说将来在调用时,不需要手工 new。下面我们按照 3 步骤试一试。
(1)定义一个类,这是一个普通类。
源代码:src/main/java/com/springboot/codingstudty/configuration/UserAction.java
public class UserAction {
public String display(){
return "执行 UserAction display.... ";
}
}
复制代码
(2)定义配置类,并注册 bean
源代码:src/main/java/com/springboot/codingstudty/configuration/MyConfiguration.java
@Configuration
public class MyConfiguration {
//默认
@Bean
UserAction userAction(){
System.out.println ("默认名字是 userAction");
return new UserAction();
}
//……
}
复制代码
注意:
(3) 调用 UserAction 类
在 Controller 类上调用测试。注意不管在哪里调用,最终运行必须依赖于 Spring 容器,否则是运行不了的。例如在普通的 main 方法中是报空指针异常的,但是在 Controller、Test测试类上是可以的,因为它们的环境都是依赖于 Spring 容器。
调用时在变量上加注解@Autowired,即可取到 bean 实例。
创建 UserActionController 类
源代码:
src/main/java/com/springboot/codingstudty/controller/UserActionController.java
//加了 Autowired 注解后,不需要 new 对象
@Autowired
UserAction userAction;
@GetMapping("user/display")
public String getDisplay() {
return userAction.display();
}
复制代码
在浏览器端请求打印效果:
也可以手工编写获取 bean 的方法,下面新建一个类,CreateBean 类
源代码:src/main/java/com/springboot/codingstudty/configuration/CreateBean.java
@Component
public class CreateBean implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {this.applicationContext=applicationContext;}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}
复制代码
此时,在 UserActionController 内调用:
源代码:src/main/java/com/springboot/codingstudty/controller/UserActionController.java
@Autowired
CallBean callBean;
@GetMapping("user/display2")
public String getDisplay2(){
//注册 bean 时的名字,是一个字符串
String beanName="userAction";
UserAction userAction=callBean.getApplicationContext ()
.getBean (beanName,UserAction.class);
String msg=userAction.display ();
return "手工获取 bean==》"+msg;
}
复制代码
在浏览器端请求打印效果:
以上已经多次使用到@Bean 注解,这里就不多介绍了,直接上示例吧。
(1)默认注册 bean,以上的代码也有,如下
源代码:src/main/java/com/springboot/codingstudty/configuration/MyConfiguration.java
//默认
@Bean
UserAction userAction(){
System.out.println ("默认名字是 userAction");
return new UserAction();
}
复制代码
(2)指定一个 bean 名字
源代码:src/main/java/com/springboot/codingstudty/configuration/MyConfiguration.java
@Bean(value="userAction1")
UserAction userAction1(){
System.out.println ("名字为 userAction1");
return new UserAction();
}
复制代码
(3)调用是制定 bean 的名字
源代码:src/main/java/com/springboot/codingstudty/controller/UserActionController.java
用@Resource
@Resource(name="userAction1")
UserAction userAction;
复制代码
或@Autowired+@Qualifier
@Autowired
@Qualifier(value="userAction1")
UserAction userAction;
复制代码
用于修饰 service 层的组件,标注在类上。注意不是标在接口上。
/**
* 描述:service 层
* @author ming
*/
@Service
public class UserService {
//TODO
}
复制代码
之后,调用时和用@Bean 注册是一样用@Autowired 即可。
用@Service 标注的类一般都是明确是业务服务层,从业务角度清晰的划分。
@component 和@Service 没有本质的区别,@Service 内部还是去引用了@component,他们是没有什么区别的。
业务无法明确划分或不能归类清晰时,对该功能进行组件封装,并希望交给 IOC 管理,这时候用@component 注解。@component 和@Service 仅仅是从业务功能上有所划分,他们的本质都是“把对象的生命周期交给 IOC 管理”的目的。
例如下面这个示例,使用@component 注解
源代码:src/main/java/com/springboot/codingstudty/configuration/CreateBean.java
@Component
public class CreateBean implements ApplicationContextAware {
//……
}
复制代码
@Repository 和@Controller、@Service、@Component 的作用差不多,都是把对象交给 IOC管理。@Repository 用在持久层的接口上,这个注解是将接口的一个实现类交给 spring 管理,使用了@Repository 注解后,就具备可以将原生的数据库异常转为 Spring 处理得异常。
有两个地方需要这个注解,在普通的 Spring 项目中的持久层和在使用 JPA 时的接口上使用,在 Spring Boot 项目中更多的是使用在 JPA 接口上。
在 JPA 接口上的使用如下:
/**
* 描述:dao 层
* @author ming
*/
@Repository
public interface UserDao extends JpaRepository<User,String>{
//TODO
}
复制代码
有时候不用@Repository 来注解,也可以得到这个接口的实现类,有几个原因:
例如使用 SSM 框架时候,经常在 Dao 层注入@Mapper 即可(这时候需要引入 MyBatis 或者 MyBatisPlus 依赖包)。
在上面提到多次@Autowired,是用来“new 实例”的。加了该注解的对象直接调用即可,无需手工 new 对象。
//注意,加了@Autowired 就相当于 new UserAction
@Autowired
UserAction userAction;
复制代码
当多个同类型 bean 时,可以这样使用@Resource,如下介绍.
用@Resource 和@Autowired 类似
@Resource(name="userAction1")
UserAction userAction;
复制代码
@Autowired+@Qualifier
@Autowired
@Qualifier(value="userAction1")
UserAction userAction;
复制代码
@Value 是获取 application.properties 中的配置信息,例如 application.properties 中有相关的配置如下:
(1)application.properties:
server.port=8086
spring.datasource.url=jdbc:mysql://localhost:3309/db01
复制代码
(2)用@Value 取值
新建控制器类 ValueController
源代码:src/main/java/com/springboot/codingstudty/controller/ValueController.java
@RestController
public class ValueController {
@Value("${server.port}")
public String port;
public static String DATA_SOURCE_URL;
/**
* @value 给静态变量赋值,需要增加 set 方法
* 方法名称和参数可任意。
* @param val
*/
@Value ("${spring.datasource.url}")
public void setDataSourceUrl(String val){
DATA_SOURCE_URL=val;
}
@GetMapping("val")
public String getVal(){
return "端口号="+ port+",DataSource URL="+DATA_SOURCE_URL;
}
}
复制代码
注意@value 给静态变量赋值的方法。
运行结果:
作者:淡若清风丶
链接:https://juejin.cn/post/6993137390000799752
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
示图
启动说明
流程图
平台架构
进程内邮件队列
项目结构
├─src │ ├─main │ │ ├─java │ │ │ └─com │ │ │ └─itstyle │ │ │ └─mail │ │ │ │ Application.java │ │ │ │ │ │ │ ├─demo │ │ │ │ CountDownLatchDemo.java │ │ │ │ Ticket.java │ │ │ │ TicketRun.java │ │ │ │ │ │ │ ├─model │ │ │ │ Email.java │ │ │ │ │ │ │ ├─queue │ │ │ │ ConsumeMailQueue.java │ │ │ │ MailQueue.java │ │ │ │ │ │ │ ├─redis │ │ │ │ Receiver.java │ │ │ │ RedisConfig.java │ │ │ │ RedisListener.java │ │ │ │ │ │ │ ├─service │ │ │ │ │ IMailService.java │ │ │ │ │ │ │ │ │ └─impl │ │ │ │ MailServiceImpl.java │ │ │ │ │ │ │ ├─task │ │ │ │ SendMail.java │ │ │ │ │ │ │ └─util │ │ │ CommonUtil.java │ │ │ Constants.java │ │ │ MailUtil.java │ │ │ │ │ ├─resources │ │ │ │ application-dev.properties │ │ │ │ application-prod.properties │ │ │ │ application-test.properties │ │ │ │ application.yml │ │ │ │ spring-context-dubbo.xml │ │ │ │ spring-context-task.xml │ │ │ │ │ │ │ └─static │ │ │ ├─file │ │ │ │ 关注科帮网获取更多源码.zip │ │ │ │ │ │ │ ├─image │ │ │ │ springcloud.png │ │ │ │ │ │ │ └─template │ │ │ welcome.flt │ │ │ welcome.html │ │ │ │ │ └─webapp │ │ │ index.jsp │ │ │ │ │ └─WEB-INF │ │ web.xml │ │ │ └─test │ └─java │ └─com │ └─itstyle │ └─mail │ └─test │ SpringbootMailApplication.java
对比测试,建议使用Freemarker模版
application.properties中配置以下内容:
spring.mail.host=smtp.qq.com spring.mail.username=345849402@qq.com #授权码g,在QQ邮箱客户端生成 修改成自己的 设置-账户-开启服务-获取授权码 spring.mail.password=XXXXXXX spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true #freemarker spring.freemarker.template-loader-path=classpath:/static/template/ spring.freemarker.enabled=true spring.freemarker.cache=false spring.freemarker.charset=UTF-8 spring.freemarker.content-type=text/html spring.freemarker.allow-request-override=false spring.freemarker.check-template-location=true spring.freemarker.expose-request-attributes=false spring.freemarker.expose-session-attributes=false spring.freemarker.expose-spring-macro-helpers=false #thymeleaf spring.thymeleaf.prefix=classpath:/static/template/ spring.thymeleaf.suffix=.html spring.thymeleaf.mode=HTML5 spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.content-type=text/html spring.thymeleaf.cache=false
封装实体
首先我们,封装一个Email实体Email.java:
/** * Email封装类 * 创建者 科帮网 * 创建时间 2017年7月20日 * */ public class Email implements Serializable { private static final long serialVersionUID=1L; //必填参数 private String email;//接收方邮件 private String subject;//主题 private String content;//邮件内容 //选填 private String template;//模板 private HashMap<String, String> kvMap;// 自定义参数 ... 省略 get set
业务实现
既然用了spring,就按照spring的方式来,先定义一个接口IMailService,接着是实现MailServiceImpl。
以下代码,实现了四种方式:纯文本,富文本(图片,附件),Freemarker模版以及Thymeleaf模版。
这里需要注意的是,springboot 1.4.0以后 Velocity 废弃了,官方建议用freemaker。而thymeleaf是博主自己实现的,显然效率没有freemaker高(评测对比见文章底部)。
@Service public class MailServiceImpl implements IMailService { @Autowired private JavaMailSender mailSender;//执行者 @Autowired public Configuration configuration;//freemarker @Autowired private SpringTemplateEngine templateEngine;//thymeleaf @Value("${spring.mail.username}") public String USER_NAME;//发送者 @Override public void send(Email mail) throws Exception { MailUtil mailUtil=new MailUtil(); SimpleMailMessage message=new SimpleMailMessage(); message.setFrom(USER_NAME); message.setTo(mail.getEmail()); message.setSubject(mail.getSubject()); message.setText(mail.getContent()); mailUtil.start(mailSender, message); } @Override public void sendHtml(Email mail) throws Exception { MailUtil mailUtil=new MailUtil(); MimeMessage message=mailSender.createMimeMessage(); MimeMessageHelper helper=new MimeMessageHelper(message, true); helper.setFrom(USER_NAME); helper.setTo(mail.getEmail()); helper.setSubject(mail.getSubject()); helper.setText( "<html><body><img src=\"cid:springcloud\" ></body></html>", true); // 发送图片 File file=ResourceUtils.getFile("classpath:static" + Constants.SF_FILE_SEPARATOR + "image" + Constants.SF_FILE_SEPARATOR + "springcloud.png"); helper.addInline("springcloud", file); // 发送附件 file=ResourceUtils.getFile("classpath:static" + Constants.SF_FILE_SEPARATOR + "file" + Constants.SF_FILE_SEPARATOR + "关注科帮网获取更多源码.zip"); helper.addAttachment("科帮网", file); mailUtil.startHtml(mailSender, message); } @Override public void sendFreemarker(Email mail) throws Exception { MimeMessage message=mailSender.createMimeMessage(); MimeMessageHelper helper=new MimeMessageHelper(message, true); helper.setFrom(USER_NAME); helper.setTo(mail.getEmail()); helper.setSubject(mail.getSubject()); Map<String, Object> model=new HashMap<String, Object>(); model.put("content", mail.getContent()); Template template=configuration.getTemplate(mail.getTemplate()+".flt"); String text=FreeMarkerTemplateUtils.processTemplateIntoString( template, model); helper.setText(text, true); mailSender.send(message); } @Override public void sendThymeleaf(Email mail) throws Exception { MimeMessage message=mailSender.createMimeMessage(); MimeMessageHelper helper=new MimeMessageHelper(message, true); helper.setFrom(USER_NAME); helper.setTo(mail.getEmail()); helper.setSubject(mail.getSubject()); Context context=new Context(); context.setVariable("email", mail); String text=templateEngine.process(mail.getTemplate(), context); helper.setText(text, true); mailSender.send(message); } }
测试用例
老司机带你去开车SpringbootMailApplication.java:
*请认真填写需求信息,我们会在24小时内与您取得联系。