Close

Spring MVC - Binding URL query parameters with @RequestParam

[Last Updated: Mar 10, 2026]

The @RequestParam annotation is used to bind parameter values of query string to the controller method parameters.



Definition of RequestParam

Version: 7.0.5
 package org.springframework.web.bind.annotation;
 @Target(ElementType.PARAMETER)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface RequestParam {
     @AliasFor("name")
     String value() default ""; 1
     @AliasFor("value")
     String name() default ""; 2
     boolean required() default true; 3
     String defaultValue() default ValueConstants.DEFAULT_NONE; 4
 }
1Alias for #name.
2The name of the request parameter to bind to. (Since 4.2)
3Whether the parameter is required.
4The default value to use as a fallback when the request parameter is not provided or has an empty value.

Examples

Using 'value' element of @RequestParam

'value' element of @RequestParam is used to specify URL query param name. Following handler method will be mapped with the request /employees?dept=IT :

@Controller
@RequestMapping("employees")
public class EmployeeController {

    @RequestMapping
    public String handleEmployeeRequestByDept (@RequestParam("dept") String deptName,
                                                                       Model map) {
        map.addAttribute("msg", "employees request by dept: " + deptName);
        return "my-page";
    }
}

The value of deptName in above snippet will be IT.




@RequestParam without 'value' element

Just like @PathVariable, 'value' element of @RequestParam annotation can be skipped if the target variable name is same as param name. The code has to be compiled with debugging information. Following handler will be mapped with /employees?sate=NC :

@Controller
@RequestMapping("employees")
public class EmployeeController {

    @RequestMapping
    public String handleEmployeeRequestByArea (@RequestParam String state, Model map) {
        map.addAttribute("msg", "employees request by area: " + state);
        return "my-page";

    }
}

The value of state parameter will be NC.

Using multiple @RequestParam annotations

A method can have any number of @RequestParam annotations. Following will be mapped with /employees?dept=IT&state=NC :

@Controller
@RequestMapping("employees")
public class EmployeeController {

    @RequestMapping
    public String handleEmployeeRequestByDept (@RequestParam("dept") String deptName,
                                            @RequestParam("state") String stateCode,
                                            Model map) {
        map.addAttribute("msg", "employees request by dept and state code : "+
                                                           deptName+", "+stateCode);
        return "my-page";
    }
}




Using Map with @RequestParam for multiple params

If the method parameter is Map or MultiValueMap then the map is populated with all query string names and values. Following will be mapped with /employees/234/messages?sendBy=mgr&date=20160210

@Controller
@RequestMapping("employees")
public class EmployeeController {

    @RequestMapping("{id}/messages")
    public String handleEmployeeMessagesRequest (@PathVariable("id") String employeeId,
                                            @RequestParam Map<String, String> queryMap,
                                            Model model) {
        model.addAttribute("msg", "employee request by id and query map : "+
                  employeeId+", "+queryMap.toString());
        return "my-page";
    }
}

Where employeeId = "234" and queryMap = {sendBy=mgr, date=20160210}





Auto type conversion

If target method parameter is not String, automatic type conversion may happen. All simple types such as int, long, Date, etc. are supported by default. Following will be mapped with /employees/234/paystubsByMonths?months=5:

@Controller
@RequestMapping("employees")
public class EmployeeController{

    @RequestMapping("{id}/paystubsByMonths")
    public String handleRequest4 (@PathVariable("id") String employeeId,
                                  @RequestParam("months") int previousMonths,
                                                                 Model model) {
        model.addAttribute("employee request by id for paystub for previous months : "+
                                     employeeId+", "+previousMonths);
        return "my-page";
    }
}

We can customize date format using Spring annotation @DateTimeFormat. Following will be mapped with /employees/234/paystubs?startDate=2000-10-31&endDate=2000-10-31"

@Controller
@RequestMapping("employees")
public class EmployeeController{

    @RequestMapping("{id}/paystubs")
    public String handleRequest4 (@PathVariable("id") String employeeId,
              @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
              @RequestParam("startDate") LocalDate startDate,
              @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
              @RequestParam("endDate") LocalDate endDate,
              Model model) {
        LOGGER.info("employee request by id and paystub dates : " +
                              employeeId + ", " + startDate + ", " + endDate);
        model.addAttribute("employee request by id and paystub dates : " +
                                     employeeId + ", " + startDate + ", " + endDate);
        return "my-page";
    }
}

