I'm looking for a good design pattern/strategy for how to using the Struts 2 framework for editing multiple objects of the same type on an HTML page. Struts is really good for editing a single object, like Address. If you provider accessor methods for address1, city, state, etc, struts calls those and the standard struts UI tags will populate the form fields accordingly.
How to do this when editing multiple of the same type of object on the same page. I have a web based contest, parting of the contest is a set of rating scale objects for each contest. Each rating scale has a value and a label. If I n开发者_运维问答ame the input fields value_0, value_1... and label_0, label_1... then I either have to code a bunch of accessor methods (UGLY) or use the raw parameters to get the values I need. It is difficult, but not impossible, to use the struts validation methods to send error messages back to the correct form field.
If I name all the fields "Value" and "label", struts is kind enough to call a method that sets a List of input values, but I have no way of sending validation errors back to the correct output field.
I need something that doesn't require a huge number of accessor methods, allows easy access to the inputs to validate, return validation messages to the correct form field.
The strategy here is to use a Map<Integer, Address>
.
Example Bean Class
Let's assume the following example Address
class.
public class Address {
private String line1;
private String line2;
private String city;
private String state;
private String zipCode;
// getters and setters here
}
Example Action
public class ExampleAction extends ActionSupport {
/**
* A map of ID -> Address.
*/
private Map<Integer, Address> addresses = Maps.newLinkedHashMap();
// ... action method(s) and validate here
public Map<Integer, Address> getAddresses() {
return addresses;
}
}
In your JSP layer, you can iterate over the map (each iteration is a Map.Entry) and output the fields (line1, line2, city, etc.) for each. The field names should be:
addresses[0].line1
addresses[0].line2
addresses[0].city
addresses[0].state
addresses[0].zipCode
...
addresses[5].line1
addresses[5].line2
addresses[5].city
addresses[5].state
addresses[5].zipCode
To perform validation, just iterate over the map and check each field appropriately. When editing addresses, you can use the primary key of the address from your database. For adding new addresses, you can just increment starting from zero. The index can be any number, so long as its unique within the map.
I typically map out everything I need to use in a form and group them into related classes, Person, Address, Misc for example. I will then create a wrapper class and use delegate accessor methods to provide a single interface to access the individual objects. Most often I work with JPA entites so these classes are already set up for me, I just need the wrapper and maybe some utility methods for CRUD functions. For example:
public class ContactWrapper implements Serializable{
private Person person;
private Address address;
private Misc misc;
// Getters / Setters for primary objects - person, address, misc
...
// Delegate accessors
public String getName(){
return person.getName();
}
public String setName(String name){
return person.setName(name);
}
...
}
Now you have one object to work with in your action class and jsp's which can be references however you choose.
In your action class:
public class ContactAction extends ActionSupport{
private ContactWrapper contact;
....
}
In your JSP:
<s:textfield name="contact.name" />
Struts handles all the object instantiation auto-magically, even in objects contained inside other objects.
精彩评论