Example 1. PersonController
The @Controller
indicates the class is a Spring MVC controller stereotype which is automatically registered
by context:component-scan in the web-application-context.xml.
Because the convention based handler ControllerClassNameHandlerMapping
was used to configure this controller,
requests will map to the class name (up unto the 'Controller' suffix) and method names. While using the method signatures and
@RequestMapping
annotations to help target if a method is specifically for a certain type of HTTP request.
More sophisticated targeting based on available parameters can also be done, but is not needed in this example.
The first method, newRequest
, is annotated with @ModelAttribute
. This indicates that the
method will be called before every request. In this case it takes the request parameter 'id', but doesn't require
the parameter. By default specifying @RequestParameter
would cause an error if it wasn't available and
no other method was available for processing the request. The newRequest
method looks up the
person from the database and returns it or if the 'id' param is null it returns a new instance for the
form to bind to. Without specifying a specific name for the model to be bound to, it will be bound to the
class name. So Person
will be bound to 'person'.
The first form
method handles a create and edit for an HTTP GET request since
it's annotated with @RequestMapping(method=RequestMethod.GET)
. It's just a place holder since
the newRequest
method has already created or retrieved the appropriate bean from the db.
By default, Spring will continue forwarding the request where it was headed before it was intercepted by
the controller. This could be changed by returning a String
with the new path or
by returning a view instance (like ModelAndView
.
The second form
method handles a save from the person form. It will only accept
a request that is an HTTP POST and it has the method signature form(Person person, Model model)
.
By specifying the person
variable, Spring will automatically retrieve or create (depending on it's scope)
an instance of Person
and bind any available request parameters to it. Since it is also the default model
object, any values set on it will be available on the page the request forwards to. The Model
is made available just by specifying it. This can also be done for the HttpServletRequest
and HttpServletResponse
. The method sets a create date if one isn't already set, saves the
person bean, then if it is create the new id is set on the person instance. After this a success
message is set on the model for display on form.
The last two method are delete
and search
. The delete
method is
very straight forward. It just deletes person, and then redirects to the search page.
The search
method retrieves all persons and returns them in a Collection
.
It doesn't explicitly set the return value to be bound to the scope 'persons' using the
@ModelAttribute(SEARCH_MODEL_KEY)
.
@Controller public class PersonController { private static final String SEARCH_VIEW_KEY = "redirect:search.html"; private static final String SEARCH_MODEL_KEY = "persons"; @Autowired protected PersonDao personDao = null; /** * For every request for this controller, this will * create a person instance for the form. */ @ModelAttribute public Person newRequest(@RequestParam(required=false) Integer id) { return (id != null ? personDao.findPersonById(id) : new Person()); } /** * <p>Person form request.</p> * * <p>Expected HTTP GET and request '/person/form'.</p> */ @RequestMapping(method=RequestMethod.GET) public void form() {} /** * <p>Saves a person.</p> * * <p>Expected HTTP POST and request '/person/form'.</p> */ @RequestMapping(method=RequestMethod.POST) public void form(Person person, Model model) { if (person.getCreated() == null) { person.setCreated(new Date()); } Person result = personDao.save(person); // set id from create if (person.getId() == null) { person.setId(result.getId()); } model.addAttribute("statusMessageKey", "person.form.msg.success"); } /** * <p>Deletes a person.</p> * * <p>Expected HTTP POST and request '/person/delete'.</p> */ @RequestMapping(method=RequestMethod.POST) public String delete(Person person) { personDao.delete(person); return SEARCH_VIEW_KEY; } /** * <p>Searches for all persons and returns them in a * <code>Collection</code>.</p> * * <p>Expected HTTP GET and request '/person/search'.</p> */ @RequestMapping(method=RequestMethod.GET) public @ModelAttribute(SEARCH_MODEL_KEY) Collection<Person> search() { return personDao.findPersons(); } }