Spring MVC

Introductie

Dit is een van de artikelen uit een reeks over Spring. Zie ook de volgende delen :

Introductie

Spring MVC organiseert de interactie (Control) tussen gebruikersinterface (View) en het Model met de business objecten. Het is gebaseerd op het MVC pattern waarbij scheiding wordt aangebracht tussen presentatie, navigatie logic en business logic. Onderstaande figuur toont de samenwerking tussen de onderdelen die hierbij een rol spelen.

  1. Een http (html of xhtml) request vanuit een browser wordt doorgestuurd naar de Spring DispatcherServlet.
  2. De Spring DispatcherServlet stuurt het request naar een controller class aan de hand van een HandlerMapping waarin de relaties tussen requests en controllers is geconfigureerd.
  3. De controller voert de benodigde verwerking uit door benadering van model classes.
  4. De controller retourneert na afloop van het werk een ModelAndView object met model data en een view naam terug naar de DispatcherServlet.
  5. De DispatcherServlet zal m.b.v. een ViewResolver de benodigde JSP (of JSF) aanroepen en daarbij de model data doorgeven om deze te laten renderen naar de benodigde presentatie. De JSP/JSF bestandsnaam wordt samengesteld o.b.v. de view naam die de controller class doorgeeft.
  6. De view zal de benodigde html output renderen en terugsturen naar de browser waar deze wordt getoond.

Om dit geheel te laten werken is een combinatie van xml bestanden en classes met annotaties nodig.

  • web.xml : definieert de DispatcherServlet als normale servlet
  • [servletnaam]-servlet.xml : definieert de ViewResolver voor de mapping van view namen naar JSP (of JSF) bestandsnamen.
  • applicationContext.xml : is het bestand met de overige Spring metagegevens met de verschillende bean configuraties om de verschillende dependency injections mogelijk te maken. Deze wordt zoveel mogelijk gebaseerd op de mogelijkheid om beans via annotaties te configureren.

Buiten deze xml bestanden worden controller classes gemaakt die worden voorzien van Spring MVC annotaties. Deze controller classes zullen de model classes benaderen voor uitvoering van het echte werk. De model classes bestaan uit DAO’s en (JPA/Hibernate) Entities. Er wordt veelal nog een extra “Service” laag toegevoegd als een facade tussen control en model classes. Maar deze kan ook worden wegbezuinigd. De zin van de servicelaag is afhankelijk van de verwachte toegevoegde waarde aan business logic die hieraan kan worden toegekend.

web.xml met DispatcherServlet

