RadhaPublication
HomeInterviewLearning PathsRole TracksMockBooksPricing
Login / Sign UpLog in

© 2026 Radha Publication. All rights reserved.

Shop on AmazonDonateContactPrivacyTerms
Spring Boot questions
TrickySpring Boot#336 min readJul 11, 2026

@RequestMapping vs @GetMapping.

practice
learning
Practice modeTest yourself instead of reading straight through

Hook: Think of @RequestMapping as the master key for every door, while @GetMapping is the labeled key that opens only the GET door — interviewers love this because it checks whether you know both the shortcut and the rule behind it.

Question: What is the difference between @RequestMapping and @GetMapping in Spring Boot?

Answer: @RequestMapping is the general annotation for mapping HTTP requests to controller methods, and it can handle any HTTP method if you configure it. @GetMapping is a specialized shortcut for @RequestMapping(method = RequestMethod.GET), so it is only for HTTP GET requests. In practice, @GetMapping is shorter, clearer, and easier to read when the endpoint is read-only.

Interview-Ready Answer: “I use @RequestMapping when I need the flexible, general mapping API, especially if I want to specify different HTTP methods or combine options. @GetMapping is just the GET-specific shortcut, so it’s equivalent to @RequestMapping(method = RequestMethod.GET). For a REST API, I usually prefer @GetMapping for readability because it makes the intent obvious at a glance.”

🧠 Memory Map
Memory map — visual summary of this topic

What they really mean

Detailed Explanation: Both annotations tell Spring MVC how to route an incoming HTTP request to a controller method. The important idea is that @RequestMapping is the broader tool, and @GetMapping is a convenience annotation built for one specific HTTP verb: GET. A verb means the request method such as GET, POST, PUT, or DELETE.

How Spring handles it under the hood

  1. When the app starts, Spring scans controller classes and reads mapping annotations.
  2. It builds a routing table inside RequestMappingHandlerMapping, which stores the URL pattern, HTTP method, headers, produces/consumes rules, and so on.
  3. For a request like GET /users/42, Spring checks each registered mapping and looks for a match on path and method.
  4. If the method is @GetMapping, Spring already knows it means GET, so the mapping is created with method = GET.
  5. If the method is @RequestMapping without a method attribute, it can match multiple HTTP methods, which is powerful but risky if you intended only one verb.

When to use which

  • Use @GetMapping for read-only endpoints like fetching a user, listing orders, or searching products.
  • Use @RequestMapping when you need more general control, or when you want to map several methods in a shared way.
  • In modern REST APIs, the specialized annotations are usually preferred because they make code easier to scan.

Comparison

Aspect@RequestMapping@GetMapping
ScopeGeneralGET only
ReadabilityMore verboseShorter, clearer
FlexibilityHighLimited to GET
Typical useShared or complex mappingREST read endpoint

Performance and edge cases

At runtime, the difference is tiny: both are resolved during request mapping, so there is no meaningful performance win for one over the other. The real cost is human, not CPU: a broad @RequestMapping without a method can accidentally accept POST, PUT, or DELETE when you meant only GET. That can cause surprising bugs and even security issues if a route exposes behavior too broadly.

Version note: @GetMapping was added in Spring 4.3 as part of the “composed annotations” family, alongside @PostMapping, @PutMapping, and @DeleteMapping. In Spring Boot 3, it works the same way, on top of Spring Framework 6.

Memory hook: “RequestMapping is the toolbox; GetMapping is the labeled wrench.” If you know exactly which bolt you are turning, use the labeled tool.

Real-World Story: Imagine a checkout service in an e-commerce app. The team adds @RequestMapping("/orders/{id}") to fetch order details, but forgets to restrict it to GET. Later, a client accidentally sends a POST to the same URL, and the controller still matches it. If the method has side effects, users may see duplicate actions, strange audit logs, or a 405/validation mismatch somewhere else in the flow.

In production, the bug might show up as support tickets saying “view order” sometimes changes state, or as logs where the same path receives multiple HTTP methods. You might see request traces like POST /orders/123 hitting a method that was meant only for reading. The fix is simple: make the contract explicit with @GetMapping or @RequestMapping(method = RequestMethod.GET).

