Spring Boot 视图层与模板引擎

Spring Boot 视图层与模板引擎

Spring Boot 视图层与模板引擎

在这里插入图片描述
19.1 学习目标与重点提示

学习目标:掌握Spring Boot视图层与模板引擎的核心概念与使用方法,包括Spring Boot视图层的基本方法、Spring Boot与Thymeleaf的集成、Spring Boot与Freemarker的集成、Spring Boot与Velocity的集成、Spring Boot的静态资源管理、Spring Boot的实际应用场景,学会在实际开发中处理视图层问题。
重点:Spring Boot视图层的基本方法Spring Boot与Thymeleaf的集成Spring Boot与Freemarker的集成Spring Boot与Velocity的集成Spring Boot的静态资源管理Spring Boot的实际应用场景

19.2 Spring Boot视图层概述

Spring Boot视图层是指使用Spring Boot进行Web应用开发的方法。

19.2.1 视图层的定义

定义:视图层是指使用Spring Boot进行Web应用开发的方法。
作用

  • 实现Web页面的渲染。
  • 实现数据的展示。
  • 实现用户交互。

✅ 结论:视图层是指使用Spring Boot进行Web应用开发的方法,作用是实现Web页面的渲染、数据的展示、用户交互。

19.2.2 视图层的常用组件

定义:视图层的常用组件是指Spring Boot提供的视图层组件。
组件

  • Thymeleaf:用于Thymeleaf模板。
  • Freemarker:用于Freemarker模板。
  • Velocity:用于Velocity模板。

✅ 结论:视图层的常用组件包括Thymeleaf、Freemarker、Velocity。

19.3 Spring Boot与Thymeleaf的集成

Spring Boot与Thymeleaf的集成是最常用的视图层方法之一。

19.3.1 集成Thymeleaf的步骤

定义:集成Thymeleaf的步骤是指使用Spring Boot与Thymeleaf集成的方法。
步骤

  1. 在pom.xml文件中添加Thymeleaf依赖。
  2. 在application.properties或application.yml文件中配置Thymeleaf。
  3. 创建实体类。
  4. 创建Repository接口。
  5. 创建控制器类。
  6. 创建Thymeleaf模板文件。
  7. 测试应用。

示例
pom.xml文件中的Thymeleaf依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Thymeleaf依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的Thymeleaf配置:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true # H2数据库控制台 spring.h2.console.enabled=true spring.h2.console.path=/h2-console # Thymeleaf配置 spring.thymeleaf.cache=false spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html 

实体类:

