Ohne Annotations
Als Beispiel soll ein einfacher HalloWellt-Controller dienen. Klassen, die bei SpringMVC als Controller-Klassen fungieren, müssen das Interface Controller implementieren oder einfach von einer bestehenden Implementierungsklasse ableiten (z.B. SimpleFormController).
<bean id="urlMapping"> <property> <props> <prop key="/hallo">halloController</prop> </props> </property> </bean> <bean name="halloController"/>
Über das URL-Mapping werden Conroller-Klassen unter einer URL registriert. Dieses wird durch das DispatcherServlet
bei eingehenden Requests ausgewertet. In unserem Beispiel wird bei /hallo
der HalloController
aufgerufen.
Mit Annotations
Mit Spring 3.0 wird durch Einführung von Annotations vieles einfacher. Zum einen fällt das Implementieren oder Ableiten von Controller-Interfaces oder Klassen weg. Jede Klasse kann ein Controller sein. Entscheidend ist die Annotation @Controller
.
package de.communardo.spring.mvc; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; @Controller public class HalloWeltController { @RequestMapping(value = "/hallo") public @ResponseBody String helloWorld() { return "Hallo Welt"; } }
Über die Annotation @RequestMapping
werden URL-Pfade auf Methoden gemappt. Über @ResponseBody
wird der Rückgabewert String (="Hallo Welt"
) auf Response.out
geschrieben.
Damit Spring die Klassen mit Annotation (er)kennt, müssen folgende 2 Zeilen in der Spring-XML-Konfiguration aufgenommen werden.
<mvc:annotation-driven /> <context:component-scan base-package= " de.communardo.spring.mvc" />
Dependency Injection
Eines der zentralen Themen bei Spring ist Dependency Injection – Abhängigkeiten zwischen Komponenten werden durch den Container per Setter injiziert. Bei Klassen, die per Spring-XML erzeugt werden, gibt es da eine spezielle Notation für das Injizieren von benötigten Komponenten.
<bean name="halloController"> <property name="serviceLocater" ref="serviceLocater"/> </bean> <bean />
Für Klassen, die per Annotation erzeugt werden, gibt es dafür entsprechende Annotation. Über die Annotation @Autowired
werden per Setter eine Implementierung des Interfaces ServiceLocater injiziert.
package de.communardo.spring.mvc; import org.springframework.beans.factory.annotation.Autowired; import de.communardo.spring.service.ServiceLocater; public class HalloWeltController { private ServiceLocater serviceLocater; @Autowired public void setServiceLocater(ServiceLocater serviceLocater) { this.serviceLocater = serviceLocater; } }
FormController
Für das Formularhandling kommen weitere Annotations hinzu. @ModelAttribute definiert die Formbean, die an das Formular gebunden wird. Im Beispiel ist das userForm
, die im Template per <form:form modelAttribute="userForm">
benutzt wird.
import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.support.SessionStatus; import de.communardo.spring.domain.User; import de.communardo.spring.service.UserService; @Controller @RequestMapping("/editUser") @SessionAttributes("userForm") public class UserController { private static final String VIEW_TEMPLATE_USER = "user"; private UserService userService; @RequestMapping(method = RequestMethod.POST) public String onSubmit(@ModelAttribute("userForm") UserForm userForm, BindingResult result, SessionStatus status) { new UserValidator().validate(userForm, result); if (result.hasErrors()) { return VIEW_TEMPLATE_USER; } userService.storeUser(new User(userForm.getFirstName(), userForm.getLastName(), userForm.getEmail())); return VIEW_TEMPLATE_USER; } @RequestMapping(method = RequestMethod.GET) public String setupForm(Model model) { UserForm userForm = new UserForm(); model.addAttribute("userForm", userForm); return VIEW_TEMPLATE_USER; } @Autowired public void setUserService(UserService userService) { this.userService = userService; } }