What goes wrong: a developer assumes “URL equals operation,” but HTTP semantics matter. GET should be safe and idempotent in normal REST design: safe means it should not change data, and idempotent means repeating it has the same effect as doing it once. When that contract is blurry, caches, browsers, and API clients can behave in confusing ways.

Spring Boot
package com.example.mappingdemo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.LinkedHashMap;
import java.util.Map;

@SpringBootApplication
public class MappingDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(MappingDemoApplication.class, args);
    }

    // This prints startup guidance so the app is runnable and self-explanatory.
    @Bean
    CommandLineRunner demoInfo() {
        return args -> {
            System.out.println("Try these endpoints:");
            System.out.println("GET  http://localhost:8080/api/users/42");
            System.out.println("GET  http://localhost:8080/api/users/99");
            System.out.println("GET  http://localhost:8080/api/raw/42");
            System.out.println("POST http://localhost:8080/api/users/42  -> should return 405 (Method Not Allowed)");
        };
    }

    @RestController
    @RequestMapping("/api")
    static class UserController {

        // Explicitly GET-only. This is the clearest choice for a read endpoint.
        @GetMapping("/users/{id}")
        public ResponseEntity<Map<String, Object>> getUser(@PathVariable int id) {
            if (id <= 0) {
                // Edge case: invalid input should fail fast with a clear 400.
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "id must be positive");
            }

            Map<String, Object> body = new LinkedHashMap<>();
            body.put("id", id);
            body.put("name", "Asha");
            body.put("mapping", "@GetMapping");
            return ResponseEntity.ok(body);
        }

        // Same behavior as @GetMapping, but written in the longer form.
        @RequestMapping(value = "/raw/{id}", method = RequestMethod.GET)
        public ResponseEntity<Map<String, Object>> getUserWithRequestMapping(@PathVariable int id) {
            Map<String, Object> body = new LinkedHashMap<>();
            body.put("id", id);
            body.put("mapping", "@RequestMapping(method = RequestMethod.GET)");
            return ResponseEntity.ok(body);
        }

        // Demonstrates the gotcha: without a method attribute, this mapping can match any HTTP verb.
        @RequestMapping("/open/{id}")
        public ResponseEntity<Map<String, Object>> openMapping(@PathVariable int id) {
            Map<String, Object> body = new LinkedHashMap<>();
            body.put("id", id);
            body.put("warning", "This endpoint is mapped without an HTTP method restriction.");
            body.put("note", "In real REST APIs, be explicit unless you truly want all verbs.");
            return ResponseEntity.ok(body);
        }

        // A POST endpoint to show that GET-only routes reject other methods with 405.
        @PostMapping("/users/{id}")
        public ResponseEntity<Map<String, Object>> updateUser(@PathVariable int id) {
            Map<String, Object> body = new LinkedHashMap<>();
            body.put("id", id);
            body.put("status", "updated");
            return ResponseEntity.ok(body);
        }
    }
}

Follow-up & Tricky Questions:

  • “Is @GetMapping just syntax sugar?” Yes. It is a composed annotation built on top of @RequestMapping(method = RequestMethod.GET), so the behavior is essentially the same.
  • “When would you still use @RequestMapping?” When you need a generic mapping, multiple attributes, or you want to stay consistent with older codebases that predate the shortcut annotations.
  • “What happens if I call a GET endpoint with POST?” Spring usually returns 405 Method Not Allowed if there is a path match but no matching method. That is a good signal that the route exists, but the verb is wrong.
  • “Can I put both @RequestMapping and @GetMapping on the same method?” You should not mix them like that for the same path intent. It makes the code harder to read and can create confusing or conflicting mappings.
  • “Do these annotations affect performance?” Not in any meaningful way at request time. The bigger impact is code clarity and correctness, because the mapping is resolved from metadata during startup and request dispatch.
  • Tricky: “If @RequestMapping has no method, is that okay for a REST GET endpoint?” It compiles and runs, but it is usually a design smell. It may accept more verbs than you intended, so the API contract becomes too loose.
  • Tricky: “Is @GetMapping available in every Spring version?” It exists from Spring Framework 4.3 onward, so modern Spring Boot apps have it. Very old projects may only use @RequestMapping directly.
  • Tricky: “Does @GetMapping guarantee the method is safe?” No, it only constrains the HTTP verb. The code inside the method can still mutate data if the developer writes it badly.

