1.1.14.4.1. fejezet, Web MVC

Ez csak az egyik oldala a Spring-nek, de jelentős oldala.

Java 5 EE-től már annotációkat is használhatunk, ami jelentősen csökkenti a konfigurációs feladatainkat. Lássunk egy példát a spring konfigurálására:

dispatcher-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="...">
 
	<bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
 
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" p:basename="messages" />
 
    <context:component-scan base-package="com.vaannila.web" />
 
    <bean id="userService" class="com.vaannila.service.UserServiceImpl" />
    <bean id="userValidator" class="com.vaannila.validator.UserValidator" />    
</beans>

és nézzük meg a web.xml-t

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="...">
  <display-name>SpringExample12</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>*.htm</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>redirect.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Ha UTF-8 támogatásra van szükségünk, tegyük bele a web-app tag közé az alábbi filtert:

  <filter>
      <filter-name>encodingFilter</filter-name>
      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
      <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
      </init-param>
      <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
      </init-param>
   </filter>
 
   <filter-mapping>
      <filter-name>encodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>

Látszik, hogy egy DispacherServlet osztályt állítottunk be servlet-nek, ami a Spring egyik web asszisztens osztálya. Ez fogadja a kéréseket, és továbbítja objektumokká alakítva a kontroller osztályoknak.

Fontos észrevennünk, hogy a dispatcher név az előző konfigurációs fájl neveként is szerepel, -servlet.xml végződéssel. Ez az alapértelmezett társítás a Spring konfigurációval.

Nézzük meg a felhasználó kezelőt (UserController.java):

package com.vaannila.web;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
 
//import com.vaannila.domain.Community;
//import com.vaannila.domain.Country;
import com.vaannila.domain.User;
import com.vaannila.service.UserService;
import com.vaannila.validator.UserValidator;
 
@Controller
@RequestMapping("/userRegistration.htm")
@SessionAttributes("user")
public class UserController {
 
	private UserService userService;
	private UserValidator userValidator;
 
	@Autowired
	public UserController(UserService userService, UserValidator userValidator) {
		this.userService = userService;
		this.userValidator = userValidator;
	}
/*
	@ModelAttribute("countryList")
	public List<Country> populateCountryList() {
		return userService.getAllCountries();
	}
 
	@ModelAttribute("communityList")
	public List<Community> populateCommunityList() {
		return userService.getAllCommunities();
	}
*/
	@RequestMapping(method = RequestMethod.GET)
	public String showUserForm(ModelMap model) {
		User user = new User();
		model.addAttribute("user", user);
		return "userForm";
	}
 
	@RequestMapping(method = RequestMethod.POST)
	public String onSubmit(@ModelAttribute("user") User user,
			BindingResult result) {
		userValidator.validate(user, result);
		if (result.hasErrors()) {
			return "userForm";
		} else {
			userService.add(user);
			return "redirect:userSuccess.htm";
		}
	}
 
}

Ebben látszik néhány magáért beszélő annotáció. A @RequestMapping-ban megadott kérés útvonal a servlet eléréséhez viszonyítva relatív. Látszik még az onSubmit metódusban egy értékellenőrzés, amit a konfigurációs fájlban is leírtunk. Lássuk az értékellenőrző osztályt (UserValidator.java):

package com.vaannila.validator;
 
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
 
import com.vaannila.domain.User;
 
public class UserValidator implements Validator {
 
	@Override
	public boolean supports(Class<?> clazz) {
		return User.class.isAssignableFrom(clazz);
	}
 
	@Override
	public void validate(Object target, Errors errors) {
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name",
				"name.required");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password",
				"password.required");
		ValidationUtils.rejectIfEmpty(errors, "gender", "gender.required");
		ValidationUtils.rejectIfEmpty(errors, "country", "country.required");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "aboutYou",
				"aboutYou.required");
		User user = (User) target;
		if (user.getCommunity().length == 0) {
			errors.rejectValue("community", "community.required");
		}
	}
 
}

A UserController.java fájlban a country és community attribútumokat és kezelő metódusaikat azért kommenteztem ki, mert a userForm.jsp-be kerültek át az általuk szolgáltatott adatok:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!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=ISO-8859-1">
<title>Registration Page</title>
<style>
.error {
color: #ff0000;
font-style: italic;
}
</style>
</head>
<body>
 
<form:form method="POST" commandName="user">
	<table>
		<tr>
			<td>User Name :</td>
			<td><form:input path="name" /></td>
			<td><form:errors path="name" cssClass="error" /></td>
		</tr>
		<tr>
			<td>Password :</td>
			<td><form:password path="password" /></td>
			<td><form:errors path="password" cssClass="error" /></td>
		</tr>
		<tr>
			<td>Gender :</td>
			<td><form:radiobutton path="gender" value="M" label="M" /> 
				<form:radiobutton path="gender" value="F" label="F" /></td>
			<td><form:errors path="gender" cssClass="error" /></td>	
		</tr>
		<tr>
			<td>Country :</td>
			<td><form:select path="country">
				<form:option value="" label="Select" />
				<form:option value="1" label="India" />
				<form:option value="2" label="USA" />
				<form:option value="3" label="UK" />
			</form:select></td>
			<td><form:errors path="country" cssClass="error" /></td>
		</tr>
		<tr>
			<td>About you :</td>
			<td><form:textarea path="aboutYou" /></td>
			<td><form:errors path="aboutYou" cssClass="error" /></td>
		</tr>
		<tr>
			<td>Community :</td>
			<td><form:checkbox path="community" value="Spring"
				label="Spring" /> <form:checkbox path="community" value="Hibernate"
				label="Hibernate" /> <form:checkbox path="community" value="Struts"
				label="Struts" /></td>
			<td><form:errors path="community" cssClass="error" /></td>
		</tr>
		<tr>
			<td colspan="3"><form:checkbox path="mailingList"
				label="Would you like to join our mailinglist?" /></td>
		</tr>
		<tr>
			<td colspan="3"><input type="submit" value="Register"></td>
		</tr>
	</table>
