Mastering @BindParam in Spring Boot 3: Seamlessly Map Path and Query Parameters

This article explains how Spring Boot 3's new @BindParam annotation lets developers map mismatched path and query parameters to constructor arguments, supports @ModelAttribute, and shows how to create custom name resolvers for advanced parameter binding scenarios.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering @BindParam in Spring Boot 3: Seamlessly Map Path and Query Parameters

1. Introduction

Spring provides powerful and flexible support for handling interface parameters in Spring MVC and Spring WebFlux, allowing binding via annotations such as @RequestParam, @PathVariable, @RequestHeader, @RequestBody, etc.

@GetMapping("/{type}/{id}")
public Object bind(Param param) {
    return param;
}
public static record Param(Long id, String type) {}

This interface correctly binds the path variables to the Param object.

2. @BindParam Annotation

2.1 Path Parameters

@GetMapping("/{cate}/{id}")
public Object bindData(Param param) {
    return param;
}
public static record Param(Long id, @BindParam("cate") String type) {}

Here @BindParam maps the path variable cate to the constructor argument type.

2.2 Query Parameters

@GetMapping("/q")
public ResponseEntity<Object> q(Param param) {
    return ResponseEntity.ok(param);
}
public static record Param(@BindParam("pid") Long id,
                           @BindParam("cate") String type) {}

Access the endpoint with /q?pid=888&cate=xxxxooo to see the binding in action.

2.3 Support for @ModelAttribute

@GetMapping("/{cate}/{id}")
public ResponseEntity<Object> q(@ModelAttribute Param param) {
    return ResponseEntity.ok(param);
}
public static record Param(Long id, @BindParam("cate") String type) {}

The @BindParam annotation also works on constructor parameters of a method argument annotated with @ModelAttribute.

2.4 Custom Name Resolver

Define a custom resolver to interpret your own annotation:

public class PackParamNameResolver implements NameResolver {
    public String resolveName(MethodParameter parameter) {
        PackParam packParam = parameter.getParameterAnnotation(PackParam.class);
        if (packParam != null && StringUtils.hasText(packParam.value())) {
            return packParam.value();
        }
        return null;
    }
}

Register the resolver (locally in a controller or globally via @ControllerAdvice):

@InitBinder
public void init(WebDataBinder binder) {
    binder.setNameResolver(new PackParamNameResolver());
}

Usage example with a custom annotation:

@GetMapping("/q")
public ResponseEntity<Object> q(Param param) {
    return ResponseEntity.ok(param);
}
public static record Param(Long id,
                           @PackParam("cate") String type) {}

The custom resolver can be extended to support SpEL expressions, e.g., @PackParam("#{${pack.param.name} + '-1'}").

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentSpring BootBindParamParameter Binding
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

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.