The 'required' element of @RequestParam

This element defines whether the parameter is required. The default is true. That means the status code 400 will be returned if the parameter is missing in the request. We can switch this to false if we prefer a null value if the parameter is not present in the request.

Following will be mapped with both /employees/234/report?project=mara and /employees/234/report

@Controller
@RequestMapping("employees")
public class EmployeeController {

    @RequestMapping(value = "{id}/report")
    public String handleEmployeeReportRequest (
              @PathVariable("id") String id,
              @RequestParam(value = "project", required = false) String projectName,
              Model model) {

        model.addAttribute("employee report request by id and project name : " +
                                                             id + ", " + projectName);
        return "my-page";
    }
}




The 'defaultValue' element of @RequestParam

This element is used as a fallback when the request parameter is not provided or has an empty value. Supplying a default value implicitly sets 'required' to false.

In our last example, we can specify our projectName with a default value. In that case we don't have to specify 'required=false'. We can still make the same two requests. In case of /employees/234/report, the projectName value received by the handler method will be the defaultValue of 'kara'.

@RequestParam(value = "project", defaultValue="kara") String projectName




Same base URI methods with different params are ambiguous

Defining different request parameters does not define different URI paths. Following handler methods will cause runtime exception, complaining about ambiguous mapping.

@Controller
@RequestMapping("/employees")
public class EmployeeController {

    @RequestMapping
    public String handleEmployeeRequestByDept (@RequestParam("dept") String deptName,
                                                                      Model map) {
        map.addAttribute("msg", "employee " + deptName);
        return "my-page";
    }

    @RequestMapping
    public String handleEmployeeRequestByState (@RequestParam("state") String stateCode,
                                            Model map) {
        map.addAttribute("msg", "employee request by  state code : " + ", " + stateCode);
        return "my-page";
    }
}
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'myMvcController' method
public java.lang.String com.logicbig.example.EmployeeController.handleEmployeeRequestByArea(java.lang.String,org.springframework.ui.Model)
to {[/employees]}: There is already 'myMvcController' bean method
public java.lang.String com.logicbig.example.EmployeeController.handleEmployeeRequestByDept(java.lang.String,org.springframework.ui.Model) mapped.



Avoiding ambiguity by using @RequestMapping(params = ....)

If having a different path is not possible (from the design perspective) and we don't have other factors with which we can resolve the ambiguity, for example factors like different HTTP methods or consume/produce type, then one way to fix this is to define different params of @RequestMapping . The good news is Spring allows to just specify parameter name without it's value, for example: @RequestMapping(params = "dept"):

@Controller
@RequestMapping("employees")
public class EmployeeController {

   @RequestMapping(params = "dept")
    public String handleEmployeeRequestByDept (@RequestParam("dept") String deptName,
                                                                         Model map) {
        map.addAttribute("msg", "employee request by dept: " + deptName);
        return "my-page";
    }

    @RequestMapping(params = "state")
    public String handleEmployeesRequestByArea (@RequestParam String state, Model map) {
        map.addAttribute("msg", "Employee request by area: " + state);
        return "my-page";
}

Alternatively, we can merge different methods into one, having all parameters together with 'required=false'. Or we can use a single Map annotated with @RequestParam. Then based on what param values are null and what are not, we can make decisions. That will not be very maintainable approach though.

Example Project

To test controllers, run the unit tests in MyMvcControllerTest

Or you can run the app using embedded jetty:

mvn  clean compile jetty:run

Then try following urls:
http://localhost:8080/employees?dept=IT
http://localhost:8080/employees?state=NC
http://localhost:8080/employees?dept=IT&state=NC
http://localhost:8080/employees?dept=IT&state=NC
http://localhost:8080/employees/234/paystubs?months=5
http://localhost:8080/employees/234/paystubs?startDate=2000-10-31&endDate=2000-10-31
http://localhost:8080/employees/234/report
http://localhost:8080/employees/234/report?project=mara
http://localhost:8080/employees/234/messages?sendBy=mgr&date=20160210

Example Project

Dependencies and Technologies Used:

