コントローラはSimpleFormControllerを使います。
チェックボックスで受け付けるため、配列が入力されることが前提となります。
また件数可変の一覧表示画面から、spring:bindタグを使って動的にデータをBeanに入れています。
【手順概要】
変更対象選択用Bean(SelectProducts)を追加します。
SelectInventorysControllerを追加します。
変更対象複数選択画面を追加します。
springapp-servlet.xmlにエントリーを追加します。
メッセージを追加します。
リンクを追加します。
価格設定用Bean(SetPrices)を追加します。
バリデータ(SetPricesValidator)を追加します。
SetPricesFormControllerを追加します。
価格設定用画面を追加します。
メッセージを追加します。
springapp-servlet.xmlにエントリーを追加します。
【手順詳細】
SelectProducts
チェックボックスなので配列を取ります。
package springapp.service;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import springapp.domain.Product;
public class SelectProducts {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private List<Product> products = null;
private int[] ids = null;
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public int[] getIds() {
return ids;
}
public void setIds(int[] ids) {
this.ids = ids;
StringBuffer log = new StringBuffer();
for(int i = 0; i < ids.length; i++) {
log.append("id[");
log.append(i);
log.append("]=");
log.append(ids[i]);
log.append("; ");
}
logger.info(log);
}
}
SelectInventorysFormControllerを追加します。
package springapp.web;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import springapp.service.ProductManager;
import springapp.service.SelectProducts;
public class SelectInventorysFormController extends SimpleFormController {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private ProductManager productManager;
protected Object formBackingObject(HttpServletRequest request)
throws ServletException {
SelectProducts selectProducts = new SelectProducts();
logger.info("productManager:" + productManager.getProducts().size());
selectProducts.setProducts(productManager.getProducts());
logger.info("selectProd:" + selectProducts.getProducts().size());
return selectProducts;
}
@Override
protected ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
logger.info("Executed.");
SelectProducts sp = (SelectProducts) command;
StringBuffer log = new StringBuffer();
log.append("SelectProduct.getIds():");
int[] i = sp.getIds();
for (int j = 0; j < i.length; j++) {
log.append("id[");
log.append(j);
log.append("]=");
log.append(i[j]);
log.append("; ");
}
logger.info(log);
HttpSession session = request.getSession();
session.setAttribute("SelectProducts", sp);
return new ModelAndView(new RedirectView(getSuccessView()));
}
public void setProductManager(ProductManager productManager) {
this.productManager = productManager;
}
public ProductManager getProductManager() {
return productManager;
}
}
変更対象複数選択画面を追加します。
<%@ include file="/WEB-INF/jsp/include.jsp" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head><title><fmt:message key="title"/></title></head>
<body>
<h1><fmt:message key="selectproducts.heading"/></h1>
<h3>Products</h3>
<form:form method="post" commandName="selectProducts">
<c:forEach items="${selectProducts.products}" var="prod" varStatus="row">
<input type="checkbox" id="ids" name="ids" value="<c:out value="${prod.id}"/>">
<c:out value="${prod.description}"/>
<i>$<c:out value="${prod.price}"/></i><br><br>
</c:forEach>
<input type="submit" align="center" value="Execute">
</form:form>
<br>
<a href="<c:url value="hello.htm"/>">back</a><br>
<br>
</body>
</html>
springapp-servlet.xmlにエントリーを追加します。
<bean name="/selectproduct.htm" class="springapp.web.SelectInventoryFormController">
<property name="sessionForm" value="true"/>
<property name="commandName" value="selectProduct"/>
<property name="commandClass" value="springapp.service.SelectProduct"/>
<property name="formView" value="selectproduct"/>
<property name="successView" value="setprice.htm"/>
<property name="productManager" ref="productManager"/>
</bean>
メッセージを追加します。
selectproducts.heading=Select Products :: SpringApp
トップページ(hello.jsp)にリンクを追加します。
<br><a href="<c:url value="selectproducts.htm"/>">Select products</a>
価格設定用Bean(SetPrices)を追加します。
妙にリッチな作りになっていますが(結果的に無意味だった)試行錯誤の結果です。
恐らく(面倒くさいので検証していませんが)setProducts(List<Product> products) だけでよいのではないかと思います。(あるべき姿は後日調査予定)
package springapp.service;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import springapp.domain.Product;
public class SetPrices {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private List<Product> products = new ArrayList<Product>();
private int[] ids = null;
private String[] descriptions = null;
private double[] prices = null;
private static final int DEFALUT_NUM = 3;
private int position = 0;
public SetPrices(int num) {
initialize(num);
}
public SetPrices() {
initialize(DEFALUT_NUM);
}
private void initialize(int number) {
ids = new int[number];
descriptions = new String[number];
prices = new double[number];
}
public void setProducts(List<Product> products) {
this.products = products;
}
public void addProduct(Product prod) {
products.add(prod);
ids[position] = prod.getId();
descriptions[position] = prod.getDescription();
prices[position] = prod.getPrice();
position++;
}
public List<Product> getProducts() {
return products;
}
public int[] getIds() {
return ids;
}
public void setIds(int[] ids) {
this.ids = ids;
}
public String[] getDescriptions() {
return descriptions;
}
public void setDescriptions(String[] descriptions) {
this.descriptions = descriptions;
}
public double[] getPrices() {
return prices;
}
public void setPrices(double[] prices) {
this.prices = prices;
}
}
バリデータ(SetPricesValidator)を追加します。
package springapp.service;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import springapp.domain.Product;
public class SetPricesValidator implements Validator {
private int DEFAULT_MIN_PRICE = 1;
private int minPrice = DEFAULT_MIN_PRICE;
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
public boolean supports(Class clazz) {
return SetPrices.class.equals(clazz);
}
public void validate(Object obj, Errors errors) {
SetPrices ps = (SetPrices) obj;
for (Product product : ps.getProducts()) {
logger.info("Validating ...");
if (product.getPrice() == null) {
logger.info("Price is null.");
errors.rejectValue("prices", "error.price-not-specified", null,
"Value required.");
} else {
logger.info(product);
if (product.getPrice() <= minPrice) {
errors.rejectValue("prices", "error.too-cheap",
new Object[] { new Integer(minPrice) },
"Value too low.");
}
}
logger.info("Validation end.");
}
}
public void setMinPrice(int i) {
minPrice = i;
}
public int getMinPercentage() {
return minPrice;
}
public void setMaxPercentage(int i) {
minPrice = i;
}
public int getMaxPercentage() {
return minPrice;
}
}
SetPricesFormControllerを追加します。
package springapp.web;
import java.util.List;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import springapp.domain.Product;
import springapp.service.ProductManager;
import springapp.service.SelectProducts;
import springapp.service.SetPrices;
public class SetPricesFormController extends SimpleFormController {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private ProductManager productManager;
public ModelAndView onSubmit(Object command) throws ServletException {
List<Product> products = ((SetPrices) command).getProducts();
for (Product product : products) {
productManager.setPrice(product.getId(), product.getPrice());
}
return new ModelAndView(new RedirectView(getSuccessView()));
}
protected Object formBackingObject(HttpServletRequest request)
throws ServletException {
SetPrices ret = new SetPrices();
SelectProducts sp = (SelectProducts) request.getSession().getAttribute(
"SelectProducts");
int[] i = sp.getIds();
for (Product product : productManager.getProducts()) {
for (int j = 0; j < i.length; j++) {
if (product.getId() == i[j]) {
ret.addProduct(product);
break;
}
}
}
return ret;
}
public void setProductManager(ProductManager productManager) {
this.productManager = productManager;
}
public ProductManager getProductManager() {
return productManager;
}
}
価格設定用画面を追加します。
恐らくはここがキモになります。
spring:bindタグを使っています。
参考サイト:Dynamic list binding in Spring MVC
<%@ include file="/WEB-INF/jsp/include.jsp" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<title><fmt:message key="title"/></title>
<style>
.error { color: red; }
</style>
</head>
<body>
<h1><fmt:message key="setprices.heading"/></h1>
<form:form method="post" commandName="setPrices">
<c:forEach items="${setPrices.products}" varStatus="row">
<spring:bind path="setPrices.products[${row.index}].id">
<input type="hidden"
name="<c:out value="${status.expression}"/>"
id="<c:out value="${status.expression}"/>"
value="<c:out value="${status.value}"/>" />
</spring:bind>
<spring:bind path="setPrices.products[${row.index}].description">
<c:out value="${status.value}"/>
</spring:bind>
<spring:bind path="setPrices.products[${row.index}].price">
<input type="text"
name="<c:out value="${status.expression}"/>"
id="<c:out value="${status.expression}"/>"
value="<c:out value="${status.value}"/>" />
</spring:bind>
<br>
</c:forEach>
<form:errors path="prices" cssClass="error"/>
<br>
<input type="submit" align="center" value="Execute">
</form:form>
<a href="<c:url value="hello.htm"/>">Home</a>
</body>
</html>
メッセージを追加します。
error.price-not-specified=Price not specified!!!
setprices.heading=Set Prices :: SpringApp
springapp-servlet.xmlにエントリーを追加します。
<bean name="/setprices.htm" class="springapp.web.SetPricesFormController">
<property name="sessionForm" value="true"/>
<property name="commandName" value="setPrices"/>
<property name="commandClass" value="springapp.service.SetPrices"/>
<property name="validator">
<bean class="springapp.service.SetPricesValidator"/>
</property>
<property name="formView" value="setprices"/>
<property name="successView" value="hello.htm"/>
<property name="productManager" ref="productManager"/>
</bean>
以上。疲れた・・・
0 件のコメント:
コメントを投稿