</form:form>
 
</body>
</html>

A mellékelt SpringExample12 minta egyesített változata a 8-as (Spring Form Validation) és 12-es (Spring Annotations) forrásnak. Az eredeti mintaprogramok megtalálhatóak itt. Ha mégis szükséges lenne szerver oldalról biztosítani néhány mező tartalmát, az old mappába megtaláljuk az osztályokat, amik a com.vaanilla.domain könyvtárba valók (ne felejtsük el átírni a package útvonalat), és a kikommentezett részeket tegyük vissza a UserController.java-ban. Ezután a userForm.jsp fájl fogadhatja a country és community osztályokat a következő képp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!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=ISO-8859-1">
<title>Registration Page</title>
</head>
<body>
 
<form:form method="POST" commandName="user">
	<table>
		<tr>
			<td>User Name :</td>
			<td><form:input path="name" /></td>
		</tr>
		<tr>
			<td>Password :</td>
			<td><form:password path="password" /></td>
		</tr>
		<tr>
			<td>Gender :</td>
			<td><form:radiobutton path="gender" value="M" label="M" /> <form:radiobutton
				path="gender" value="F" label="F" /></td>
		</tr>
		<tr>
			<td>Country :</td>
			<td><form:select path="country">
				<form:option value="0" label="Select" />
				<form:options items="${countryList}" itemValue="countryId" itemLabel="countryName" />
			</form:select></td>
		</tr>
		<tr>
			<td>About you :</td>
			<td><form:textarea path="aboutYou" /></td>
		</tr>
		<tr>
			<td>Community :</td>
			<td><form:checkboxes path="communityList" items="${communityList}" itemValue="key" itemLabel="value" /></td>
		</tr>
		<tr>
			<td></td>
			<td><form:checkbox path="mailingList"
				label="Would you like to join our mailinglist?" /></td>
		</tr>
		<tr>
			<td colspan="2"><input type="submit"></td>
		</tr>
	</table>
</form:form>
 
</body>
</html>

A sikeres adatrögzítésről a UserSuccessController.java és a userSuccess.jsp értesít. A UserSuccessController.java nem tartalmaz különösebb kódot:

package com.vaannila.web;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
public class UserSuccessController {
 
	@RequestMapping("/userSuccess.htm")
	public String redirect()
	{
		return "userSuccess";
	}
}

Itt látható még egy példa. A redirect metódus egyben a userSuccess.htm kezelő metódusa is. Ez azért fontos, mert ebben az esetben nem az osztály, hanem egy metódus kezeli a kérést. Ez működik több metódus esetén is, ha metódusonként használjuk a @RequestMapping annotációt. Az eredmény megjelenítés érdemi részét a userSuccess.jsp fájl tartalmazza:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
  <head>
    <title>Success Page</title>
  </head>
  <body>
    User Details
  <hr>
    User Name   : <c:out value="${user.name}"></c:out> <br/>
    Gender      : <c:out value="${user.gender}"></c:out> <br/>
    Country     : <c:out value="${user.country}"></c:out> <br/>
    About You   : <c:out value="${user.aboutYou}"></c:out> <br/>
    Community   :
    <c:forEach var="community" items="${user.communityList}" >
      <c:out value="${community}"></c:out>
    </c:forEach> <br />
    Mailing List: <c:out value="${user.mailingList} "></c:out>
  </body>
</html>

Maga a felhasználó osztály pedig egy egyszerű POJO:

package com.vaannila.domain;
 
import java.util.List;
 
public class User {
 
	private String name;
	private String password;
	private String gender;
	private String country;
	private List countryList;
	private String aboutYou;
	private String[] community;
	private List communityList;
	private Boolean mailingList;
 
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String getCountry() {
		return country;
	}
	public void setCountry(String country) {
		this.country = country;
	}
	public List getCountryList() {
		return countryList;
	}
	public void setCountryList(List countryList) {
		this.countryList = countryList;
	}
	public String getAboutYou() {
		return aboutYou;
	}
	public void setAboutYou(String aboutYou) {
		this.aboutYou = aboutYou;
	}
	public String[] getCommunity() {
		return community;
	}
	public void setCommunity(String[] community) {
		this.community = community;
	}
	public List getCommunityList() {
		return communityList;
	}
	public void setCommunityList(List communityList) {
		this.communityList = communityList;
	}
	public Boolean getMailingList() {
		return mailingList;
	}
	public void setMailingList(Boolean mailingList) {
		this.mailingList = mailingList;
	}	
}
CsatolmányMéret
Csomag ikon SpringExample12.zip78.06 KB