Key SpringMVC Controller Techniques for Modern Web Applications

Automatic Parameter Binding in Controller Methods

SpringMVC automatically maps request parameters to method arguments. The parameter names must match the incoming request parameter names.

@Controller
@RequestMapping("/api")
public class UserController {
    
    @RequestMapping("/greet")
    public String greet(Model model, String username, double score) {
        model.addAttribute("result", username + "|" + String.valueOf(score));
        return "result";
    }
}

Restricting Access by HTTP Method

Use the method attribute to limit which HTTP methods can access a specific endpoint. This enforces RESTful API conventions and improves security.

@Controller
@RequestMapping("/api")
public class UserController {
    
    @RequestMapping(method = {RequestMethod.POST, RequestMethod.GET}, value = "/greet")
    public String greet(Model model) {
        model.addAttribute("message", "Welcome");
        return "result";
    }
    
    @RequestMapping(method = RequestMethod.GET, value = "/leave")
    public String leave(Model model) {
        model.addAttribute("message", "Farewell");
        return "result";
    }
}

Traditional Servlet API Support

SpringMVC controllers can accept HttpServletRequest and HttpServletResponse directly, enabling compatibility with legacy code and fine-grained control over the request-response cycle.

@Controller
@RequestMapping("/api")
public class UserController {
    
    @RequestMapping(method = {RequestMethod.POST, RequestMethod.GET}, value = "/process")
    public void processData(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        String username = request.getParameter("username");
        String identifier = request.getParameter("identifier");
        System.out.println(username + ":" + identifier);
        
        request.getSession().setAttribute("username", username);
        request.getSession().setAttribute("identifier", identifier);
        
        response.sendRedirect(request.getContextPath() + "/output.jsp");
    }
}

Custom Property Editors and Multiple Domain Objects

SpringMVC cannot automatically convert String to java.util.Date. Use @InitBinder to register custom property editors for type conversion. This mechanism also supports handling multiple domain objects in a single request.

@Controller
@RequestMapping("/api")
public class UserController {
        
    /**
     * Register custom date editor with specified format
     */
    @InitBinder
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder)
            throws Exception {
        binder.registerCustomEditor(Date.class, new CustomDateEditor
                (new SimpleDateFormat("yyyy-MM-dd"), true));
    }
    
    @RequestMapping("/person")
    public String handlePerson(Model model, Person person) {
        System.out.println(person.toString());
        model.addAttribute("person", person);
        return "result";
    }
    
    /**
     * Receiving multiple entity objects through wrapper class
     */
    @RequestMapping("/entities")
    public String handleEntities(Model model, Bean wrapper) {
        System.out.println(wrapper.getPerson());
        System.out.println(wrapper.getAnimal());
        model.addAttribute("person", wrapper.getPerson());
        model.addAttribute("animal", wrapper.getAnimal());
        return "result";
    }
}

Collecting Array Parameters

Controllers can directly receive arrays from form submissions. Each checkbox or multi-select value maps to the array element.

<form action="${pageContext.request.contextPath}/api/batch.action" method="post">
    | Item A | <input name="selectedIds" type="checkbox" value="101"></input> |
|---|---|
| Item B | <input name="selectedIds" type="checkbox" value="202"></input> |
| Item C | <input name="selectedIds" type="checkbox" value="303"></input> |
| <input type="submit" value="Submit Selection"></input> |
</form>

@Controller
@RequestMapping("/api")
public class UserController {
    
    @RequestMapping("/batch")
    public String processBatch(Model model, int[] selectedIds) {
        for (int id : selectedIds) {
            System.out.println(id);
        }
        return "success";
    }
}

Collecting List Parameters

For complex form submissions, use indexed notation in input names to populate a list of domain objects.

<form action="${pageContext.request.contextPath}/api/batchPersons.action" method="post">
    | <input name="userList[0].name" type="text" value="Alice"></input> | <input name="userList[0].code" type="text" value="A001"></input> |
|---|---|
| <input name="userList[1].name" type="text" value="Bob"></input> | <input name="userList[1].code" type="text" value="B002"></input> |
| <input type="submit" value="Submit Users"></input> |
</form>

public class BatchWrapper {
    private List<Person> userList = new ArrayList<Person>();

    public List<Person> getUserList() {
        return userList;
    }

    public void setUserList(List<Person> userList) {
        this.userList = userList;
    }
}

@Controller
@RequestMapping("/api")
public class UserController {
    
    @RequestMapping("/batchPersons")
    public String processBatchPersons(Model model, BatchWrapper wrapper) {
        System.out.println(wrapper.getUserList());
        return "success";
    }
}

Forward and Redirect Operations

SpringMVC supports both forward and redirect prefixes for navigation between controllers. Forward preserves request attributes while redirect creates a new request.

@Controller
@RequestMapping("/api")
public class UserController {
    
    @RequestMapping("/start")
    public String start(Model model, String userName) {
        System.out.println("Starting " + userName);
        return "forward:/api/complete";
    }
    
    @RequestMapping("/complete")
    public String complete(Model model, String userName) {
        System.out.println("Completing " + userName);
        return "result";
    }
}

Returning JSON Responses with @ResponseBody

The @ResponseBody annotation enables controllers to return data directly as JSON, elimianting the need for view resolution. This is essential for building RESTful APIs and AJAX-powered interfaces.

<h3>JSON API Tests</h3>
<input type="button" value="Single Object" class="json-btn" data-target="single">
<input type="button" value="Object List" class="json-btn" data-target="list">
<input type="button" value="Map Data" class="json-btn" data-target="map">
<script type="text/javascript">
    $(".json-btn").click(function() {
        var endpoint = "${pageContext.request.contextPath}/api/" + $(this).data("target");
        $.post(endpoint, null, function(response, status, xhr) {
            alert(xhr.responseText);
        });
    });
</script>

@Controller
@RequestMapping("/api")
public class ApiController {
    
    @RequestMapping("/single")
    public @ResponseBody Person getSinglePerson() {
        return new Person("Alice", "Developer", "28");
    }
    
    @RequestMapping("/list")
    public @ResponseBody List<Person> getPersonList() {
        List<Person> users = new ArrayList<Person>();
        users.add(new Person("Dog", "Breed1", "3"));
        users.add(new Person("Cat", "Breed2", "4"));
        return users;
    }
    
    @RequestMapping("/map")
    public @ResponseBody Map<String, Object> getMapData() {
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("count", 1);
        data.put("title", "Sample");
        return data;
    }
}

Tags: SpringMVC java web development Spring Framework

Posted on Mon, 19 Oct 2026 16:18:19 +0000 by basheer12m