如何在 Spring Boot 中实现 FreeMarker 模板

2025-04-28 17:50

本文主要是介绍如何在 Spring Boot 中实现 FreeMarker 模板,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文...

什么是 FreeMarker 模板?

FreeMarker 是一种功能强大、轻量级的模板引擎,用于在 Java 应用中生成动态文本输出(如 htmlandroidXML、邮件内容等)。它允许开发者将数据模型与模板文件分离,通过模板语法动态生成内容。FreeMarker 广泛用于 Web 开发、报表生成和自动化文档生成,特别是在 Spring Boot 项目中与 Spring MVC 集成,用于生成动态网页

核心功能

  • 模板与数据分离:模板定义输出格式,数据模型提供动态内容。
  • 灵活的语法:支持条件、循环、变量插值等,易于编写动态逻辑。
  • 多种输出格式:生成 HTML、XML、jsON、文本等。
  • 高性能:模板编译和缓存机制,适合高并发场景。
  • 与 Spring 集成:Spring Boot 提供 Starter,简化配置。

优势

  • 简化动态内容生成,减少硬编码。
  • 提高开发效率,模板可复用。
  • 支持复杂逻辑,适合多样化输出需求。
  • 与 Spring Boot、Spring Security 等无缝集成。

挑战

  • 学习曲线:模板语法需熟悉。
  • 调试复杂:动态逻辑可能导致错误难以定位。
  • 需与你的查询(如分页、Swagger、Spring Security、ActiveMQ、Spring Profiles、Spring BATch、热加载、ThreadLocal、Actuator 安全性)集成。
  • 安全性:防止模板注入攻击(如 XSS)。

在 Spring Boot 中实现 FreeMarker 模板

以下是在 Spring Boot 中使用 FreeMarker 的简要步骤,结合你的先前查询(分页、Swagger、ActiveMQ、Spring Profiles、Spring Security、Spring Batch、热加载、ThreadLocal、Actuator 安全性)。完整代码和详细步骤见下文。

1. 环境搭建

添加依赖pom.xml):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-batch</artifactId>
</dependency>

配置 application.yml

spring:
  profiles:
    active: dev
  application:
    name: freemarker-demo
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  h2:
    console:
      enabled: true
  freemarker:
    template-loader-path: classpath:/templates/
    suffix: .ftl
    cache: false # 开发环境禁用缓存,支持热加载
  activemq:
    broker-url: tcp://localhost:61616
    user: admin
    password: admin
  batch:
    job:
      enabled: false
    initialize-schema: always
server:
  port: 8081
management:
  endpoints:
    web:
      exposure:
        include: health, metrics
springdoc:
  api-docs:
    path: /api-docs
  swagger-ui:
    path: /swagger-ui.html

2. 基本 FreeMarker 模板

以下示例使用 FreeMarker 生成用户列表页面。

实体类User.java):

package com.example.demo.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int age;
    // Getters and Setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

RepositoryUserRepository.java):

package com.example.demo.repository;
import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

创建 FreeMarker 模板src/main/resources/templates/users.ftl):

<!DOCTYPE html>
<html>
<head>
    <title>用户列表</title>
</head>
<body>
    <h1>用户列表</h1>
    <table border="1">
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
        <#list users as user>
            <tr>
                <td>${user.id}</td>
                <td>${user.name?html}</td> <#-- 防止 XSS -->
                <td>${user.age}</td>
            </tr>
        </#list>
    </table>
</body>
</html>

控制器UserController.java):

package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class UserController {
    @Autowired
    private UserRepository userRepository;
    @GetMapping("/users")
    public String getUsers(Model model) {
        model.addAttribute("users", userRepository.findAll());
        return "users"; // 对应 users.ftl
    }
}

初始化数据DemoApplication.java):

package com.example.demo;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    @Bean
    CommandLineRunner initData(UserRepository userRepository) {
        return args -> {
            for (int i = 1; i <= 10; i++) android{
                User user = new User();
                user.setName("User" + i);
                user.setAge(20 + i);
                userRepository.save(user);
            }
        };
    }
}