importjavax.persistence.*;@Entity@Table(name ="product")publicclassProduct{@Id@GeneratedValue(strategy =GenerationType.IDENTITY)privateLong id;privateString productId;privateString productName;privatedouble price;privateint sales;publicProduct(){}publicProduct(String productId,String productName,double price,int sales){this.productId = productId;this.productName = productName;this.price = price;this.sales = sales;}// Getter和Setter方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetProductId(){return productId;}publicvoidsetProductId(String productId){this.productId = productId;}publicStringgetProductName(){return productName;}publicvoidsetProductName(String productName){this.productName = productName;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicintgetSales(){return sales;}publicvoidsetSales(int sales){this.sales = sales;}@OverridepublicStringtoString(){return"Product{"+"id="+ id +",+ productId +'\''+",+ productName +'\''+", price="+ price +", sales="+ sales +'}';}}

Repository接口:

importorg.springframework.data.jpa.repository.JpaRepository;importorg.springframework.stereotype.Repository;importjava.util.List;@RepositorypublicinterfaceProductRepositoryextendsJpaRepository<Product,Long>{List<Product>findBySalesGreaterThan(int sales);}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;importorg.springframework.ui.Model;importorg.springframework.web.bind.annotation.*;importjava.util.List;@Controller@RequestMapping("/products")publicclassProductController{@AutowiredprivateProductRepository productRepository;@GetMapping("/")publicStringgetAllProducts(Model model){List<Product> products = productRepository.findAll(); model.addAttribute("products", products);return"products";}@PostMapping("/")publicStringaddProduct(@ModelAttributeProduct product){ productRepository.save(product);return"redirect:/products/";}@GetMapping("/top-selling")publicStringgetTopSellingProducts(@RequestParamint topN,Model model){List<Product> products = productRepository.findBySalesGreaterThan(0); products.sort((p1, p2)-> p2.getSales()- p1.getSales());if(products.size()> topN){ products = products.subList(0, topN);} model.addAttribute("products", products);return"products";}}

Thymeleaf模板文件(src/main/resources/templates/products.html):

<!DOCTYPEhtml><htmlxmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>产品列表</title><style>table{border-collapse: collapse;width: 100%;}th, td{border: 1px solid #ddd;padding: 8px;text-align: left;}th{background-color: #f2f2f2;}.add-product{margin-bottom: 20px;}</style></head><body><h1>产品列表</h1><divclass="add-product"><formth:action="@{/products/}"method="post"th:object="${product}"><label>产品ID:</label><inputtype="text"th:field="*{productId}"required><br><label>产品名称:</label><inputtype="text"th:field="*{productName}"required><br><label>价格:</label><inputtype="number"th:field="*{price}"step="0.01"required><br><label>销量:</label><inputtype="number"th:field="*{sales}"required><br><buttontype="submit">添加产品</button></form></div><div><formth:action="@{/products/top-selling}"method="get"><label>销量TOP:</label><inputtype="number"name="topN"value="3"min="1"required><buttontype="submit">查询</button></form></div><table><thead><tr><th>ID</th><th>产品ID</th><th>产品名称</th><th>价格</th><th>销量</th></tr></thead><tbody><trth:each="product : ${products}"><tdth:text="${product.id}"></td><tdth:text="${product.productId}"></td><tdth:text="${product.productName}"></td><tdth:text="${#numbers.formatDecimal(product.price, 0, 'COMMA', 2, 'POINT')}"></td><tdth:text="${product.sales}"></td></tr></tbody></table></body></html>

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestHomePage(){String response = restTemplate.getForObject("http://localhost:"+ port +"/products/",String.class);assertThat(response).contains("产品列表");}}

✅ 结论:集成Thymeleaf的步骤包括添加Thymeleaf依赖、配置Thymeleaf、创建实体类、创建Repository接口、创建控制器类、创建Thymeleaf模板文件、测试应用。

19.4 Spring Boot与Freemarker的集成

Spring Boot与Freemarker的集成是常用的视图层方法之一。

19.4.1 集成Freemarker的步骤

定义:集成Freemarker的步骤是指使用Spring Boot与Freemarker集成的方法。
步骤

  1. 在pom.xml文件中添加Freemarker依赖。
  2. 在application.properties或application.yml文件中配置Freemarker。
  3. 创建实体类。
  4. 创建Repository接口。
  5. 创建控制器类。
  6. 创建Freemarker模板文件。
  7. 测试应用。

示例
pom.xml文件中的Freemarker依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Freemarker依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的Freemarker配置:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true # H2数据库控制台 spring.h2.console.enabled=true spring.h2.console.path=/h2-console # Freemarker配置 spring.freemarker.cache=false spring.freemarker.prefix=classpath:/templates/ spring.freemarker.suffix=.ftl 

实体类、Repository接口、控制器类与集成Thymeleaf的示例相同。

Freemarker模板文件(src/main/resources/templates/products.ftl):

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>产品列表</title> <style> table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } .add-product { margin-bottom: 20px; } </style> </head> <body> <h1>产品列表</h1> <div> <form action="/products/" method="post"> <label>产品ID:</label> <input type="text" name="productId" required> <br> <label>产品名称:</label> <input type="text" name="productName" required> <br> <label>价格:</label> <input type="number" name="price" step="0.01" required> <br> <label>销量:</label> <input type="number" name="sales" required> <br> <button type="submit">添加产品</button> </form> </div> <div> <form action="/products/top-selling" method="get"> <label>销量TOP:</label> <input type="number" name="topN" value="3" min="1" required> <button type="submit">查询</button> </form> </div> <table> <thead> <tr> <th>ID</th> <th>产品ID</th> <th>产品名称</th> <th>价格</th> <th>销量</th> </tr> </thead> <tbody> <#list products as product> <tr> <td>${product.id}</td> <td>${product.productId}</td> <td>${product.productName}</td> <td>${product.price?string(",###.00")}</td> <td>${product.sales}</td> </tr> </#list> </tbody> </table> </body> </html> 

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestHomePage(){String response = restTemplate.getForObject("http://localhost:"+ port +"/products/",String.class);assertThat(response).contains("产品列表");}}

