Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Using ThreadLocal for Thread-Specific Variables and DTOs in Java Applications

Tech 1

When the data submitted by the frontend differs significantly from the corresponding properties in the entity class, its advisable to use Data Transfer Objects (DTOs) to encapsulate the data.

In the service layer, where data transmission is required, you can use the following method to copy properties between types:

BeanUtils.copyProperties(frontendDTO, targetObject);

To retrieve the account ID associated with the method execution, ThreadLocal can be employed as a thread-specific variable. This allows you to obtain the current user's ID by setting it in an interceptor and then accessing it in the service layer using BaseContext.getCurrentId(). Here is an example implementation:

public class BaseContext {
    private static final ThreadLocal<Long> userThreadLocal = new ThreadLocal<>();

    public static void setCurrentUserId(Long userId) {
        userThreadLocal.set(userId);
    }

    public static Long getCurrentUserId() {
        return userThreadLocal.get();
    }

    public static void clearCurrentUserId() {
        userThreadLocal.remove();
    }
}

Additional Application of ThreadLocal: Addressing Date Format Issues in Pagination Modules

When returning JSON data to the frontend, date-time parameters may sometimes appear as array types, which is not the desired format. Here are two methods to resolve this issue:

Method 1: Add annotations to the properties

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.time.LocalDateTime;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    private String username;
    private String name;
    private String password;
    private String phone;
    private String sex;
    private String idNumber;
    private Integer status;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;

    private Long createUser;
    private Long updateUser;
}

Method 2: Add a custom converter to the Spring MVC message converter container

This involves concepts of serialization and deserialization. Below is an example configuration:

// WebMvcConfiguration: This class extends WebMvcConfigurationSupport for message converters

/**
 * Description: Extends MVC message converters
 */
@ApiOperation("Extend MVC message converters")
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    // Create a message converter
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

    // Set a custom object mapper for the message converter
    converter.setObjectMapper(new CustomObjectMapper());

    // Add the custom message converter to the MVC converters list
    converters.add(0, converter);
}

Serialization and Deserialization Code

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;

/**
 * Object Mapper: Based on Jackson for converting Java objects to JSON and vice versa.
 * Parsing JSON to Java objects is called deserialization.
 * Generating JSON from Java objects is called serialization.
 */
public class CustomObjectMapper extends ObjectMapper {
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public CustomObjectMapper() {
        super();
        // Do not throw exceptions on unknown properties
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        // Handle missing properties during deserialization
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        SimpleModule dateTimeModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        // Register the module with custom serializers and deserializers
        this.registerModule(dateTimeModule);
    }
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.