De DispatcherServlet wordt als normale servlet gedefinieerd in web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>dierentuin</display-name>
  	<servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/control/*</url-pattern>
    </servlet-mapping>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<welcome-file-list>
	    <welcome-file>index.html</welcome-file>
	</welcome-file-list>
</web-app>

[servletnaam]-servlet.xml met de ViewResolver

De DispatcherServlet krijgt in web.xml de naam “dispatcher”. Als Spring conventie houdt dat in dat er in WEB-INF/ ook een bestand dispatcher-servlet.xml ( [servletnaam]-servlet.xml) moet komen. Dit bestand is een Spring metagegevens bestand waarin de ViewResolver wordt gedefinieerd en geconfigureerd. Voor de ViewResolver wordt gespecificeerd hoe JSP (of JSF) bestandsnamen worden samengesteld. Deze worden samengesteld met de View namen die door controller classes worden geretourneerd. De prefix /jsp/ geeft aan dat deze JSP’s zich bevinden in subdirectory /jsp/. De suffix property geeft aan dat het om .jsp bestanden gaat. Dat had ook een .jsf bestand kunnen zijn. Het gaat dus om “/jsp/[Viewnaam].jsp”.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context.xsd


http://www.springframework.org/schema/tx


http://www.springframework.org/schema/tx/spring-tx.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop.xsd

	http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">

	<bean id="viewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver"
    	      p:prefix="/jsp/" p:suffix=".jsp" />

</beans>

applicationContext.xml

applicationContext.xml is het bestand met de overige Spring metagegevens met de verschillende bean configuraties om de verschillende dependency injections mogelijk te maken. Deze wordt zoveel mogelijk gebaseerd op de mogelijkheid om beans via annotaties te configureren. De volgende tags zijn hier van belang:

  • <context:annotation-config> : geeft aan dat dependency injection via annotaties verloopt
  • <context:component-scan> : specificeert de packages waarvan de geannoteerde classes automatisch als beans worden opgenomen als Spring beans
  • <tx:annotation-driven> : geeft aan dat transactie management met annotaties wordt gespecificeerd.
  • <mvc:annotation-driven> geeft aan dat mvc via annotaties wordt gespecificeerd.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context.xsd


http://www.springframework.org/schema/tx


http://www.springframework.org/schema/tx/spring-tx.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop.xsd

	http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd

http://www.springframework.org/schema/mvc


http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

	<context:annotation-config/>
	<context:component-scan base-package="org.biz.dierentuin5" />
    	<tx:annotation-driven />
    	<mvc:annotation-driven />

	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource"
		p:driverClassName="org.hsqldb.jdbcDriver" p:url="jdbc:hsqldb:mem:dierentuindb"
		p:username="sa" p:password="" />

	<bean id="entityManagerFactory"
              class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="PU"/>
	</bean>

	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
		p:entityManagerFactory-ref="entityManagerFactory" />

</beans>

Controller Classes

Hieronder een voorbeeld van een controller class voor het Hond object.
Met @Controller wordt de class als Spring controller gedefinieerd.
Met @RequestMapping wordt aangegeven met welk url pad deze wordt geadresseerd waarmee de DispatcherServlet de mapping kan maken van http request naar controller en method.
Dus voor request “http:/[host]:[port]/[project]/hond/addhond.html” wordt de method addHond() van class HondController aangeroepen.
De request “addhondpost.html” is van type “POST” en wordt aangeroepen t.b.v. een Form Submit uit Form van een JSP.

Met de return statements wordt een View naam geretourneerd waarmee een aan te roepen JSP/JSF bestandnaam wordt gemaakt. In het bestand dispatcher-servlet.xml
( [servletnaam]-servlet.xml) was als pad /jsp/*.jsp gespecificeerd. In de commentaren hieronder is te zien wat de betreffende jsp’s zijn die aangeroepen zullen worden na de returns.

In addHondPost() is te zien dat een Form veld “fldNaam” vanuit de JSP wordt meegegeven. Hierin is ook het argument “Mapmodel” te zien. Deze wordt gebruikt om model data terug te geven aan de JSP die na de return wordt aangeroepen.

De controller maakt gebruik van de geïnjecteerde DAO “HondDao” om de hond data te schrijven en lezen.

@Controller
@RequestMapping("/hond")
public class HondController  {

	@Autowired
	protected HondDAO hondDao;

	//stuur addhond.jsp form naar browser
	@RequestMapping(value = "/addhond.html", method = RequestMethod.GET)
        public String addHond() {

    	// Wordt gekoppeld aan /jsp/addhond.jsp
    	return "addhond";
	}

	//verwerk input van addhond.jsp
	@RequestMapping(value = "/addhondpost.html", method = RequestMethod.POST)
	public String addHondPost(@RequestParam(value="fldNaam", required=true) String fldNaam,
Map<String, Object> model) {

		Hond hond = new Hond();
		hond.setNaam(fldNaam);
		hondDao.save(hond);

		model.put("fldNaam", fldNaam);

		List<Hond> honden = hondDao.getAll();
		model.put("honden", honden);

	    // Wordt gekoppeld aan /jsp/honden.jsp
	    return "honden";
	}

	//stuur honden.jsp form naar browser
	@RequestMapping(value = "/honden.html", method = RequestMethod.GET)
	public String Honden(Map<String, Object> model) {

		List<Hond> honden = hondDao.getAll();
		model.put("honden", honden);

	    // Wordt gekoppeld aan /jsp/honden.jsp
	    return "honden";
	}

}

JSP bestanden

Hieronder een voorbeeld van het bestand “addhond.jsp” om een nieuwe hond toe te voegen.
Voor het form wordt de request “addhondpost.html” gedefinieerd waarmee een controller class “HondController” en method “addHondPost()” zal worden aangroepen zoals in voorgaande paragraaf besproken. Te zien is het veld “fldNaam” waarvan de waarde wordt doorgegeven aan de control class.
NB: Spring heeft een eigen “form” taglibrary om forms te gebruiken. Eigenlijk moeten ook de form fields hier gebruik van maken. In dit voorbeeld is dat niet gedaan.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Nieuwe Hond</title>
</head>
<body>
<h1>Nieuwe Hond</h1>
<form:form action="addhondpost.html">
	<table>
		<tr>
			<td>Nieuwe Hond:</td>
			<td><input type="text" name="fldNaam" size="100"/></td>
		</tr>
		<tr>
			<td colspan="2" align="center">
				<input type="submit" value="Submit" />
			</td>
		</tr>
	</table>
</form:form>
</body>
</html>

Hieronder het bestand “honden.jsp” die de lijst honden toont die door de controller class zijn doorgegeven.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Honden</title>
</head>
<body>
<h1>Honden</h1>

<c:if test="${not empty honden}" >
<ul>
	<c:forEach items="${honden}" var="hond">
			<li><c:out value="${hond.naam}" /></li>
	</c:forEach>
</ul>
</c:if>
<c:if test="${empty honden}" >
	Geen honden aanwezig.
</c:if>
<a href="/DierenTuin/control/hond/addhond.html">Nieuwe Hond</a><br/>
<a href="/DierenTuin/index.html">Home</a>
</body>
</html>

Maven dependencies

Uiteraard zijn er additionele Spring MVC modules en Servlet/JSP libraries nodig, waarvan de jar’s in Maven worden gedefinieerd.

De Spring kern :

     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>3.2.0.RELEASE</version>
    </dependency>

De Spring Web / MVC module:

      <dependency>
	      <groupId>org.springframework</groupId>
	      <artifactId>spring-web</artifactId>
	      <version>3.2.0.RELEASE</version>
      </dependency>
      <dependency>
	      <groupId>org.springframework</groupId>
	      <artifactId>spring-webmvc</artifactId>
	      <version>3.2.0.RELEASE</version>
      </dependency>

De Spring ORM module:

  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-orm</artifactId>
  		<version>3.2.0.RELEASE</version>
  	</dependency>

De Servlet api:

      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
       </dependency>

Voor de in het voorbeeld gebruikte JSP toepassing is nog de volgende aanvulling nodig:

      <dependency>
	    <groupId>jstl</groupId>
	    <artifactId>jstl</artifactId>
	    <version>1.1.2</version>
      </dependency>
      <dependency>
	    <groupId>taglibs</groupId>
	    <artifactId>standard</artifactId>
	    <version>1.1.2</version>
      </dependency>
This entry was posted in JSP, Spring, Web and tagged , , . Bookmark the permalink.

One Response to Spring MVC

  1. Lucas says:

    - Hannie, these are absolutely baaithtrkeng. Inspiring. Sweet. Beautiful. I love how photography has a way of so gracefully pulling you into a story in such an overwhelmingly powerful way. Jennifer, you did an amazing job! I can’t wait to see part II February 6, 2012 1:48 PM

Geef een reactie

Je e-mailadres wordt niet gepubliceerd.

De volgende HTML tags en attributen zijn toegestaan: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>