Backend Development 10 min read

Developing a Custom SpringBoot Starter for Global Encryption/Decryption

This article explains the concepts behind SpringBoot Starters, walks through the creation of a custom starter that provides global request/response encryption and decryption using SM2, shows the project structure, key configuration files, core code, testing steps, and subsequent optimizations.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Developing a Custom SpringBoot Starter for Global Encryption/Decryption

The purpose of this guide is to introduce SpringBoot Starter concepts, demonstrate how to build a custom starter that adds global encryption/decryption, describe the testing workflow, and suggest optimizations.

SpringBoot Starter Overview

A SpringBoot Starter packages a set of related dependencies to simplify configuration and initialization, enabling rapid development of specific functional modules while promoting reuse and consistency across projects.

Development Process

To inject a custom starter into SpringBoot, create the necessary resources under src/main/resources/META-INF/spring.factories and define the auto‑configuration class.

<dependency>
    <groupId>com.xbhog</groupId>
    <artifactId>globalValidation-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

The starter project layout looks like:

demo-spring-boot-starter
└── src
    └── main
        └── java
            └── com.xbhog
                ├── DemoBean.java
                └── DemoBeanConfig.java
        └── resources
            └── META-INF
                └── spring.factories

In spring.factories register the auto‑configuration class:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.xbhog.DemoBeanConfig

Example configuration class:

@Slf4j
@Configuration
public class DemoBeanConfig {
    @Bean
    public DemoBean getDemo() {
        log.info("已经触发了配置类,正在初始化DemoBean...");
        return new DemoBean();
    }
}

public class DemoBean {
    public void getDemo() {
        log.info("方法调用成功");
    }
}

After packaging, import the starter into a test project via Maven and verify its functionality.

Custom Global Encryption/Decryption Starter

The starter is designed to handle POST request bodies using @ComponentScan , RequestBodyAdvice/ResponseBodyAdvice , and custom annotations. It intercepts requests in beforeBodyRead and responses in beforeBodyWrite to perform decryption and encryption respectively.

@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class
> converterType) throws IOException {
    log.info("进入【RequestBodyDecryptAdvice】beforeBodyRead的操作,方法:{}", parameter.getMethod());
    SecuritySupport securitySupport = parameter.getMethodAnnotation(SecuritySupport.class);
    assert securitySupport != null;
    ContextHolder.setCryptHolder(securitySupport.securityHandler());
    String original = IOUtils.toString(inputMessage.getBody(), Charset.defaultCharset());
    String handler = securitySupport.securityHandler();
    String plainText = original;
    if (StringUtils.isNotBlank(handler)) {
        SecurityHandler securityHandler = SpringContextHolder.getBean(handler, SecurityHandler.class);
        plainText = securityHandler.decrypt(original);
    }
    return new MappingJacksonInputMessage(IOUtils.toInputStream(plainText, Charset.defaultCharset()), inputMessage.getHeaders());
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    log.info("进入【ResponseBodyEncryptAdvice】beforeBodyWrite的操作,方法:{}", returnType.getMethod());
    String cryptHandler = ContextHolder.getCryptHandler();
    SecurityHandler securityHandler = SpringContextHolder.getBean(cryptHandler, SecurityHandler.class);
    assert body != null;
    return securityHandler.encrypt(body.toString());
}

The default encryption uses the SM2 algorithm from the Hutool library. An issue with random key generation was solved by initializing the key pair once in a @PostConstruct method.

@PostConstruct
public void encryHolder() {
    KeyPair pair = SecureUtil.generateKeyPair("SM2");
    byte[] privateKey = pair.getPrivate().getEncoded();
    byte[] publicKey = pair.getPublic().getEncoded();
    log.info("生成的公钥:{}", publicKey);
    log.info("生成的私钥:{}", privateKey);
    sm2 = SmUtil.sm2(privateKey, publicKey);
}

The starter also provides a configurable SecuritySupport annotation to specify a custom SecurityHandler implementation.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SecuritySupport {
    String securityHandler() default "securityHandlerImpl";
    String exceptionResponse() default "";
}

Testing

In a test application, add the starter dependency and invoke the encrypted endpoint. The logs confirm successful encryption/decryption.

@RestController
public class BasicController implements ApplicationContextAware {
    @Resource(name = "demoSecurityHandlerImpl")
    private SecurityHandler encryAdecry;
    private ApplicationContext applicationContext;

    @SecuritySupport
    @PostMapping("/hello")
    public String hello(@RequestBody String name) {
        return "Hello " + name;
    }

    @GetMapping("/configTest")
    public String configTest(@RequestParam("name") String name) {
        return encryAdecry.encrypt(name);
    }
}

Optimization

The project structure was refined, a GlobalProperties class was added for external configuration binding, and the default encryption implementation was updated to initialize the SM2 key pair based on a configurable algorithm type.

@Data
@ConfigurationProperties(GlobalProperties.PREFIX)
public class GlobalProperties {
    public static final String PREFIX = "encryption.type";
    private String algorithmType;
    private String key;
}

Finally, the custom starter can be published to a Maven repository for reuse across multiple services.

BackendJavaSpringBootEncryptiondecryptionStarter
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.