✅ 结论:集成Freemarker的步骤包括添加Freemarker依赖、配置Freemarker、创建实体类、创建Repository接口、创建控制器类、创建Freemarker模板文件、测试应用。

19.5 Spring Boot与Velocity的集成

Spring Boot与Velocity的集成是常用的视图层方法之一。

19.5.1 集成Velocity的步骤

定义:集成Velocity的步骤是指使用Spring Boot与Velocity集成的方法。
步骤

  1. 在pom.xml文件中添加Velocity依赖。
  2. 在application.properties或application.yml文件中配置Velocity。
  3. 创建实体类。
  4. 创建Repository接口。
  5. 创建控制器类。
  6. 创建Velocity模板文件。
  7. 测试应用。

示例
pom.xml文件中的Velocity依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Velocity依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-velocity</artifactId><version>1.5.22.RELEASE</version></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的Velocity配置:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true # H2数据库控制台 spring.h2.console.enabled=true spring.h2.console.path=/h2-console # Velocity配置 spring.velocity.cache=false spring.velocity.prefix=classpath:/templates/ spring.velocity.suffix=.vm 

实体类、Repository接口、控制器类与集成Thymeleaf的示例相同。

Velocity模板文件(src/main/resources/templates/products.vm):

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>产品列表</title> <style> table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } .add-product { margin-bottom: 20px; } </style> </head> <body> <h1>产品列表</h1> <div> <form action="/products/" method="post"> <label>产品ID:</label> <input type="text" name="productId" required> <br> <label>产品名称:</label> <input type="text" name="productName" required> <br> <label>价格:</label> <input type="number" name="price" step="0.01" required> <br> <label>销量:</label> <input type="number" name="sales" required> <br> <button type="submit">添加产品</button> </form> </div> <div> <form action="/products/top-selling" method="get"> <label>销量TOP:</label> <input type="number" name="topN" value="3" min="1" required> <button type="submit">查询</button> </form> </div> <table> <thead> <tr> <th>ID</th> <th>产品ID</th> <th>产品名称</th> <th>价格</th> <th>销量</th> </tr> </thead> <tbody> #foreach ($product in $products) <tr> <td>$product.id</td> <td>$product.productId</td> <td>$product.productName</td> <td>$product.price.format("###,###.00")</td> <td>$product.sales</td> </tr> #end </tbody> </table> </body> </html> 

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestHomePage(){String response = restTemplate.getForObject("http://localhost:"+ port +"/products/",String.class);assertThat(response).contains("产品列表");}}

✅ 结论:集成Velocity的步骤包括添加Velocity依赖、配置Velocity、创建实体类、创建Repository接口、创建控制器类、创建Velocity模板文件、测试应用。

19.6 Spring Boot的静态资源管理

Spring Boot的静态资源管理是视图层的重要组件。

19.6.1 静态资源管理的定义

定义:静态资源管理是指使用Spring Boot管理静态资源的方法。
作用

  • 管理Web应用的静态资源,如CSS、JavaScript、图片等。
  • 提高开发效率。
  • 提供统一的编程模型。

常用静态资源目录

  • src/main/resources/static:用于存放静态资源。
  • src/main/resources/public:用于存放静态资源。
  • src/main/resources/resources:用于存放静态资源。
  • src/main/resources/templates:用于存放模板文件。

示例
创建静态资源文件(src/main/resources/static/css/style.css):