  • spring-webmvc 7.0.5 (Spring Web MVC)
     Version Compatibility: 4.0.0.RELEASE - 7.0.5Version List
    ×

    Version compatibilities of spring-webmvc with this example:

      javax.servlet-api:3.x
    • 4.0.0.RELEASE
    • 4.0.1.RELEASE
    • 4.0.2.RELEASE
    • 4.0.3.RELEASE
    • 4.0.4.RELEASE
    • 4.0.5.RELEASE
    • 4.0.6.RELEASE
    • 4.0.7.RELEASE
    • 4.0.8.RELEASE
    • 4.0.9.RELEASE
    • 4.1.0.RELEASE
    • 4.1.1.RELEASE
    • 4.1.2.RELEASE
    • 4.1.3.RELEASE
    • 4.1.4.RELEASE
    • 4.1.5.RELEASE
    • 4.1.6.RELEASE
    • 4.1.7.RELEASE
    • 4.1.8.RELEASE
    • 4.1.9.RELEASE
    • 4.2.0.RELEASE
    • 4.2.1.RELEASE
    • 4.2.2.RELEASE
    • 4.2.3.RELEASE
    • 4.2.4.RELEASE
    • 4.2.5.RELEASE
    • 4.2.6.RELEASE
    • 4.2.7.RELEASE
    • 4.2.8.RELEASE
    • 4.2.9.RELEASE
    • 4.3.0.RELEASE
    • 4.3.1.RELEASE
    • 4.3.2.RELEASE
    • 4.3.3.RELEASE
    • 4.3.4.RELEASE
    • 4.3.5.RELEASE
    • 4.3.6.RELEASE
    • 4.3.7.RELEASE
    • 4.3.8.RELEASE
    • 4.3.9.RELEASE
    • 4.3.10.RELEASE
    • 4.3.11.RELEASE
    • 4.3.12.RELEASE
    • 4.3.13.RELEASE
    • 4.3.14.RELEASE
    • 4.3.15.RELEASE
    • 4.3.16.RELEASE
    • 4.3.17.RELEASE
    • 4.3.18.RELEASE
    • 4.3.19.RELEASE
    • 4.3.20.RELEASE
    • 4.3.21.RELEASE
    • 4.3.22.RELEASE
    • 4.3.23.RELEASE
    • 4.3.24.RELEASE
    • 4.3.25.RELEASE
    • 4.3.26.RELEASE
    • 4.3.27.RELEASE
    • 4.3.28.RELEASE
    • 4.3.29.RELEASE
    • 4.3.30.RELEASE
    • 5.0.0.RELEASE
    • 5.0.1.RELEASE
    • 5.0.2.RELEASE
    • 5.0.3.RELEASE
    • 5.0.4.RELEASE
    • 5.0.5.RELEASE
    • 5.0.6.RELEASE
    • 5.0.7.RELEASE
    • 5.0.8.RELEASE
    • 5.0.9.RELEASE
    • 5.0.10.RELEASE
    • 5.0.11.RELEASE
    • 5.0.12.RELEASE
    • 5.0.13.RELEASE
    • 5.0.14.RELEASE
    • 5.0.15.RELEASE
    • 5.0.16.RELEASE
    • 5.0.17.RELEASE
    • 5.0.18.RELEASE
    • 5.0.19.RELEASE
    • 5.0.20.RELEASE
    • 5.1.0.RELEASE
    • 5.1.1.RELEASE
    • 5.1.2.RELEASE
    • 5.1.3.RELEASE
    • 5.1.4.RELEASE
    • 5.1.5.RELEASE
    • 5.1.6.RELEASE
    • 5.1.7.RELEASE
    • 5.1.8.RELEASE
    • 5.1.9.RELEASE
    • 5.1.10.RELEASE
    • 5.1.11.RELEASE
    • 5.1.12.RELEASE
    • 5.1.13.RELEASE
    • 5.1.14.RELEASE
    • 5.1.15.RELEASE
    • 5.1.16.RELEASE
    • 5.1.17.RELEASE
    • 5.1.18.RELEASE
    • 5.1.19.RELEASE
    • 5.1.20.RELEASE
    • 5.2.0.RELEASE
    • 5.2.1.RELEASE
    • 5.2.2.RELEASE
    • 5.2.3.RELEASE
    • 5.2.4.RELEASE
    • 5.2.5.RELEASE
    • 5.2.6.RELEASE
    • 5.2.7.RELEASE
    • 5.2.8.RELEASE
    • 5.2.9.RELEASE
    • 5.2.10.RELEASE
    • 5.2.11.RELEASE
    • 5.2.12.RELEASE
    • 5.2.13.RELEASE
    • 5.2.14.RELEASE
    • 5.2.15.RELEASE
    • 5.2.16.RELEASE
    • 5.2.17.RELEASE
    • 5.2.18.RELEASE
    • 5.2.19.RELEASE
    • 5.2.20.RELEASE
    • 5.2.21.RELEASE
    • 5.2.22.RELEASE
    • 5.2.23.RELEASE
    • 5.2.24.RELEASE
    • 5.2.25.RELEASE
    • 5.3.0
    • 5.3.1
    • 5.3.2
    • 5.3.3
    • 5.3.4
    • javax.servlet-api:4.x
    • 5.3.5
    • 5.3.6
    • 5.3.7
    • 5.3.8
    • 5.3.9
    • 5.3.10
    • 5.3.11
    • 5.3.12
    • 5.3.13
    • 5.3.14
    • 5.3.15
    • 5.3.16
    • 5.3.17
    • 5.3.18
    • 5.3.19
    • 5.3.20
    • 5.3.21
    • 5.3.22
    • 5.3.23
    • 5.3.24
    • 5.3.25
    • 5.3.26
    • 5.3.27
    • 5.3.28
    • 5.3.29
    • 5.3.30
    • 5.3.31
    • 5.3.32
    • 5.3.33
    • 5.3.34
    • 5.3.35
    • 5.3.36
    • 5.3.37
    • 5.3.38
    • 5.3.39
    • javax.* -> jakarta.*
      jakarta.servlet-api:6.x
      Java 17 min
    • 6.0.0
    • 6.0.1
    • 6.0.2
    • 6.0.3
    • 6.0.4
    • 6.0.5
    • 6.0.6
    • 6.0.7
    • 6.0.8
    • 6.0.9
    • 6.0.10
    • 6.0.11
    • 6.0.12
    • 6.0.13
    • 6.0.14
    • 6.0.15
    • 6.0.16
    • 6.0.17
    • 6.0.18
    • 6.0.19
    • 6.0.20
    • 6.0.21
    • 6.0.22
    • 6.0.23
    • 6.1.0
    • 6.1.1
    • 6.1.2
    • 6.1.3
    • 6.1.4
    • 6.1.5
    • 6.1.6
    • 6.1.7
    • 6.1.8
    • 6.1.9
    • 6.1.10
    • 6.1.11
    • 6.1.12
    • 6.1.13
    • 6.1.14
    • 6.1.15
    • 6.1.16
    • 6.1.17
    • 6.1.18
    • 6.1.19
    • 6.1.20
    • 6.1.21
    • 6.2.0
    • 6.2.1
    • 6.2.2
    • 6.2.3
    • 6.2.4
    • 6.2.5
    • 6.2.6
    • 6.2.7
    • 6.2.8
    • 6.2.9
    • 6.2.10
    • 6.2.11
    • 6.2.12
    • 6.2.13
    • 6.2.14
    • 6.2.15
    • 6.2.16
    • 7.0.0
    • 7.0.1
    • 7.0.2
    • 7.0.3
    • 7.0.4
    • 7.0.5

    Versions in green have been tested.

  • spring-test 7.0.5 (Spring TestContext Framework)
  • jakarta.servlet-api 6.1.0 (Jakarta Servlet API documentation)
  • junit-jupiter-engine 6.0.2 (Module "junit-jupiter-engine" of JUnit)
  • JDK 25
  • Maven 3.9.11

Spring MVC - @RequestParam Examples Select All Download
  • spring-mvc-request-param
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • EmployeeController.java
          • webapp
            • WEB-INF
              • views
        • test
          • java
            • com
              • logicbig
                • example

    See Also

    Join