整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          SpringBoot使用Thymeleaf模板(20

          SpringBoot使用Thymeleaf模板(2019-09-25)

          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

          用注解

          1.創建項目

          項目名稱:01-spring-boot-MVC

          2.@SpringBootApplication

          @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 個注解,以上清單也有介紹。

          3.@Controller

          @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 數據,有多種方案。

          • 第一種方案:引入 freemark 模板;
          • 第二種方案:引入 thymeleaf 模板;
          • 第三種方案:建立 JSP 頁面,等等;

          由于第一種方案的語法簡單,使用頻率高,下面簡單說第一種方案。

          在 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 下.

          4.@RestController

          @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;
              }
          }
          復制代碼

          運行結果:

          5.@RequestMapping

          @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 代替它。

          6.@RequestParam

          在參數前面設置,格式是:

          @RequestParam(value=“變量名”, required=true/false, defaultVale=默認值 )
          復制代碼
          1. value:請求參數名(必須配置)
          2. required:是否必需,默認為 true,即 請求中必須包含該參數,如果沒有包含,將會拋出異常(可選配置)
          3. defaultValue:默認值,如果設置了該值,required 將自動設為 false,無論你是否配置了 required,配置了什么值,都是 false(可選配置)

          設置 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
          復制代碼
          • 當只設置 value 的時候,value 可以省略;
          • 當要設置多個參數值,value 不能省略;
          • required 默認是 true,也就是必須傳值,沒有則報錯;

          第二個參數:如下 url 可以沒有 userName 這個參數,請求不報錯。

          @RequestParam(value="userName", required=false) String userName
          復制代碼

          第三個參數:如下設置 required=false,age 不傳值,此時 age 等于 null,因 int 是基礎類型不能接收 null 所以報錯,所以一般可以使用 Integer 聲明,避免錯誤。

          @RequestParam(value="age", required=false) int age
          復制代碼

          運行結果:

          7.@PathVariable

          新建 PathVariableController 控制器類。

          源代碼:

          src/main/java/com/springboot/codingstudty/controller/PathVariableController.java

          在參數前面設置,格式是:

          @PathVariable(value=“變量名”, required=true/false)
          復制代碼
          1. value:請求參數名(必須配置)
          2. required:是否必需,默認為 true,即 請求中必須包含該參數,如果沒有包含,將會

          拋出異常(可選配置)

          具體方法:

          @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/張三

          注意:請求路徑必須是完整,否則報錯。

          運行結果

          8.@GetMapping

          以下@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;
          }
          復制代碼

          9.@PostMapping

          @PostMapping 是一個組合注解,是@RequestMapping(method=RequestMethod.POST)的縮寫,只接收前端 post 提交,一般用于數據的新增。

          @PostMapping
          public boolean insert(@RequestBody User user) {
              //insert ...
              return true;
          }
          復制代碼

          10. @PutMapping

          @PutMapping 是一個組合注解,是@RequestMapping(method=RequestMethod.PUT)的縮寫,只接收前端 PUT 提交,一般用于數據的修改。

          @PutMapping
          public boolean update(@RequestBody User user) {
              //update .....
              return true;
          }
          復制代碼

          11. @DeleteMapping

          @DeleteMapping 是一個組合注解,是@RequestMapping(method=RequestMethod.DELETE)的縮寫,只接收前端 DELETE 提交,用于數據刪除。

          @DeleteMapping
          public boolean del(@PathVariable("id") String id) {
              System.out.println(id);
              //delete ....
              return true;
          }
          復制代碼

          12. @ResponseBody

          @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;
          }
          復制代碼

          運行結果:

          13. @RequestBody

          @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

          14. @CrossOrigin

          前后端分離之后前端 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("銷毀......");
              }
          }
          復制代碼

          15. @Configuration

          @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();
              }
              //……
          }
          復制代碼

          注意:

          • 類頭注解@Configuration
          • 里面的方法加有@Bean(@Bean 下面單獨說)

          (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;
          }
          復制代碼

          在瀏覽器端請求打印效果:

          16. @Bean

          以上已經多次使用到@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;
          復制代碼

          17. @Service

          用于修飾 service 層的組件,標注在類上。注意不是標在接口上。

          /**
          * 描述:service 層
          * @author ming
          */
          
          @Service
          public class UserService {
              //TODO
          }
          復制代碼

          之后,調用時和用@Bean 注冊是一樣用@Autowired 即可。

          用@Service 標注的類一般都是明確是業務服務層,從業務角度清晰的劃分。

          18. @Component

          @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 {
              //……
          }
          復制代碼

          19. @Repository

          @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 來注解,也可以得到這個接口的實現類,有幾個原因:

          • spring 配置文件中配置了 MapperScannerConfigurer 這個 bean,它會掃描持久層接口創建實現類并交給 spring 管理。
          • 接口上使用了@Mapper 注解或者 springboot 中主類上使用了@MapperScan 注解,它和MapperScannerConfigurer 作用一樣。

          例如使用 SSM 框架時候,經常在 Dao 層注入@Mapper 即可(這時候需要引入 MyBatis 或者 MyBatisPlus 依賴包)。

          20. @Autowired

          在上面提到多次@Autowired,是用來“new 實例”的。加了該注解的對象直接調用即可,無需手工 new 對象。

          //注意,加了@Autowired 就相當于 new UserAction
          @Autowired
          UserAction userAction;
          復制代碼

          當多個同類型 bean 時,可以這樣使用@Resource,如下介紹.

          21. @Resource

          用@Resource 和@Autowired 類似

          @Resource(name="userAction1")
          UserAction userAction;
          復制代碼

          22. @Autowired+@Qualifier

          @Autowired+@Qualifier

          @Autowired
          @Qualifier(value="userAction1")
          UserAction userAction;
          復制代碼

          23. @Value

          @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
          來源:掘金
          著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

          示圖

          啟動說明

          • 項目中RPC框架使用的是當當維護的DubboX,現在阿里已經處于維護狀態中,請自行更新
          • 配置Dubbo需要安裝注冊中心zookeeper: http://www.52itstyle.top/thread-19791-1-1.html
          • 如果不想使用Dubbo和安裝zookeeper,又想啟動看下效果,請注釋掉 Application 類中的@ImportResource({"classpath:spring-context-dubbo.xml"}), 同時由于接口掃描注解使用的是Dubbo的 com.alibaba.dubbo.config.annotation.Service; 請自行替換成spring的 org.springframework.stereotype.Service(廢棄);
          • Sql文件位于src/main/resource/sql下,自行導入即可、里面有一條測試數據
          • API: http://localhost:8080/springboot_mail/swagger-ui.html、 可以自行測試發送郵件,前提是要修改application-dev.properties中的郵箱配置為自己可用的
          • 2018-10-25 原spring-context-dubbo.xml 配置 替換為 dubbo-spring-boot-starter 2.0.0
          • 執行 com.itstyle.mail.test.SpringbootMailApplication main 方法

          流程圖

          平臺架構

          進程內郵件隊列

          項目結構

          ├─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模版發送郵件
          • thymeleaf模版發送郵件

          評測生成模版時間對比(1000次循環)

          • Thymeleaf用時:2686ms
          • Freemarker用時:498ms

          對比測試,建議使用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:


          主站蜘蛛池模板: 日韩亚洲AV无码一区二区不卡| 日本亚洲国产一区二区三区| 国产在线精品一区二区| 久久一本一区二区三区| 91成人爽a毛片一区二区| 99热门精品一区二区三区无码| 亚洲AV无码一区二区三区鸳鸯影院| 日本v片免费一区二区三区 | 日韩好片一区二区在线看| 日本视频一区在线观看免费| 亚洲av色香蕉一区二区三区蜜桃| 女同一区二区在线观看| 精品人妻少妇一区二区三区在线| 亚洲AV无码一区二区二三区入口 | 五十路熟女人妻一区二区| 国产aⅴ精品一区二区三区久久 | 精品无码日韩一区二区三区不卡| 丝袜美腿一区二区三区| 国产精品污WWW一区二区三区| 亚洲av一综合av一区| 日韩美一区二区三区| 国产剧情国产精品一区| 日韩欧美一区二区三区免费观看| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 亚洲A∨无码一区二区三区| 成人免费一区二区三区在线观看| 国产精品小黄鸭一区二区三区| 日韩免费一区二区三区在线播放| 亚洲视频一区二区| 久久精品成人一区二区三区 | 97久久精品无码一区二区天美 | 三上悠亚一区二区观看| 亚洲欧美日韩一区二区三区| 中日韩一区二区三区| 成人精品一区二区三区校园激情| 亚洲国产成人一区二区精品区 | 亚洲天堂一区二区三区| 国产精品被窝福利一区| 99偷拍视频精品一区二区| 久久精品国产免费一区| 一区二区三区在线|