Spring MVC快速教程:表单处理 Spring MVC Fast Tutorial: Form Processing

Spring MVC Fast Tutorial: Form Processing

:!: This tutorial is out of date. See the new version for Spring 4.

What are we going to build?

A form to create a new car.

Spring Form Processing

Form Controller

Struts controllers extend Action whereas Spring controllers extend/implement a Controller class/interface. There are many of them. The most basic is Controller, used previously. To process a form,SimpleFormController is generally used.

A form controller has two roles:

  • initialize the form's initial values
  • process/persist submitted user input:

Command

A Command object is used to store the form values: it's equivalent to a Struts Action Form. However, it doesn't have to extend nor implement anything. So it's even possible to directly use the model class! (Car in our example)

Manager Classes

We need a method to create a car in 'WEB-INF/src/springmvc/service/CarManager.java':

public Car createCar(Car c) {
	Car car = new Car();
	car.setId((long)carList.size() + 1);
	car.setBrand(c.getBrand());
	car.setModel(c.getModel());
	car.setPrice(c.getPrice());
 
	carList.add(car);
 
	return car;
}

We also need a manager for brands, 'WEB-INF/src/springmvc/service/BrandManager.java':

package springmvc.service;
 
import java.util.LinkedList;
import java.util.List;
 
import springmvc.model.Brand;
 
public class BrandManager {
 
	private static List<Brand> brandList;
 
	static {
		Brand brand1 = new Brand();
		brand1.setId((long)1);
		brand1.setName("Mercedes");
		brand1.setCountry("Germany");		
 
		Brand brand2 = new Brand();
		brand2.setId((long)2);
		brand2.setName("Peugeot");
		brand2.setCountry("France");		
 
		brandList = new LinkedList<Brand>();
		brandList.add(brand1);
		brandList.add(brand2);		
	}
 
	public List<Brand> getBrandList() {
		return brandList;
	}	
 
	public Brand getBrandById(Long id) {
		for (Brand brand : brandList) {
			if (brand.getId().equals(id))
				return brand;
		}
		return null;
	}
}

Let's not frown upon the data duplication, it's not the point here :-)

Controller

In 'WEB-INF/springmvc-servlet.xml', we declare a new URL and its Controller:

<bean name="/new_car.html" class="springmvc.web.CarNewController">
    <property name="commandClass" value="springmvc.model.Car"/>
    <property name="formView" value="carNew"/>
    <property name="successView" value="list_cars.html"/>
</bean>
  • commandClass: the Command class
  • formView: the form view name
  • successView: where we go after the form has been successfully submitted

We now create this Controller: 'WEB-INF/src/springmvc/web/CarNewController.java':

package springmvc.web;
 
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
 
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.view.RedirectView;
 
import springmvc.model.Brand;
import springmvc.model.Car;
import springmvc.service.BrandManager;
import springmvc.service.CarManager;
 
public class CarNewController extends SimpleFormController {
 
    @Override
    protected Object formBackingObject(HttpServletRequest request) throws Exception {
    	Car defaultCar = new Car();
    	defaultCar.setModel("new model");
    	defaultCar.setPrice(new BigDecimal(15000));
    	return defaultCar;
    }
 
    @Override
    protected Map referenceData(HttpServletRequest request) throws Exception {
    	Map<Object, Object> dataMap = new HashMap<Object, Object>();
    	BrandManager brandManager = new BrandManager();
    	dataMap.put("brandList", brandManager.getBrandList());
    	return dataMap;
    }
 
    @Override
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    	binder.setDisallowedFields(new String[] {"brand"});
 
    	Car car = (Car)binder.getTarget();
 
    	// set car's brand from request parameter brand id
    	BrandManager brandManager = new BrandManager();    	
    	Long brandId = null;
    	try {
	    	brandId = Long.parseLong(request.getParameter("brand"));
		} catch (Exception e) {}		
		if (brandId != null) {
			Brand brand = brandManager.getBrandById(brandId);
			car.setBrand(brand);
		}    
    }
 
    @Override
    public ModelAndView onSubmit(Object command) throws ServletException {
    	CarManager carManager = new CarManager();
    	carManager.createCar((Car)command);
 
    	return new ModelAndView(new RedirectView(getSuccessView()));
    }
 
}

These methods are called before the form is displayed:

  • formBackingObject: initialize the Command used to init the form.
  • referenceData: set the view attributes (using a Map)

These are called after:

  • initBinder: prevent Spring to do some bindings and so them by ourselves if needed. Here we used the brand id parameter to set the actual Brand.
  • onSubmit: the main code. In this case, we used the command object, which is a Car, to create a new Car.

View

Let's now create the view 'jsp/carNew.jsp':

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
 
<html>
<body>
	<h1>New Car</h1>
 
	<form:form method="post">
 
		Brand<br />
		<form:select path="brand">
		   <form:options items="${brandList}" itemLabel="name" itemValue="id" />
		</form:select>
		<br /><br />
 
		Model<br />
		<form:input path="model"/><br /><br />
 
		Price<br />
		<form:input path="price"/><br /><br />
 
		<input type="submit" value="Submit">
 
	</form:form>
</body>
</html>

It's blissfully simple. We use the brandList attribute defined in referenceDatamethod in the controller to populate the form select.

Result

We rebuild (ant), relaunch Tomcat and check it's working:http://localhost:8180/springmvc/new_car.html

Summary

Your project should now look like that:

You can download it here.

This is how Spring processes a form. Some advantages compared to Struts:

  • controller code is divided between several methods to override only when necessary
  • model beans can be used as form beans: no extra classes to write. For complex attributes (like brand in our example), we can override Spring and do the bindings ourselves.
  • xml configuration is clear and straightforward
from: http://jeromejaglale.com/doc/java/spring/form_processing
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值