Backend Development 7 min read

Mastering SpringBoot @RequestMapping: Advanced Techniques & Custom Annotations

This tutorial explains the basics of SpringBoot's @RequestMapping annotation, its shortcut variants, handling of HEAD and OPTIONS requests, how to create custom request annotations, and demonstrates dynamic handler registration with complete code examples.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering SpringBoot @RequestMapping: Advanced Techniques & Custom Annotations

Environment: SpringBoot 2.7.18

1. Introduction

Based on annotation-driven controllers, you can use @RequestMapping to map requests to controller methods. It supports matching by URL, HTTP method, parameters, headers, and media types, and can be applied at class level for shared mappings or at method level for specific endpoints.

Shortcut annotations for specific HTTP methods include:

@GetMapping

@PostMapping

@PutMapping

@DeleteMapping

@PatchMapping

2. Practical Cases

2.1 HEAD and OPTIONS requests

Spring does not provide dedicated shortcuts for HEAD or OPTIONS; you must use @RequestMapping with the method attribute.

@GetMapping (or @RequestMapping(method=HttpMethod.GET) ) also supports transparent HEAD mapping. The controller method runs unchanged, and the servlet container ensures the Content‑Length header reflects the byte size without sending a body.

<code>@GetMapping("/h")
public Object h() {
    System.out.println("header....");
    return "h method...";
}
</code>

When invoked with HEAD, the method executes but no response body is sent; only the Content‑Length header is returned.

Response header example:

OPTIONS handling: Spring automatically sets the Allow header with all HTTP methods mapped to the URL. Example:

<code>@RequestMapping(value = "/o", method = {RequestMethod.DELETE, RequestMethod.HEAD})
public Object o() {
    System.out.println("o....");
    return "h method...";
}
</code>

When the endpoint is called with OPTIONS, the Allow header lists DELETE, HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS (if no method is specified).

2.2 Custom request annotation

In scenarios requiring reusable mapping patterns, define a meta‑annotation that composes @RequestMapping with preset attributes.

<code>@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping
public @interface PackMapping {
    @AliasFor(annotation = RequestMapping.class) String name() default "";
    @AliasFor(annotation = RequestMapping.class) String[] value() default {};
    @AliasFor(annotation = RequestMapping.class) RequestMethod[] method() default {RequestMethod.GET, RequestMethod.POST};
    @AliasFor(annotation = RequestMapping.class) String[] path() default {};
    @AliasFor(annotation = RequestMapping.class) String[] params() default {};
    @AliasFor(annotation = RequestMapping.class) String[] headers() default {"X-API-Version=v1"};
    @AliasFor(annotation = RequestMapping.class) String[] consumes() default {};
    @AliasFor(annotation = RequestMapping.class) String[] produces() default {};
}
</code>

Test controller using the custom annotation:

<code>@PackMapping("/v")
public Object v() {
    System.out.println("自定义请求注解....");
    return "PackMapping method...";
}
</code>

The request must include the X-API-Version header.

2.3 Dynamic registration of handlers

Programmatically register a handler method for a specific URL, useful for dynamic or advanced scenarios.

<code>@Configuration
public class CustomWebConfig {
    @Autowired
    public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserService handler) throws NoSuchMethodException {
        BuilderConfiguration options = new BuilderConfiguration();
        options.setPatternParser(new PathPatternParser());
        RequestMappingInfo info = RequestMappingInfo.paths("/api/user/{id}")
            .methods(RequestMethod.GET)
            .options(options)
            .build();
        Method method = UserHandler.class.getMethod("getUser", Integer.class);
        mapping.registerMapping(info, handler, method);
    }
}
</code>

Handler implementation:

<code>@Component
public class UserHandler {
    @ResponseBody
    public User getUser(@PathVariable("id") Integer id) {
        User user = new User();
        user.setId(id);
        user.setName("张三");
        return user;
    }
}
</code>

Calling /api/user/1 returns the user JSON.

End of article.

Javabackend developmentAnnotationsSpringBootRESTRequestMapping
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.