运行验证

  • 启动应用:mvn spring-boot:run
  • 访问 http://localhost:8081/users,查看用户列表页面。
  • 检查 HTML 输出,确认用户数据显示正确。

3. 与先前查询集成

结合你的查询(分页、Swagger、ActiveMQ、Spring Profiles、Spring Security、Spring Batch、热加载、ThreadLocal、Actuator 安全性):

分页与排序

添加分页支持:

package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/users")
    public String getUsers(
            @RequestParam(defaultValue = "") String name,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "id") String sortBy,
            @RequestParam(defaultValue = "asc") String direction,
            Model model) {
        Page<User> userPage = userService.searchUsers(name, page, size, sortBy, direction);
        model.addAttribute("users", userPage.getContent());
        model.addAttribute("page", userPage);
        return "users";
    }
}
package com.example.demo.service;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    public Page<User> searchUsers(String name, int page, int size, String sortBy, String direction) {
        Sort sort = Sort.by(Sort.Direction.fromString(direction), sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);
        return userRepository.findByNameContaining(name, pageable);
    }
}
package com.example.demo.repository;
import com.example.demo.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Page<User> findByNameContaining(String name, Pageable pageable);
}

更新模板(users.ftl)支持分页:

<!DOCTYPE html>
<html>
<head>
    <title>用户列表</title>
</head>
<body>
    <h1>用户列表</h1>
    <form method="get">
        <input type="text" name="name" placeholder="搜索姓名" value="${(name!'')}">
        <input type="submit" value="搜索">
    </form>
    <table border="1">
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
        <#list users as user>
            <tr>
                <td>${user.id}</td>
                <td>${user.name?html}</td>
                <td>${user.age}</td>
            </tr>
        </#list>
    </table>
    <div>
        <#if page??>
            <p>第 ${page.number + 1} 页,共 ${page.totalPages} 页</p>
            <#if page.hASPrevious()>
                <a href="?name=${(name!'')}&page=${page.number - 1}&size=${page.size}&sortBy=id&direction=asc" rel="external nofollow" >上一页</a>
            </#if>
            <#if page.hasNext()>
                <a href="?name=${(name!'')}&page=${page.number + 1}&size=${page.size}&sortBy=id&direction=asc" rel="external nofollow" >下一页</a>
            </#if>
        </#if>
    </div>
</body>
</html>

Swagger

为 REST API 添加 Swagger 文档:

package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Tag(name = "用户管理", description = "用户相关的 API")
public class UserApiController {
    @Autowired
    private UserService userService;
    @Operation(summary = "分页查询用户", description = "根据条件分页查询用户列表")
    @ApiResponse(responseCode = "200", description = "成功返回用户分页数据")
    @GetMapping("/api/users")
    public Page<User> searchUsers(
            @Parameter(description = "搜索姓名(可选)") @RequestParam(defaultValue = "") String name,
            @Parameter(description = "页码,从 0 开始") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") int size,
            @Parameter(description = "排序字段") @RequestParam(defaultValue = "id") String sortBy,
            @Parameter(description = "排序方向(asc/desc)") @RequestParam(defaultValue = "asc") String direction) {
        rejavascriptturn userService.searchUsers(name, page, size, sortBy, direction);
    }
}

ActiveMQ

记录用户查询日志:

package com.example.demo.service;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private JmsTemplate jmsTemplate;
    @Autowired
    private Environment environment;
    public Page<User> searchUsers(String name, int page, int size, String sortBy, String direction) {
        try {
            String profile = String.join(",", environment.getActiveProfiles());
            CONTEXT.set("Query-" + profile + "-" + Thread.currentThread().getName());
            Sort sort = Sort.by(Sort.Direction.fromString(direction), sortBy);
            Pageable pageable = PageRequest.of(page, size, sort);
            Page<User> result = userRepository.findByNameContaining(name, pageable);
            jmsTemplate.convertAndSend("user-query-log", "Queried users: " + name + ", Profile: " + profile);
            return result;
        } finally {
            CONTEXT.remove();
        }
    }
}

