Java开发必看:@JsonFormat、@DateTimeFormat、@JSONField三兄弟的恩怨情仇(附避坑指南)

# Java开发必看:@JsonFormat、@DateTimeFormat、@JSONField三兄弟的恩怨情仇(附避坑指南) 如果你在Java后端开发中处理过日期时间,大概率遇到过这样的场景:前端传过来的日期字符串,后端死活解析不了,或者数据库查出来的时间,返回给前端时格式变得面目全非。这时候,你可能会在DTO的字段上加上各种注解——@JsonFormat、@DateTimeFormat、@JSONField,但有时候管用,有时候又莫名其妙失效。这三个注解就像三个性格迥异的兄弟,虽然都姓“日期格式化”,但各有各的脾气和适用场合,用错了地方,项目里就会埋下各种坑。 这篇文章,我们不打算照本宣科地罗列API文档,而是从一个真实的项目迭代故事讲起。假设你接手了一个正在从Spring MVC向Spring Boot迁移、同时JSON框架从Fastjson逐步切换到Jackson的老项目。在这个混杂的生态里,这三个注解的“恩怨情仇”会体现得淋漓尽致。我们会深入它们的“出身背景”、行为模式,并通过一系列可复现的代码案例,帮你彻底理清它们的分工与协作,最终形成一套清晰、可落地的日期处理最佳实践。无论你是刚接触Spring Boot不久,还是已经踩过一些坑的中级开发者,这篇文章都能帮你构建一个更稳固的知识体系。 ## 1. 从一次线上故障说起:混乱的日期格式 去年我参与维护一个电商后台系统,就曾因为日期注解的混用,引发过一次不大不小的线上问题。订单列表接口突然返回了大量`"createTime": "2024-05-20T08:30:00"`这样的数据,前端直接报错,因为前端组件期望的是`"2024-05-20 08:30:00"`。排查后发现,一个新同事在某个订单查询的DTO里,给`LocalDateTime`字段同时加上了`@JsonFormat`和`@JSONField`,但两个注解的`pattern`格式不一致,而项目里又同时配置了Jackson和Fastjson的HttpMessageConverter,导致序列化时行为不可预测。 这个案例暴露出的核心问题是:**开发者往往只记住了注解能“格式化日期”,却忽略了它们背后所代表的框架体系和生效时机**。要避免这类问题,我们必须先摸清这“三兄弟”的底细。 ### 1.1 出身决定立场:框架归属是根本差异 这三个注解最本质的区别,在于它们来自不同的“家族”,服务于不同的技术栈。 * **@JsonFormat:Jackson家族的“外交官”** 它来自`jackson-annotations`包,是Jackson JSON处理库的“亲儿子”。Spring Boot默认就集成了Jackson,所以在纯Spring Boot项目中,它是最常见、最“正统”的日期序列化/反序列化方案。它的核心职责是**在Java对象与JSON字符串相互转换时,对日期格式进行约定**。 * **@DateTimeFormat:Spring MVC的“门卫”** 它来自Spring Framework核心的`spring-context`包。它的工作场景更早,发生在HTTP请求参数绑定到Controller方法入参的阶段。它不关心JSON,主要处理`application/x-www-form-urlencoded`(表单提交)或`multipart/form-data`格式的数据,以及URL查询参数(`@RequestParam`)。你可以把它理解为**专门负责把前端传来的、形如`“2024-05-20”`的普通字符串,转换成Controller方法里你想要的`LocalDate`对象**。 * **@JSONField:Fastjson家族的“多面手”** 它来自阿里巴巴的Fastjson库。功能和`@JsonFormat`高度重叠,都是处理JSON序列化的。如果你的项目历史包袱重,或者团队习惯使然,还在使用Fastjson作为主要的JSON处理器,那么你就得用它。它比`@JsonFormat`功能更多,除了格式化日期,还能控制字段名映射、序列化开关等。 为了更直观地理解它们在请求-响应流程中的位置,我画了下面这个简单的对比表: | 注解 | 所属框架 | 主要作用阶段 | 处理的数据格式 | 典型应用场景 | | :--- | :--- | :--- | :--- | :--- | | **@DateTimeFormat** | Spring Framework | **请求参数绑定阶段** | `application/x-www-form-urlencoded`, `multipart/form-data`, URL查询参数 | 处理表单提交、GET请求参数 | | **@JsonFormat** | Jackson | **HTTP消息体转换阶段** (JSON<->Object) | `application/json` | RESTful API接口的请求/响应体 | | **@JSONField** | Fastjson | **HTTP消息体转换阶段** (JSON<->Object) | `application/json` | 使用Fastjson的RESTful API接口 | > **提示**:一个常见的误解是,在接收JSON请求的`@RequestBody`对象上使用`@DateTimeFormat`。这是完全无效的,因为`@RequestBody`的解析是由`HttpMessageConverter`(如`MappingJackson2HttpMessageConverter`)完成的,`@DateTimeFormat`根本不会被触发。 ### 1.2 环境准备:搭建一个可验证的沙箱 理论说再多,不如动手跑一跑。我们创建一个简单的Spring Boot 3.x项目来验证所有想法。核心依赖如下,重点关注Jackson、Fastjson和Web模块: ```xml <dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Lombok简化代码 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- Jackson对Java 8时间API的支持(关键!) --> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <!-- Fastjson2 --> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.32</version> </dependency> <!-- 测试 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> ``` ## 2. 深入剖析“大哥”@JsonFormat:Jackson的秩序维护者 Jackson作为Spring Boot的默认选择,`@JsonFormat`是处理JSON日期最标准的姿势。但用好它,有几个细节必须抠清楚。 ### 2.1 核心属性与实战陷阱 `@JsonFormat`最常用的属性就两个:`pattern`和`timezone`。但恰恰是简单的`timezone`,坑了无数人。 ```java import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.time.LocalDateTime; import java.util.Date; @Data public class OrderDTO { // 示例1:指定格式和时区 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime createTime; // 示例2:对于java.util.Date,时区至关重要 @JsonFormat(pattern = "yyyy/MM/dd", timezone = "Asia/Shanghai") private Date payDate; // 示例3:不指定时区 - 危险!行为取决于服务器默认时区 @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate deliveryDate; } ``` 写一个简单的Controller测试一下: ```java @RestController @RequestMapping("/jackson") public class JacksonDemoController { @PostMapping("/order") public OrderDTO createOrder(@RequestBody OrderDTO orderDTO) { // 模拟业务处理 System.out.println("接收到订单时间:" + orderDTO.getCreateTime()); // 返回对象,观察序列化结果 return orderDTO; } } ``` 使用`curl`或者Postman发送请求: ```bash curl -X POST http://localhost:8080/jackson/order \ -H "Content-Type: application/json" \ -d '{"createTime":"2024-05-20 14:30:00", "payDate":"2024/05/20"}' ``` 你会看到返回的JSON里,时间格式如你所设。但如果你把`timezone = "GMT+8"`去掉,并且你的服务器运行在UTC时区,那么返回给前端的时间可能会是`"2024-05-20 06:30:00"`,**凭空少了8小时**。这是`@JsonFormat`的第一个大坑:**对于`java.util.Date`和`java.time.Instant`这种带时区概念的类,不指定`timezone`就会使用Jackson的默认时区(通常是UTC)**。而`LocalDateTime`本身不包含时区信息,序列化结果不受此影响,但反序列化时若字符串不含时区,也会按默认时区解析,逻辑上可能出错。 > **注意**:`LocalDateTime`、`LocalDate`等类型在序列化为字符串时,`timezone`属性不影响输出结果,因为它们没有时区概念。但在反序列化时,如果输入的字符串隐含了时区(比如带`Z`或时区偏移),Jackson需要知道如何转换到系统默认时区,此时全局配置的`timezone`或`@JsonFormat`的`timezone`会起作用。最安全的做法是,无论用哪种日期类型,都显式指定`timezone`。 ### 2.2 与全局配置的博弈 很多团队为了统一格式,会在全局配置Jackson。这时,注解和全局配置谁说了算? ```java @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); JavaTimeModule javaTimeModule = new JavaTimeModule(); // 全局设置LocalDateTime格式 javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"))); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"))); mapper.registerModule(javaTimeModule); mapper.setTimeZone(TimeZone.getTimeZone("GMT+8")); return mapper; } } ``` 配置了全局格式后,如果DTO字段上没有`@JsonFormat`注解,就会采用全局的`yyyy/MM/dd HH:mm`格式。**但如果字段上加了`@JsonFormat`,那么注解的优先级高于全局配置**。这给了我们灵活性:大部分字段用全局格式,少数特殊字段用注解定制。 ### 2.3 真实案例:MyBatis-Plus与Jackson的协作 在实际项目中,DTO经常要和数据库实体(Entity)互相转换。我们结合MyBatis-Plus来看一个常见场景。 ```java // Entity 实体类 @Data @TableName("t_order") public class Order { @TableId(type = IdType.AUTO) private Long id; private LocalDateTime createTime; // 数据库存储的datetime // ... 其他字段 } // DTO 数据传输对象 @Data public class OrderVO { @JsonFormat(pattern = "yyyy年MM月dd日 HH时mm分") private LocalDateTime createTime; // 希望以更友好的格式展示 // ... 其他字段 } // Service层 @Service public class OrderService { public OrderVO getOrderDetail(Long id) { Order order = orderMapper.selectById(id); // 使用BeanUtils或MapStruct进行拷贝 OrderVO vo = new OrderVO(); BeanUtils.copyProperties(order, vo); // createTime是LocalDateTime,直接拷贝 return vo; // 返回时,Jackson会根据@JsonFormat序列化 } } ``` 这里的关键在于,**`@JsonFormat`的生效时机是在对象被序列化为JSON的那一刻**。在Service层,`OrderVO`对象里的`createTime`还是`LocalDateTime`类型,拷贝操作没有问题。只有当这个对象通过Controller返回,被`MappingJackson2HttpMessageConverter`处理时,`@JsonFormat`才会起作用,将其格式化为指定的字符串。这种设计实现了数据层(纯对象)与展示层(格式化字符串)的解耦。 ## 3. 剖析“二哥”@DateTimeFormat:Spring的参数守门员 如果说`@JsonFormat`管的是JSON“体内”的事,那`@DateTimeFormat`管的就是HTTP请求“表皮”的事。它的工作更前置,专门处理那些不是JSON的请求数据。 ### 3.1 表单提交与URL参数的解析专家 想象一个用户在前端页面填写表单,提交出生日期和预约时间。后端接口可能这样写: ```java @PostMapping("/profile") public String updateUserProfile(@ModelAttribute UserProfileForm form) { // 处理表单数据 return "success"; } @Data public class UserProfileForm { @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate birthday; @DateTimeFormat(pattern = "HH:mm") private LocalTime appointmentTime; @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) // 支持ISO8601格式 private LocalDateTime registerTime; } ``` 或者从URL获取日期参数: ```java @GetMapping("/events") public List<Event> getEvents( @RequestParam @DateTimeFormat(pattern = "yyyyMMdd") LocalDate date) { return eventService.findByDate(date); } // 访问 /events?date=20240520 ``` `@DateTimeFormat`在这里大显身手,它能将字符串`"2024-05-20"`自动转换成`LocalDate`对象。它的`iso`属性支持标准的ISO格式,比如`ISO.DATE_TIME`对应`"2024-05-20T14:30:00"`,这在一些标准化接口中很有用。 ### 3.2 与@JsonFormat的常见混淆场景 混淆最常发生在`@RequestBody`上。看下面这个错误示例: ```java // ❌ 错误用法:@DateTimeFormat对@RequestBody无效 @PostMapping("/wrong") public void wrongExample(@RequestBody @Valid RequestDTO dto) { // ... } @Data public class RequestDTO { @DateTimeFormat(pattern = "yyyy-MM-dd") // 这个注解会被Jackson忽略! private LocalDate startDate; } ``` 当你用JSON(`application/json`)发送请求时,Spring会使用Jackson(或Fastjson)的`HttpMessageConverter`来解析请求体。这个过程**根本不会经过**`@DateTimeFormat`注解的处理逻辑。`@DateTimeFormat`是Spring `DataBinder`在绑定**非请求体参数**(如`@ModelAttribute`、`@RequestParam`)时使用的。所以,对于`@RequestBody`,你应该用`@JsonFormat`(Jackson)或`@JSONField`(Fastjson)。 ### 3.3 全局配置与自定义转换器 和Jackson一样,我们也可以为Spring MVC配置全局的日期格式,避免在每个字段上重复注解。 ```java @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); // 设置全局格式 registrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd")); registrar.setTimeFormatter(DateTimeFormatter.ofPattern("HH:mm:ss")); registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); registrar.registerFormatters(registry); } } ``` 配置之后,对于`@ModelAttribute`或`@RequestParam`中的`LocalDate`、`LocalTime`、`LocalDateTime`参数,如果没有用`@DateTimeFormat`指定格式,就会默认使用上面配置的格式进行解析。这大大简化了代码。 ## 4. 剖析“三弟”@JSONField:Fastjson的灵活管家 在那些历史项目或特定技术选型的团队中,Fastjson依然占有一席之地。`@JSONField`作为其核心注解,功能比`@JsonFormat`更丰富,但也带来了更多的配置项和潜在的混乱。 ### 4.1 不仅仅是日期格式化 `@JSONField`的`format`属性用于日期格式化,这点和`@JsonFormat`的`pattern`类似。但它的能力远不止于此。 ```java import com.alibaba.fastjson2.annotation.JSONField; import lombok.Data; import java.time.LocalDateTime; @Data public class ProductDTO { // 1. 日期格式化 @JSONField(format = "yyyy|MM|dd") private LocalDateTime manufactureDate; // 2. 字段名映射:Java字段名与JSON字段名不同 @JSONField(name = "product_name") private String productName; // 3. 序列化控制:该字段不序列化到JSON @JSONField(serialize = false) private String internalCode; // 4. 反序列化控制:JSON中的该字段不解析到Java对象 @JSONField(deserialize = false) private String readOnlyField; // 5. 字段顺序控制 @JSONField(ordinal = 1) private Integer id; } ``` ### 4.2 让Fastjson接管Spring Boot的JSON处理 Spring Boot默认使用Jackson。要启用Fastjson,需要一些配置。这里有个关键点:**不要完全替换掉Jackson,除非你确定所有依赖(如Spring Boot Actuator、Spring Doc OpenAPI)都兼容Fastjson**。更稳妥的方式是让Fastjson和Jackson共存,并优先使用Fastjson。 ```java @Configuration public class FastjsonConfig { @Bean @Primary // 设置为最高优先级 public HttpMessageConverter<?> fastJsonHttpMessageConverter() { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); FastJsonConfig config = new FastJsonConfig(); config.setDateFormat("yyyy-MM-dd HH:mm:ss"); // 全局日期格式 config.setCharset(StandardCharsets.UTF_8); // 配置序列化特性 config.setWriterFeatures( JSONWriter.Feature.PrettyFormat, // 美化输出,生产环境可关闭 JSONWriter.Feature.WriteMapNullValue // 输出空字段 ); config.setReaderFeatures(JSONReader.Feature.SupportAutoType); converter.setFastJsonConfig(config); converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON)); return converter; } } ``` 配置好后,Spring MVC在处理`application/json`时就会优先使用这个`FastJsonHttpMessageConverter`,`@JSONField`注解也就生效了。 ### 4.3 混用框架下的“精神分裂”问题 这是最棘手的场景:项目里既有Jackson又有Fastjson的依赖,可能因为不同第三方库引入了不同的JSON处理器。此时,如果DTO上同时标记了`@JsonFormat`和`@JSONField`,会发生什么? ```java // 危险操作:同时使用两个注解 @Data public class MixedDTO { @JsonFormat(pattern = "yyyy/MM/dd", timezone = "GMT+8") @JSONField(format = "dd-MM-yyyy") private LocalDate someDate; } ``` 结果取决于最终是哪个`HttpMessageConverter`处理了这个对象。如果Jackson的转换器先工作,就按`@JsonFormat`的格式输出;如果Fastjson的转换器先工作,就按`@JSONField`的格式输出。在Spring Boot中,`@Primary`注解可以指定优先级,但更根本的解决方法是**统一技术栈**,移除不必要的JSON库依赖,或者在团队内建立明确的规范,禁止这种混用。 一个实用的排查技巧是,在Controller方法里打印`HttpMessageConverter`列表: ```java @Autowired private RequestMappingHandlerAdapter handlerAdapter; @PostConstruct public void checkConverters() { List<HttpMessageConverter<?>> converters = handlerAdapter.getMessageConverters(); converters.forEach(c -> System.out.println(c.getClass().getName())); } ``` ## 5. 终极对决与选型指南:如何做出明智选择? 经过前面的详细拆解,我们现在可以站在更高的维度,为这三个注解的使用制定清晰的策略。 ### 5.1 功能对比与决策矩阵 下表总结了它们在关键维度上的差异,可以作为你的速查手册: | 特性维度 | @JsonFormat (Jackson) | @DateTimeFormat (Spring) | @JSONField (Fastjson) | | :--- | :--- | :--- | :--- | | **核心职责** | JSON序列化/反序列化 | 请求参数绑定(表单/URL) | JSON序列化/反序列化 | | **生效阶段** | `HttpMessageConverter`处理请求/响应体时 | Spring `DataBinder`绑定非请求体参数时 | `HttpMessageConverter`处理请求/响应体时 | | **日期格式化** | `pattern`, `timezone`, `shape` | `pattern`, `iso`, `style` | `format` | | **额外能力** | 相对较少,专注日期 | 仅限日期参数解析 | **强大**:`name`(别名), `serialize`/`deserialize`(序列化开关), `ordinal`(顺序) | | **默认集成** | **Spring Boot默认** | Spring Framework内置 | 需手动引入和配置 | | **性能考量** | 性能优秀,生态成熟 | 仅参数解析,开销小 | **以解析速度见长** | | **安全性记录** | 良好 | 良好 | 旧版本有安全漏洞史,Fastjson2已重构 | ### 5.2 根据项目场景的选型策略 基于以上对比,我推荐以下决策路径: 1. **全新Spring Boot项目(强推荐)**: * **首选组合:`@JsonFormat` + `@DateTimeFormat`**。 * **理由**:Spring Boot原生支持,无需额外配置。用`@JsonFormat`处理所有`@RequestBody`和`@ResponseBody`的JSON日期。用`@DateTimeFormat`处理`@RequestParam`、`@PathVariable`以及`@ModelAttribute`中的日期参数。 * **动作**:引入`jackson-datatype-jsr310`依赖,并在`application.yml`或配置类中做好Jackson的全局配置。 2. **遗留项目或强制使用Fastjson的项目**: * **首选:`@JSONField`**。 * **理由**:既然技术栈已定,就统一使用其配套工具。可以利用其丰富的功能,如字段别名、序列化控制等。 * **注意**:务必升级到**Fastjson2**,并仔细评估其与其他组件(如Spring Security、OpenAPI)的兼容性。 3. **需要处理多种数据格式的复杂接口**: * 同一个DTO字段,既可能从JSON反序列化,也可能从表单参数绑定。 * **解决方案**:可以**同时注解**,它们互不干扰。 ```java @Data public class ComplexDTO { // 同时支持JSON请求体和表单参数 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime flexibleTime; } ``` * **提醒**:确保格式一致,避免混淆。 ### 5.3 避坑指南与最佳实践 结合我踩过的坑,总结几条血泪经验: * **时区!时区!时区!**:处理`Date`或`Instant`时,**永远显式指定`timezone`**。全局配置`spring.jackson.time-zone=GMT+8`是个好习惯。 * **坚持使用Java 8+的日期时间API**:彻底抛弃`java.util.Date`和`Calendar`,拥抱`LocalDateTime`、`LocalDate`、`ZonedDateTime`。它们更清晰、线程安全,且与数据库(如MySQL 8+、PostgreSQL)的类型映射更自然。 * **全局配置为主,局部注解为辅**:在`application.yml`或配置类中定义项目统一的日期格式(如`yyyy-MM-dd HH:mm:ss`)。只有少数需要特殊格式的字段,才使用注解覆盖。 * **保持技术栈纯洁**:尽量避免在同一个项目中混用Jackson和Fastjson作为HTTP消息转换器。如果因依赖冲突无法避免,使用`@Primary`明确指定一个默认的,并在团队文档中写清楚。 * **为日期字段编写单元测试**:这是成本最低的保障。测试用例应覆盖:正常格式解析、错误格式处理、空值处理、时区转换。 ```java @Test public void testOrderDTODeserialization() throws Exception { String json = "{\"createTime\":\"2024-05-20 14:30:00\"}"; ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); OrderDTO dto = mapper.readValue(json, OrderDTO.class); assertThat(dto.getCreateTime()).isEqualTo(LocalDateTime.of(2024, 5, 20, 14, 30, 0)); } ``` * **关注日志中的日期序列化警告**:如果看到类似`“Cannot serialize instance of `java.time.LocalDateTime`”`的警告,说明缺少`jackson-datatype-jsr310`模块,务必补上依赖。 说到底,`@JsonFormat`、`@DateTimeFormat`和`@JSONField`这三个“兄弟”并没有好坏之分,只有适用场景之别。理解它们背后的框架原理和生效机制,就像摸清了每个人的脾气秉性。在Spring Boot成为事实标准的今天,`@JsonFormat`+`@DateTimeFormat`的组合无疑是最高效、最省心的选择。而对于那些仍在Fastjson生态中的项目,深入掌握`@JSONField`的每一项特性,也能帮你把日期处理玩得游刃有余。最重要的,是建立起一套适合自己团队的、统一的日期处理规范,让代码里的时间,再也不“错乱”。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

