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;
}
}