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.
The @RequestMapping
annotation on the methods use the value attribute to
map the method to a path. The method attribute is used to indicate the HTTP request type
(ex: GET, POST, DELETE). 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 returns the saved person instance which replaces the existing model after 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"; private final PersonRepository repository; @Autowired public PersonController(PersonRepository repository) { this.repository = repository; } /** * 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 ? repository.findOne(id) : new Person()); } /** * <p>Person form request.</p> * * <p>Expected HTTP GET and request '/person/form'.</p> */ @RequestMapping(value="/person/form", method=RequestMethod.GET) public void form() {} /** * <p>Saves a person.</p> * * <p>Expected HTTP POST and request '/person/form'.</p> */ @RequestMapping(value="/person/form", method=RequestMethod.POST) public Person form(Person person, Model model) { if (person.getCreated() == null) { person.setCreated(new Date()); } Person result = repository.saveAndFlush(person); model.addAttribute("statusMessageKey", "person.form.msg.success"); return result; } /** * <p>Deletes a person.</p> * * <p>Expected HTTP POST and request '/person/delete'.</p> */ @RequestMapping(value="/person/delete", method=RequestMethod.POST) public String delete(Person person) { repository.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(value="/person/search", method=RequestMethod.GET) public @ModelAttribute(SEARCH_MODEL_KEY) Collection<Person> search() { return repository.findAll(); } }