Spring 4.3 introduced new annotations which serve the same purpose as @RequestMapping having predefined 'method' (HTTP verb) value. Those annotations are actually themselves meta-annotated with @RequestMapping with the related value of 'method' element.
Followings are those annotations:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
To understand clearly how Spring is using Java annotation to achieve that, let's see the definition of @GetMapping:
Definition of GetMappingVersion: 7.0.6 package org.springframework.web.bind.annotation;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {
@AliasFor(annotation = RequestMapping.class)
String name() default ""; 1
@AliasFor(annotation = RequestMapping.class)
String[] value() default {}; 2
@AliasFor(annotation = RequestMapping.class)
String[] path() default {}; 3
@AliasFor(annotation = RequestMapping.class)
String[] params() default {}; 4
@AliasFor(annotation = RequestMapping.class)
String[] headers() default {}; 5
@AliasFor(annotation = RequestMapping.class)
String[] consumes() default {}; 6
@AliasFor(annotation = RequestMapping.class)
String[] produces() default {}; 7
@AliasFor(annotation = RequestMapping.class)
String version() default ""; 8
}
As we can see, all elements of @RequestMapping are redefined here, except for the method element, which is hard-coded (in the above case, method = RequestMethod.GET) via @RequestMapping defined as a type-level annotation.
Though this is just a Spring-internal annotation processing detail, out of curiosity: imagine that the Spring annotation processor delegates the processing of these new annotations to the original ones, passing along the hard-coded method value.
The advantage of this kind of approach is that it reduces configuration metadata on the application side, making the code more readable.
Example
The Controller
Let's create a simple controller with handler method having each of the new mapping annotation as listed above:
package com.logicbig.example;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class MyController {
@GetMapping("test")
public String handleGetRequest () {
return "GetMapping-view";
}
@PostMapping("test")
public String handlePostRequest () {
return "PostMapping-view";
}
@PutMapping("test")
public String handlePutRequest () {
return "PutMapping-view";
}
@DeleteMapping("test")
public String handleDeleteRequest () {
return "DeleteMapping-view";
}
@PatchMapping("test")
public String handlePatchRequest () {
return "PatchMapping-view";
}
}
The JUnit Test
package com.logicbig.example;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import org.springframework.web.context.WebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration(classes = MyWebConfig.class)
public class ControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvcTester mockMvc;
@BeforeEach
public void setup() {
// Initialize the AssertJ-aware tester from the WebAppContext
this.mockMvc = MockMvcTester.from(wac);
}
@Test
public void testGet() {
assertThat(mockMvc.get().uri("/test"))
.hasStatusOk()
.hasViewName("GetMapping-view");
}
@Test
public void testPost() {
assertThat(mockMvc.post().uri("/test"))
.hasStatusOk()
.hasViewName("PostMapping-view");
}
@Test
public void testPut() {
assertThat(mockMvc.put().uri("/test"))
.hasStatusOk()
.hasViewName("PutMapping-view");
}
@Test
public void testDelete() {
assertThat(mockMvc.delete().uri("/test"))
.hasStatusOk()
.hasViewName("DeleteMapping-view");
}
@Test
public void testPatch() {
assertThat(mockMvc.patch().uri("/test"))
.hasStatusOk()
.hasViewName("PatchMapping-view");
}
}
mvn clean test -Dtest="ControllerTest" Output$ mvn clean test -Dtest="ControllerTest" [INFO] Scanning for projects... [WARNING] [WARNING] Some problems were encountered while building the effective model for com.logicbig.com:spring-mvc-request-mapping-variants:war:1.0-SNAPSHOT [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-war-plugin is missing. @ line 34, column 21 [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. [WARNING] [INFO] [INFO] --------< com.logicbig.com:spring-mvc-request-mapping-variants >-------- [INFO] Building spring-mvc-request-mapping-variants 1.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ war ]--------------------------------- [INFO] [INFO] --- clean:3.2.0:clean (default-clean) @ spring-mvc-request-mapping-variants --- [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ spring-mvc-request-mapping-variants --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\example-projects\spring-mvc\spring-mvc-request-mapping-variants\src\main\resources [INFO] [INFO] --- compiler:3.3:compile (default-compile) @ spring-mvc-request-mapping-variants --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 2 source files to D:\example-projects\spring-mvc\spring-mvc-request-mapping-variants\target\classes [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ spring-mvc-request-mapping-variants --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\example-projects\spring-mvc\spring-mvc-request-mapping-variants\src\test\resources [INFO] [INFO] --- compiler:3.3:testCompile (default-testCompile) @ spring-mvc-request-mapping-variants --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to D:\example-projects\spring-mvc\spring-mvc-request-mapping-variants\target\test-classes [INFO] ------------------------------------------------------------- [ERROR] COMPILATION ERROR : [INFO] ------------------------------------------------------------- [ERROR] /D:/LogicBig/example-projects/spring-mvc/spring-mvc-request-mapping-variants/src/test/java/com/logicbig/example/ControllerTest.java:[44,58] cannot access org.hamcrest.Matcher class file for org.hamcrest.Matcher not found [INFO] 1 error [INFO] ------------------------------------------------------------- [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4.053 s [INFO] Finished at: 2026-03-16T13:44:38+08:00 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.3:testCompile (default-testCompile) on project spring-mvc-request-mapping-variants: Compilation failure [ERROR] /D:/LogicBig/example-projects/spring-mvc/spring-mvc-request-mapping-variants/src/test/java/com/logicbig/example/ControllerTest.java:[44,58] cannot access org.hamcrest.Matcher [ERROR] class file for org.hamcrest.Matcher not found [ERROR] [ERROR] -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
Example ProjectDependencies and Technologies Used: - spring-webmvc 7.0.6 (Spring Web MVC)
Version Compatibility: 4.3.0.RELEASE - 7.0.6 Version compatibilities of spring-webmvc with this example: Versions in green have been tested.
- spring-test 7.0.6 (Spring TestContext Framework)
- jakarta.servlet-api 6.1.0 (Jakarta Servlet API documentation)
- junit-jupiter-engine 6.0.3 (Module "junit-jupiter-engine" of JUnit)
- hamcrest 3.0 (Core API and libraries of hamcrest matcher framework)
- assertj-core 3.26.3 (Rich and fluent assertions for testing in Java)
- JDK 25
- Maven 3.9.11
|