Common Mistakes:

  • Using @RequestMapping without method by accident. Correction: add method = RequestMethod.GET or switch to @GetMapping.
  • Thinking the annotations change business logic. Correction: they only control routing; the method body still decides what the endpoint does.
  • Writing verbose controller code for simple GET handlers. Correction: use @GetMapping to keep REST controllers easy to read.
  • Forgetting that GET should be read-only in REST design. Correction: if the endpoint changes data, choose the proper verb, usually POST, PUT, PATCH, or DELETE.

Memory Hook: “RequestMapping is the whole toolbox; GetMapping is the one tool already labeled for GET.”

Cheat Sheet:

  • @RequestMapping = general mapping annotation.
  • @GetMapping = shortcut for GET requests only.
  • Both are resolved by Spring MVC during request mapping.
  • Use @GetMapping for clarity in REST read endpoints.
  • Use explicit method attributes when you need full control.
  • Leaving @RequestMapping methodless can widen the route too much.

Practice Tasks:

  • Add a @PostMapping for the same resource and test that GET and POST behave differently.
  • Replace @RequestMapping("/open/{id}") with @GetMapping("/open/{id}") and observe the tighter contract.
  • Send a POST request to a GET-only route and confirm the 405 response.
Previous
Back to Questions←→to navigate
Next

Recommended Resources

Recommended Book

Cracking the Coding Interview

189 Programming Questions and Solutions

Recommended Book

Cracking the Coding Interview

189 Programming Questions and Solutions

package com.example.mappingdemo; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; import java.util.LinkedHashMap; import java.util.Map; @SpringBootApplication public class MappingDemoApplication { public static void main(String[] args) { SpringApplication.run(MappingDemoApplication.class, args); } // This prints startup guidance so the app is runnable and self-explanatory. @Bean CommandLineRunner demoInfo() { return args -> { System.out.println("Try these endpoints:"); System.out.println("GET http://localhost:8080/api/users/42"); System.out.println("GET http://localhost:8080/api/users/99"); System.out.println("GET http://localhost:8080/api/raw/42"); System.out.println("POST http://localhost:8080/api/users/42 -> should return 405 (Method Not Allowed)"); }; } @RestController @RequestMapping("/api") static class UserController { // Explicitly GET-only. This is the clearest choice for a read endpoint. @GetMapping("/users/{id}") public ResponseEntity<Map<String, Object>> getUser(@PathVariable int id) { if (id <= 0) { // Edge case: invalid input should fail fast with a clear 400. throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "id must be positive"); } Map<String, Object> body = new LinkedHashMap<>(); body.put("id", id); body.put("name", "Asha"); body.put("mapping", "@GetMapping"); return ResponseEntity.ok(body); } // Same behavior as @GetMapping, but written in the longer form. @RequestMapping(value = "/raw/{id}", method = RequestMethod.GET) public ResponseEntity<Map<String, Object>> getUserWithRequestMapping(@PathVariable int id) { Map<String, Object> body = new LinkedHashMap<>(); body.put("id", id); body.put("mapping", "@RequestMapping(method = RequestMethod.GET)"); return ResponseEntity.ok(body); } // Demonstrates the gotcha: without a method attribute, this mapping can match any HTTP verb. @RequestMapping("/open/{id}") public ResponseEntity<Map<String, Object>> openMapping(@PathVariable int id) { Map<String, Object> body = new LinkedHashMap<>(); body.put("id", id); body.put("warning", "This endpoint is mapped without an HTTP method restriction."); body.put("note", "In real REST APIs, be explicit unless you truly want all verbs."); return ResponseEntity.ok(body); } // A POST endpoint to show that GET-only routes reject other methods with 405. @PostMapping("/users/{id}") public ResponseEntity<Map<String, Object>> updateUser(@PathVariable int id) { Map<String, Object> body = new LinkedHashMap<>(); body.put("id", id); body.put("status", "updated"); return ResponseEntity.ok(body); } } }