Backend Development 6 min read

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.

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

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

2. @BindParam Annotation

2.1 Path Parameters

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

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

2.2 Query Parameters

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

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

2.3 Support for @ModelAttribute

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

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:

<code>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;
    }
}
</code>

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

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

Usage example with a custom annotation:

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

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

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

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.