body{font-family: Arial, sans-serif;margin: 0;padding: 0;}h1{color: #333;margin: 20px 0;}table{border-collapse: collapse;width: 100%;}th, td{border: 1px solid #ddd;padding: 8px;text-align: left;}th{background-color: #f2f2f2;}.add-product{margin-bottom: 20px;}

在Thymeleaf模板文件中引用静态资源:

<!DOCTYPEhtml><htmlxmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>产品列表</title><linkrel="stylesheet"th:href="@{/css/style.css}"></head><body><h1>产品列表</h1><divclass="add-product"><formth:action="@{/products/}"method="post"th:object="${product}"><label>产品ID:</label><inputtype="text"th:field="*{productId}"required><br><label>产品名称:</label><inputtype="text"th:field="*{productName}"required><br><label>价格:</label><inputtype="number"th:field="*{price}"step="0.01"required><br><label>销量:</label><inputtype="number"th:field="*{sales}"required><br><buttontype="submit">添加产品</button></form></div><div><formth:action="@{/products/top-selling}"method="get"><label>销量TOP:</label><inputtype="number"name="topN"value="3"min="1"required><buttontype="submit">查询</button></form></div><table><thead><tr><th>ID</th><th>产品ID</th><th>产品名称</th><th>价格</th><th>销量</th></tr></thead><tbody><trth:each="product : ${products}"><tdth:text="${product.id}"></td><tdth:text="${product.productId}"></td><tdth:text="${product.productName}"></td><tdth:text="${#numbers.formatDecimal(product.price, 0, 'COMMA', 2, 'POINT')}"></td><tdth:text="${product.sales}"></td></tr></tbody></table></body></html>

✅ 结论:静态资源管理是指使用Spring Boot管理静态资源的方法,常用静态资源目录包括src/main/resources/static、src/main/resources/public、src/main/resources/resources、src/main/resources/templates。

19.7 Spring Boot的实际应用场景

在实际开发中,Spring Boot视图层与模板引擎的应用场景非常广泛,如:

  • 实现商品的展示与购买。
  • 实现订单的管理。
  • 实现用户的管理。
  • 实现博客的发布与管理。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.data.jpa.repository.JpaRepository;importorg.springframework.stereotype.Repository;importorg.springframework.stereotype.Controller;importorg.springframework.ui.Model;importorg.springframework.web.bind.annotation.*;importjavax.persistence.*;importjava.util.List;// 产品类@Entity@Table(name ="product")publicclassProduct{@Id@GeneratedValue(strategy =GenerationType.IDENTITY)privateLong id;privateString productId;privateString productName;privatedouble price;privateint sales;publicProduct(){}publicProduct(String productId,String productName,double price,int sales){this.productId = productId;this.productName = productName;this.price = price;this.sales = sales;}// Getter和Setter方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetProductId(){return productId;}publicvoidsetProductId(String productId){this.productId = productId;}publicStringgetProductName(){return productName;}publicvoidsetProductName(String productName){this.productName = productName;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicintgetSales(){return sales;}publicvoidsetSales(int sales){this.sales = sales;}@OverridepublicStringtoString(){return"Product{"+"id="+ id +",+ productId +'\''+",+ productName +'\''+", price="+ price +", sales="+ sales +'}';}}// 产品Repository@RepositorypublicinterfaceProductRepositoryextendsJpaRepository<Product,Long>{List<Product>findBySalesGreaterThan(int sales);}// 产品控制器@Controller@RequestMapping("/products")publicclassProductController{@AutowiredprivateProductRepository productRepository;@GetMapping("/")publicStringgetAllProducts(Model model){List<Product> products = productRepository.findAll(); model.addAttribute("products", products); model.addAttribute("product",newProduct());return"products";}@PostMapping("/")publicStringaddProduct(@ModelAttributeProduct product){ productRepository.save(product);return"redirect:/products/";}@GetMapping("/top-selling")publicStringgetTopSellingProducts(@RequestParamint topN,Model model){List<Product> products = productRepository.findBySalesGreaterThan(0); products.sort((p1, p2)-> p2.getSales()- p1.getSales());if(products.size()> topN){ products = products.subList(0, topN);} model.addAttribute("products", products); model.addAttribute("product",newProduct());return"products";}}// 应用启动类@SpringBootApplicationpublicclassProductApplication{publicstaticvoidmain(String[] args){SpringApplication.run(ProductApplication.class, args);}@AutowiredprivateProductRepository productRepository;publicvoidrun(String... args){// 初始化数据 productRepository.save(newProduct("P001","手机",1000.0,100)); productRepository.save(newProduct("P002","电脑",5000.0,50)); productRepository.save(newProduct("P003","电视",3000.0,80)); productRepository.save(newProduct("P004","手表",500.0,200)); productRepository.save(newProduct("P005","耳机",300.0,150));}}// 测试类@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestHomePage(){String response = restTemplate.getForObject("http://localhost:"+ port +"/products/",String.class);assertThat(response).contains("产品列表");}}

输出结果

  • 访问http://localhost:8080/products/:显示产品列表页面。
  • 访问http://localhost:8080/products/top-selling?topN=3:显示销量TOP3的产品列表页面。

✅ 结论:在实际开发中,Spring Boot视图层与模板引擎的应用场景非常广泛,需要根据实际问题选择合适的模板引擎。

总结

本章我们学习了Spring Boot视图层与模板引擎,包括Spring Boot视图层的基本方法、Spring Boot与Thymeleaf的集成、Spring Boot与Freemarker的集成、Spring Boot与Velocity的集成、Spring Boot的静态资源管理、Spring Boot的实际应用场景,学会了在实际开发中处理视图层问题。其中,Spring Boot视图层的基本方法、Spring Boot与Thymeleaf的集成、Spring Boot与Freemarker的集成、Spring Boot与Velocity的集成、Spring Boot的静态资源管理、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。

Read more

Java 并发常见问题总结(4)

Java线程出现异常,进程为啥不会退出? 因为Java是采用线程独立模型,各个线程之间互相独立,有各自的上下文,当一个线程出现错误的时候,只会影响到这个线程自己本身,不会影响到其它的线程,更不会导致程序退出 不过我们这里介绍的异常更多是Exception,如果是error级别的,通常意味着硬件层面不够,才有可能会导致退出 此外Exception我们是可以通过捕获的,捕获了的话也不会导致线程直接死掉 Java是如何判断一个线程是否存活的?需要注意什么吗? 通过isAlive() 方法: public class Main { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { System.out.println("t1 begin"); try { Thread.sleep(1000); } catch (InterruptedException e)

By Ne0inhk
鸿蒙UI框架演进史:从Java UI到ArkUI的架构变迁,解码声明式UI与跨端一致性的技术革命

鸿蒙UI框架演进史:从Java UI到ArkUI的架构变迁,解码声明式UI与跨端一致性的技术革命

鸿蒙UI框架演进史:从Java UI到ArkUI的架构变迁,解码声明式UI与跨端一致性的技术革命 第一章 :UI框架的十年之变 在移动操作系统的演进史上,UI框架的变迁始终是开发者体验与系统能力的晴雨表。从2012年EMUI 1.0诞生,到2025年HarmonyOS NEXT全面推广ArkUI,华为的UI框架走过了13年的技术迭代之路。 这期间,我们见证了从“命令式UI”到“声明式UI”的范式转移,经历了从“单设备适配”到“多端一致”的架构革命。对于开发者而言,理解这段演进史,不仅是回顾技术发展脉络,更是把握鸿蒙生态未来方向的关键。 本文将系统梳理鸿蒙UI框架的演进历程,深入剖析渲染引擎的优化技术,用量化数据证明声明式UI的性能优势,并解密跨端UI一致性的实现方案。全文约12000字,包含大量代码示例与实践建议。 第二章 鸿蒙UI框架演进史:从Java UI到ArkUI的架构变迁 2.1 EMUI时代:定制化UI的探索期(2012-2019) 要理解鸿蒙UI的今天,必须先回顾EMUI的昨天。2012年,华为发布了基于Android的EMUI 1.0,

By Ne0inhk
【Java 开发日记】有了解过 SpringBoot 的参数配置吗?

【Java 开发日记】有了解过 SpringBoot 的参数配置吗?

目录 核心概念:application.properties 与 application.yml 配置的加载位置与优先级 外部化配置(非常强大) 如何在代码中获取配置值? 常用配置示例 总结 当然了解,Spring Boot 的参数配置是其核心特性之一,也是它实现“约定大于配置”理念的关键。它极大地简化了传统 Spring 应用中繁琐的 XML 配置。 一、核心概念:application.properties 与 application.yml Spring Boot 默认使用这两种文件进行配置(二者选其一即可,.yml 更常用)。 application.properties (传统键值对格式) server.port=8081 spring.datasource.url=jdbc:mysql://localhost:

By Ne0inhk
Java之Volatile 关键字全方位解析:从底层原理到最佳实践

Java之Volatile 关键字全方位解析:从底层原理到最佳实践

文章目录 * 课程导言 * 适用对象 * 学习目标 * 第一部分:从并发三要素看volatile的定位 * 1.1 并发编程的三座大山 * 1.2 volatile的坐标:轻量级的同步利器 * 1.3 一个先导案例:感受volatile的魔力 * 第二部分:volatile与Java内存模型(JMM) * 2.1 为什么要JMM? * 2.2 JMM的核心结构:主内存 vs 工作内存 * 2.3 可见性问题的根源 * 2.4 volatile如何保证可见性? * 2.5 JMM对volatile的规范 * 第三部分:有序性与指令重排序 * 3.1 什么是指令重排序? * 3.2 重排序的潜在风险 * 3.3 volatile如何禁止重排序? * 3.

By Ne0inhk