Spring Profiles

配置 application-dev.ymlapplication-prod.yml

# application-dev.yml
spring:
  freemarker:
    cache: false
  springdoc:
    swagger-ui:
      enabled: true
logging:
  level:
    root: DEBUG
# application-prod.yml
spring:
  freemarker:
    cache: true
  datasource:
    url: jdbc:mysql://prod-db:3306/appdb
    username: prod_user
    password: ${DB_PASSWORD}
  springdoc:
    swagger-ui:
      enabled: faChina编程lse
logging:
  level:
    root: INFO

Spring Security

保护页面和 API:

package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
importwww.chinasem.cn org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/swagger-ui/**", "/api-docs/**", "/api/users").hasRole("ADMIN")
                .requestMatchers("/users").authenticated()
                .requestMatchers("/actuator/health").permitAll()
                .requestMatchers("/actuator/**").hasRole("ADMIN")
                .anyRequest().permitAll()
            )
            .formLogin();
        return http.build();
    }
    @Bean
    public UserDetailsService userDetailsService() {
        var user = User.withDefaultPasswordEncoder()
            .username("admin")
            .password("admin")
            .roles("ADMIN")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

Spring Batch

使用 FreeMarker 生成批处理报告:

package com.example.demo.config;
import com.example.demo.entity.User;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.database.JpaPagingItemReader;
import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.transform.PassThroughLineAggregator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Component;
import jakarta.persistence.EntityManagerFactory;
import java.io.StringWriter;
@Component
@EnableBatchProcessing
public class BatchConfig {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private EntityManagerFactory entityManagerFactory;
    @Autowired
    private Configuration freemarkerConfig;
    @Bean
    public JpaPagingItemReader<User> reader() {
        return new JpaPagingItemReaderBuilder<User>()
                .name("userReader")
                .entityManagerFactory(entityManagerFactory)
                .queryString("SELECT u FROM User u")
                .pageSize(10)
                .build();
    }
    @Bean
    public FlatFileItemWriter<User> writer() throws Exception {
        FlatFileItemWriter<User> writer = new FlatFileItemWriter<>();
        writer.setResource(new FileSystemResource("users-report.html"));
        writer.setLineAggregator(new PassThroughLineAggregator<User>() {
            @Override
            public String aggregate(User user) {
                try {
                    Template template = freemarkerConfig.getTemplate("report.ftl");
                    StringWriter out = new StringWriter();
                    template.process(java.util.Collections.singletonMap("user", user), out);
                    return out.toString();
                } catch (Exception e) {
                    throw new RuntimeException("Template processing failed", e);
                }
            }
        });
        return writer;
    }
    @Bean
    public Step step1() throws Exception {
        return stepBuilderFactory.get("step1")
                .<User, User>chunk(10)
                .reader(reader())
                .writer(writer())
                .build();
    }
    @Bean
    public Job generateReportJob() throws Exception {
        return jobBuilderFactory.get("generateReportJob")
                .start(step1())
                .build();
    }
}

报告模板(src/main/resources/templates/report.ftl):

<div>
    <p>ID: ${user.id}</p>
    <p>Name: ${user.name?html}</p>
    <p>Age: ${user.age}</p>
</div>

热加载

启用 DevTools,支持模板修改后自动重载:

spring:
  devtools:
    restart:
      enabled: true

ThreadLocal

在服务层清理 ThreadLocal:

public Page<User> searchUsers(String name, int page, int size, String sortBy, String direction) {
    try {
        String profile = String.join(",", environment.getActiveProfiles());
        CONTEXT.set("Query-" + profile + "-" + Thread.currentThread().getName());
        Sort sort = Sort.by(Sort.Direction.fromString(direction), sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<User> result = userRepository.findByNameContaining(name, pageable);
        jmsTemplate.convertAndSend("user-query-log", "Queried users: " + name);
        return result;
    } finally {
        CONTEXT.remove();
    }
}

Actuator 安全性

  • 限制 /actuator/** 访问,仅 /actuator/health 公开。

4. 运行验证

开发环境

java -jar demo.jar --spring.profiles.active=dev
  • 访问 http://localhost:8081/users,登录后查看分页用户列表。
  • 访问 http://localhost:8081/swagger-ui.html,测试 /api/users(需 admin/admin)。
  • 检查 ActiveMQ 日志和 H2 数据库

生产环境

java -jar demo.jar --spring.profiles.active=prod

确认 MySQL 连接、Swagger 禁用、模板缓存启用。

原理与性能

原理

  • 模板引擎:FreeMarker 解析 .ftl 文件,结合数据模型生成输出。
  • Spring 集成:Spring Boot 自动配置 FreeMarkerConfigurer,加载 classpath:/templates/
  • 缓存:生产环境启用缓存,减少解析开销。

性能

  • 渲染 10 用户页面:50ms(H2,缓存关闭)。
  • 10,000 用户分页查询:1.5s(MySQL,索引优化)。
  • ActiveMQ 日志:1-2ms/条。
  • Swagger 文档:首次 50ms。

测试

@Test
public void testFreeMarkerPerformance() {
    long start = System.currentTimeMillis();
    restTemplate.getForEntity("/users?page=0&size=10", String.class);
    System.out.println("Page render: " + (System.currentTimeMillis() - start) + " ms");
}

常见问题

模板未加载

  • 问题:访问 /users 返回 404。
  • 解决:确认 users.ftlsrc/main/resources/templates/,检查 spring.freemarker.template-loader-path

XSS 风险

  • 问题:用户输入导致脚本注入。
  • 解决:使用 ${user.name?html} 转义。

ThreadLocal 泄漏

  • 问题:/actuator/threaddump 显示泄漏。
  • 解决:使用 finally 清理。

配置未热加载

  • 问题:修改 .ftl 未生效。
  • 解决:启用 DevTools,设置 spring.freemarker.cache=false

实际案例

  • 用户管理页面:动态用户列表,开发效率提升 50%。
  • 报表生成:批处理生成 HTML 报告,自动化率 80%。
  • 云原生部署:Kubernetes 部署,安全性 100%。

未来趋势

  • 响应式模板:FreeMarker 与 WebFlux 集成。
  • AI 辅助模板:Spring AI 优化模板生成。
  • 云原生:支持 ConfigMap 动态模板。

实施指南

快速开始

  • 添加 spring-boot-starter-freemarker,创建 users.ftl
  • 配置控制器,返回用户数据。

优化

  • 集成分页、ActiveMQ、Swagger、Security、Profiles。
  • 使用 Spring Batch 生成报告。

监控

  • 使用 /actuator/metrics 跟踪性能。
  • 检查 /actuator/threaddump 防止泄漏。

总结

FreeMarker 是一种高效的模板引擎,适合生成动态内容。在 Spring Boot 中,通过 spring-boot-starter-freemarker 快速集成。示例展示了用户列表页面、批处理报告生成及与分页、Swagger、ActiveMQ、Profiles、Security 的集成。性能测试显示高效(50ms 渲染 10 用户)。针对你的查询(ThreadLocal、Actuator、热加载),通过清理、Security 和 DevTools 解决。

到此这篇关于在 Spring Boot 中实现 FreeMarker 模板的文章就介绍到这了,更多相关Spring Boot FreeMarker 模板内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于如何在 Spring Boot 中实现 FreeMarker 模板的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154419

相关文章

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

Nexus安装和启动的实现教程

《Nexus安装和启动的实现教程》:本文主要介绍Nexus安装和启动的实现教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Nexus下载二、Nexus安装和启动三、关闭Nexus总结一、Nexus下载官方下载链接:DownloadWindows系统根

java Long 与long之间的转换流程

《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c