Spring MVC
GET @RequestParam
Complex Objects
Web Development
Java Programming

Spring MVC Complex object as GET @RequestParam

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Spring MVC, a complex object passed through a GET request is usually not something you handle with one @RequestParam string. If the query string contains multiple fields, the normal solution is model binding with @ModelAttribute or even a plain method parameter, not a single @RequestParam Person person.

@RequestParam is great for simple scalar values. For multi-field request data such as name, age, and city, Spring's object binding is usually the cleaner and more idiomatic approach.

Bind Query Parameters Into an Object

Suppose the request looks like this:

text
/search?name=Ava&age=30&city=Toronto

Define a simple DTO:

java
1public class PersonFilter {
2    private String name;
3    private Integer age;
4    private String city;
5
6    public String getName() {
7        return name;
8    }
9
10    public void setName(String name) {
11        this.name = name;
12    }
13
14    public Integer getAge() {
15        return age;
16    }
17
18    public void setAge(Integer age) {
19        this.age = age;
20    }
21
22    public String getCity() {
23        return city;
24    }
25
26    public void setCity(String city) {
27        this.city = city;
28    }
29}

Then bind it in the controller:

java
1import org.springframework.stereotype.Controller;
2import org.springframework.web.bind.annotation.GetMapping;
3import org.springframework.web.bind.annotation.ModelAttribute;
4import org.springframework.web.bind.annotation.ResponseBody;
5
6@Controller
7public class SearchController {
8
9    @GetMapping("/search")
10    @ResponseBody
11    public String search(@ModelAttribute PersonFilter filter) {
12        return "Searching for " + filter.getName();
13    }
14}

Spring matches query parameters to bean properties by name and populates the object automatically.

You Often Do Not Need @ModelAttribute Explicitly

For many GET handlers, this also works:

java
1@GetMapping("/search")
2@ResponseBody
3public String search(PersonFilter filter) {
4    return "Searching for " + filter.getName();
5}

Spring will still treat it as a model attribute in this context. Adding @ModelAttribute can make the intent clearer, but the binding mechanism is the same.

When @RequestParam Still Makes Sense

If the request really contains a single encoded value, then @RequestParam may be appropriate:

text
/search?person=Ava,30,Toronto

In that case, Spring sees one string parameter named person, so you need a converter to turn that string into an object:

java
1import org.springframework.core.convert.converter.Converter;
2
3public class StringToPersonFilterConverter implements Converter<String, PersonFilter> {
4    @Override
5    public PersonFilter convert(String source) {
6        String[] parts = source.split(",");
7        PersonFilter filter = new PersonFilter();
8        filter.setName(parts[0]);
9        filter.setAge(Integer.valueOf(parts[1]));
10        filter.setCity(parts[2]);
11        return filter;
12    }
13}

That is a valid pattern, but it solves a different problem. It is for one encoded parameter, not ordinary multi-field query binding.

Validation Still Applies

Complex GET filters often need validation just like POST bodies do:

java
1import jakarta.validation.constraints.Min;
2
3public class PersonFilter {
4    private String name;
5
6    @Min(0)
7    private Integer age;
8
9    // getters and setters
10}

Then validate it in the controller with @Valid if needed. GET requests are still user input and can still contain malformed values.

Common Pitfalls

The biggest mistake is trying to use one @RequestParam for a multi-field object when the query string already exposes separate fields. In that case, use object binding, not one large string.

Another common issue is forgetting that binding by property name requires matching parameter names. If the query string says fullName but the DTO says name, binding will not happen automatically.

Developers also sometimes use a converter when plain @ModelAttribute binding would have been simpler and more readable.

Finally, do not forget validation and optionality. A complex object in a GET request still needs rules for missing or invalid parameters.

Summary

  • For multi-field GET query strings, bind to a complex object with @ModelAttribute or a plain object parameter.
  • Use @RequestParam for simple scalar parameters or for one explicitly encoded string value.
  • Add a custom converter only when one query parameter must be parsed into an object.
  • Make sure query parameter names match the target object's property names.
  • Treat complex GET input as real user input and validate it when appropriate.

Course illustration
Course illustration

All Rights Reserved.