Python内容推荐

Java避坑指南:Java高手笔记代码篇.rar

Java避坑指南:Java高手笔记代码篇.rar

Java避坑指南

JsonFormat与@DateTimeFormat注解实例解析

JsonFormat与@DateTimeFormat注解实例解析

主要介绍了JsonFormat与@DateTimeFormat注解实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

常用JSON注解区别[可运行源码]

常用JSON注解区别[可运行源码]

本文详细介绍了三种常用的JSON相关注解:@JsonFormat、@JsonField和@DateTimeFormat的区别与用法。@JsonFormat主要用于控制后端返回给前端的日期格式,需注意时区设置以避免时间偏差;@JsonField是阿里巴巴FastJSON框架中的注解,兼具前后端数据格式处理功能,其format属性可替代@JsonFormat;@DateTimeFormat则是Spring框架自带的注解,用于处理前端传入的日期数据。文章总结指出,@DateTimeFormat处理前端到后端数据,@JsonFormat处理后端到前端数据,而@JsonField兼具两者功能,因此更推荐使用@JsonField。

关于fastjson的@JSONField注解的一些问题(详解)

关于fastjson的@JSONField注解的一些问题(详解)

下面小编就为大家带来一篇关于fastjson的@JSONField注解的一些问题(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

NEO4J安装避坑指南

NEO4J安装避坑指南

NEO4J安装避坑指南

如何在Spring Boot应用中优雅的使用Date和LocalDateTime的教程详解

如何在Spring Boot应用中优雅的使用Date和LocalDateTime的教程详解

主要介绍了如何在Spring Boot应用中优雅的使用Date和LocalDateTime,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

java常用必坑指南大法

java常用必坑指南大法

java必坑指南,如何巧妙的避免空指针,合理的使用optional,计算集合接口常见坑

计算机求职2025年简历优化与高频面试题详解:技术栈匹配及避坑指南

计算机求职2025年简历优化与高频面试题详解:技术栈匹配及避坑指南

内容概要:本文档《2025计算机求职面经大全》主要针对计算机行业求职者,提供了从简历优化到高频面试题库,再到面试避坑指南的全方位指导。简历优化部分强调技术栈匹配、关键词调整、项目经验量化和技术作品展示的重要性。高频题库涵盖Java核心、数据库、算法、系统设计四个领域,详细列出各领域的重点考察知识点及其具体实例,如HashMap原理、JVM内存模型、MySQL索引优化等。避坑指南列举了面试中最应避免的五种行为,包括简历造假、答非所问、过度谦虚、薪资乱报和离职原因踩雷。最后附有30套真题答案速查表,按Java、算法、前端、系统架构四个方向分类,提供具体真题示例。 适合人群:计算机相关专业毕业生或有1-3年工作经验的技术人员,尤其是准备跳槽或找工作的程序员。 使用场景及目标:①帮助求职者优化简历,提高通过初筛的概率;②掌握2025年各大厂高频面试题的核心知识点;③避免面试中的常见错误,提升面试表现;④通过真题练习,增强实际解决问题的能力。 其他说明:文档内容整合了2025年各大厂的真题及技术社区的高赞解析,覆盖90%以上的考点,旨在为求职者提供全面而实用的参考。

Java开发异常处理最佳实践与避坑指南:分类、资源管理、自定义异常及日志规范综合应用

Java开发异常处理最佳实践与避坑指南:分类、资源管理、自定义异常及日志规范综合应用

内容概要:本文系统总结了Java异常处理的最佳实践与避坑指南,涵盖异常分类、try-catch-finally和try-with-resources的正确用法、自定义异常设计、生产环境日志规范以及高频错误场景的对比分析。重点强调异常处理的核心原则:精准捕获、资源自动释放、异常链传递、日志上下文记录与敏感信息脱敏,并通过大量反例与正例对比帮助开发者识别常见陷阱。同时推荐使用SLF4J+Logback日志框架结合MDC实现全链路日志追踪,提升问题定位效率。; 适合人群:具备一定Java开发经验,工作1-3年的后端研发人员,尤其是正在参与企业级项目开发、关注代码健壮性和生产环境稳定性的工程师。; 使用场景及目标:①掌握Java异常体系结构及不同异常类型的处理策略;②正确使用try-with-resources管理资源,避免内存泄漏;③设计规范的自定义业务异常体系并与全局异常处理器集成;④编写符合生产要求的异常日志,支持快速排查与监控告警; 阅读建议:此资源不仅提供理论指导,更配有可复用的代码模板和真实场景示例,建议结合实际项目进行对照优化,在开发中主动规避文中列出的“反例”模式,并落地错误码统一管理、日志分级与上下文绑定等最佳实践。

java三大框架学习笔记总结 新手必看

java三大框架学习笔记总结 新手必看

java三大框架ssh学习笔记总结 新手必看

java开发必去的网站

java开发必去的网站

相信能对你JAVA的学习之路,又所帮助。

Delphi6开发者指南附书源码

Delphi6开发者指南附书源码

经典书籍附书源码

代码工厂避坑指南[代码]

代码工厂避坑指南[代码]

本文详细介绍了在代码工厂中进行代码托管的完整流程及注意事项。首先,需要确保能访问代码工厂的443端口,并配置好Java环境,包括安装Java 1.8和Java 17,并正确设置环境变量。接着,通过浙政钉扫码登录代码工厂平台,创建研发代码服务组并关联应用。然后,生成Access Tokens,使用Git Bash克隆代码仓库并上传代码。此外,还涉及修改配置文件、运行Maven上传工具以及构建流水线等步骤。最后,提供了常见问题的解决方案,并提醒验签时需使用CMD而非Powershell。整个流程清晰,步骤详细,适合开发者参考。

Android开发指南中文版【新手必看】

Android开发指南中文版【新手必看】

Android开发指南中文版【新手必看】,新手不用发愁啦

精选_基于JAVA的葫芦娃兄弟游戏_源码打包

精选_基于JAVA的葫芦娃兄弟游戏_源码打包

基于JAVA的葫芦娃兄弟游戏

Java中增强for循环的实现原理和坑详解

Java中增强for循环的实现原理和坑详解

增强的for循环是在传统的for循环中增加的强大的迭代功能的循环,是在jdk1.5之后提出来的。下面这篇文章主要给大家介绍了关于Java中增强for循环的实现原理和坑的相关资料,需要的朋友可以参考下

【boot-admin】微服务开发避坑指南 落地即用无套路!.zip

【boot-admin】微服务开发避坑指南 落地即用无套路!.zip

【boot-admin】微服务开发避坑指南 落地即用无套路!.zip

@JsonFormat的使用jackson-annotations

@JsonFormat的使用jackson-annotations

含有 jackson-annotations.jar 、 jackson-core.jar 、 jackson-databind.jar

RFID读写器开发指南-Java1

RFID读写器开发指南-Java1

1.前言41.1. 概述41.2. 适用设备41.3. 版权说明41.4. 读写基本流程53. 快速上手64. 连接说明84.1. RS232 连接 84.2.

【会员签到系统 + 新人实训】避坑指南 落地即用 2025 首发!.zip

【会员签到系统 + 新人实训】避坑指南 落地即用 2025 首发!.zip

【会员签到系统 + 新人实训】避坑指南 落地即用 2025 首发!.zip

最新推荐最新推荐

recommend-type

在Pycharm terminal中字体大小设置的方法

如下所示: file->settings->Editor->General->Console里面的console commands history size 以上这篇在Pycharm terminal中字体大小设置的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持软件开发网。 您可能感兴趣的文章:PyCharm中代码字体大小调整方法Pycharm使用之设置代码字体大小和颜色主题的教程用Pycharm实现鼠标滚轮控制字体大小的方法pycharm 使用心得(二)设置字体大小Pycharm 字体大小调整设置的方法实现
recommend-type

PyCharm中代码字体大小调整方法

在本篇文章里小编给大家分享了关于PyCharm中代码字体大小调整方法以及相关知识点,需要的朋友们学习下。
recommend-type

PyCharm设置注释字体颜色以及是否倾斜的操作

如下所示: File–>Settings–>Editor–> Color Scheme–>Language Defaults–>Comments–>Line conmment Italic是是否倾斜。 Blod是否加粗。 Foreground是字体颜色。 Background背景色。 补充知识:Pycharm默认注释字体大小不一的解决方法 再使用Pycharm的过程中我们可能会发现注释的字体大小不一的情况; 注释中文字大小不一 因为个人习惯或是为了方便学习和工作我们会希望将其设置统一。以下为笔者使用过的方法。因为直接上手图片更加直观所以直接上图。 一、第一步 二、第二步 三、第三步
recommend-type

PyCharm更改字体和界面样式的方法步骤

主要介绍了PyCharm更改字体和界面样式的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
recommend-type

Pycharm 字体大小调整设置的方法实现

主要介绍了Pycharm 字体大小调整的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
recommend-type

学生成绩管理系统C++课程设计与实践

资源摘要信息:"学生成绩信息管理系统-C++(1).doc" 1. 系统需求分析与设计 在进行学生成绩信息管理系统开发前,首先需要进行系统需求分析,这是确定系统开发目标与范围的过程。需求分析应包括数据需求和功能需求两个方面。 - 数据需求分析: - 学生成绩信息:需要收集学生的姓名、学号、课程成绩等数据。 - 数据类型和长度:明确每个数据项的数据类型(如字符串、整型等)和长度,例如学号可能是字符串类型且长度为一定值。 - 描述:详细描述每个数据项的意义,以确保系统能够准确处理。 - 功能需求分析: - 列出功能列表:用户界面应提供清晰的操作指引,列出所有可用功能。 - 查询学生成绩:系统应能通过学号或姓名查询学生的成绩信息。 - 增加学生成绩信息:允许用户添加未保存的学生成绩信息。 - 删除学生成绩信息:能够通过学号或姓名删除已经保存的成绩信息。 - 修改学生成绩信息:通过学号或姓名修改已有的成绩记录。 - 退出程序:提供安全退出程序的选项,并确保所有修改都已保存。 2. 系统设计 系统设计阶段主要完成内存数据结构设计、数据文件设计、代码设计、输入输出设计、用户界面设计和处理过程设计。 - 内存数据结构设计: - 使用链表结构组织内存中的数据,便于动态增删查改操作。 - 数据文件设计: - 选择文本文件存储数据,便于查看和编辑。 - 代码设计: - 根据功能需求,编写相应的函数和模块。 - 输入输出设计: - 设计简洁明了的输入输出提示信息和操作流程。 - 用户界面设计: - 用户界面应为字符界面,方便在命令行环境下使用。 - 处理过程设计: - 设计数据处理流程,确保每个操作都有明确的处理逻辑。 3. 系统实现与测试 实现阶段需要根据设计阶段的成果编写程序代码,并进行系统测试。 - 程序编写: - 完成系统设计中所有功能的程序代码编写。 - 系统测试: - 设计测试用例,通过测试用例上机测试系统。 - 记录测试方法和测试结果,确保系统稳定可靠。 4. 设计报告撰写 最后,根据系统开发的各个阶段,撰写详细的设计报告。 - 系统描述:包括问题说明、数据需求和功能需求。 - 系统设计:详细记录内存数据结构设计、数据文件设计、代码设计、输入/输出设计、用户界面设计、处理过程设计。 - 系统测试:包括测试用例描述、测试方法和测试结果。 - 设计特点、不足、收获和体会:反思整个开发过程,总结经验和教训。 时间安排: - 第19周(7月12日至7月16日)完成项目。 - 7月9日8:00到计算机学院实验中心(三楼)提交程序和课程设计报告。 指导教师和系主任(或责任教师)需要在文档上签名确认。 系统需求分析: - 使用表格记录系统需求分析的结果,包括数据项、数据类型、数据长度和描述。 - 分析数据项如学生成绩信息、状态器、链表节点等,确定其属性和行为。 以上就是文档中提到的学生成绩信息管理系统开发的关键知识点。开发此类系统需要熟练掌握C++编程基础,了解面向对象的程序设计思想,以及熟悉文件操作和链表等数据结构的应用。此外,良好的软件开发流程意识、测试意识和文档撰写能力也是必不可少的。
recommend-type

别再手动拖拽了!用Lumerical脚本批量创建FDTD仿真结构(附完整代码)

# 告别低效建模:Lumerical脚本自动化实战指南 在光子学仿真领域,时间就是科研生命线。当同行还在GUI界面里反复点击菜单时,你已经用脚本批量生成了20组参数化结构——这不是未来场景,而是每位FDTD用户都应该掌握的基础生产力革命。本文将彻底改变你与Lumerical的交互方式,从手动拖拽的农耕时代,跃迁到自动化建模的工业文明。 ## 1. 为何脚本建模是必然选择 2019年Nature Photonics的一项研究显示,科研工作者在仿真工具上平均浪费37%的时间在重复性操作上。对于需要参数扫描的纳米光学结构设计,这个数字可能更高。手动创建10个不同尺寸的纳米柱阵列意味着: -
recommend-type

Java邮件解析任务中,如何安全高效地提取HTML邮件内容并避免硬编码、资源泄漏和类型转换异常?

<think>我们被要求优化一段Java代码,该代码用于处理邮件(特别是来自特定发件人的构建通知邮件)。代码的主要问题包括: 1. 重复获取邮件内容:在检查MIME类型后,多次调用`msg[i].getContent()`,这可能导致性能问题或流关闭异常。 2. 类型转换问题:直接将邮件内容转换为`Multipart`而不进行类型检查,可能引发`ClassCastException`。 3. 代码结构问题:逻辑嵌套过深,可读性差,且存在重复代码(如插入邮件详情的操作在两个地方都有)。 4. 硬编码和魔法值:例如在解析HTML表格时使用了硬编码的索引(如list3.get(10)),这容易因邮件
recommend-type

RH公司应收账款管理优化策略研究

资源摘要信息:"本文针对RH公司的应收账款管理问题进行了深入研究,并提出了改进策略。文章首先分析了应收账款在企业管理中的重要性,指出其对于提高企业竞争力、扩大销售和充分利用生产能力的作用。然后,以RH公司为例,探讨了公司应收账款管理的现状,并识别出合同管理、客户信用调查等方面的不足。在此基础上,文章提出了一系列改善措施,包括完善信用政策、改进业务流程、加强信用调查和提高账款回收力度。特别强调了建立专门的应收账款回收部门和流程的重要性,并建议在实际应用过程中进行持续优化。同时,文章也意识到企业面临复杂多变的内外部环境,因此提出的策略需要根据具体情况调整和优化。 针对财务管理领域的专业学生和从业者,本文提供了一个关于应收账款管理问题的案例研究,具有实际指导意义。文章还探讨了信用管理和征信体系在应收账款管理中的作用,强调了它们对于提升企业信用风险控制和市场竞争能力的重要性。通过对比国内外企业在应收账款管理上的差异,文章总结了适合中国企业实际环境的应收账款管理方法和策略。" 根据提供的文件内容,以下是详细的知识点: 1. 应收账款管理的重要性:应收账款作为企业的一项重要资产,其有效管理关系到企业的现金流、财务健康以及市场竞争力。不良的应收账款管理会导致资金链断裂、坏账损失增加等问题,严重影响企业的正常运营和长远发展。 2. 应收账款的信用风险:在信用交易日益频繁的商业环境中,企业必须对客户信用进行评估,以便采取合理的信用政策,降低信用风险。 3. 合同管理的薄弱环节:合同是应收账款管理的法律基础,严格的合同管理能够保障企业权益,减少因合同问题导致的应收账款风险。 4. 客户信用调查:了解客户的信用状况对于预测和控制应收账款风险至关重要。企业需要建立有效的客户信用调查机制,识别和筛选信用良好的客户。 5. 应收账款回收策略:企业应建立有效的账款回收机制,包括定期的账款跟进、逾期账款的催收等。同时,建立专门的应收账款回收部门可以提升回收效率。 6. 应收账款管理流程优化:通过改进企业内部管理流程,如简化审批流程、提高工作效率等措施,能够提升应收账款的管理效率。 7. 应收账款管理策略的调整和优化:由于企业的内外部环境复杂多变,因此制定的管理策略需要根据实际情况进行动态调整和持续优化。 8. 信用管理和征信体系的作用:建立和完善企业内部信用管理体系和征信体系,有助于企业更好地控制信用风险,并在市场竞争中占据有利地位。 9. 对比国内外应收账款管理实践:通过研究国内外企业在应收账款管理上的不同做法和经验,可以借鉴先进的管理理念和方法,提升国内企业的应收账款管理水平。 综上所述,本文深入探讨了应收账款管理的多个方面,为RH公司乃至其他同类型企业提供了应收账款管理的改进方向和策略,对于财务管理专业的教育和实践都具有重要的参考价值。
recommend-type

新手别慌!用BingPi-M2开发板带你5分钟搞懂Tina Linux SDK目录结构

# 新手别慌!用BingPi-M2开发板带你5分钟搞懂Tina Linux SDK目录结构 第一次拿到BingPi-M2开发板时,面对Tina Linux SDK里密密麻麻的文件夹,我完全不知道从哪下手。就像走进一个陌生的大仓库,每个货架上都堆满了工具和零件,却找不到操作手册。这种困惑持续了整整两天,直到我意识到——理解目录结构比死记硬背每个文件更重要。 ## 1. 为什么SDK目录结构如此重要 想象你正在组装一台复杂的模型飞机。如果所有零件都混在一个箱子里,你需要花大量时间寻找每个螺丝和面板。但如果有分门别类的隔层,标注着"机身部件"、"电子设备"、"紧固件",组装效率会成倍提升。Ti