A Model instance can add objects without any specified name by using following methods:
Model addAttribute(Object attributeValue)
Model addAllAttributes(Collection<?> attributeValues)
Model object auto generates attribute names and then forward the above method calls to addAttribute(String attributeName, Object attributeValue)
Following are the rules of name generation strategy:
- For an object which is not a collection, short class name is generated. For example for java.lang.String, 'string' will be generated.
- For collections/arrays, 'List' is appended after the type of elements in it e.g. 'stringList'. The collection/array should not be empty because the logic uses the first element to find it's type.
Example
@Controller
public class TheController {
@RequestMapping("/")
public String handleRequest (Model model) {
String string1 = "my string value";
model.addAttribute(string1);
int i = 10;
model.addAttribute(i);
List<String> list = Arrays.asList("one", "two");
model.addAttribute(list);
return "myView";
}
}
myView.jsp
<%@ page language="java"
contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="fm"%>
<html>
<body style="margin:15px;">
<p>String value: ${string}</p>
<p>int value: ${integer}</p>
<br/>
StringList:
<fm:checkboxes path="stringList" items="${stringList}" />
</body>
</html>
Output
If, in a single Model, same object type is being populated various times then we should use explicit attribute name rather than relying on auto name generation.
Some developer would prefer to use explicit names anyways, so that they have more control on attribute names. It's good to use this feature in simple cases though.
The logic of name generation is actually forwarded to the Conventions#getVariableName(..) . Here's a test to understand auto generation rules:
public class VariableNameTest {
public static void main (String[] args) {
Object obj = "test string";
print(obj, "\"test string\"");
obj = new String[]{"one", "two"};
print(obj, "new String[]{\"one\", \"two\"};");
obj = 5;
print(obj, "5");
obj = new Integer(5);
print(obj, "new Integer(5)");
obj = 'z';
print(obj, "'z'");
obj = Arrays.asList(1, 2, 3);
print(obj, "Arrays.asList(1, 2, 3)");
obj = new LinkedList<>(Arrays.asList(1, 2, 3));
print(obj, "new LinkedList<>(Arrays.asList(1, 2, 3))");
obj = new HashSet<>(Arrays.asList("1", "2"));
print(obj, "new HashSet<>(Arrays.asList(\"1\", \"2\"))");
obj = new HashMap<String, Integer>();
print(obj, "new HashMap<String, Integer>()");
obj = new LinkedHashMap<>();
print(obj, "new LinkedHashMap<>()");
obj = new TreeMap<>();
print(obj, "new TreeMap<>()");
obj = new MyNestedObject();
print(obj, "MyNestedObject()");
obj = new TheController();
print(obj, "new TheController()");
//a collection cannot be empty (map is ok)
// following will throw IllegalArgumentException,
/* Set<Integer> integerTreeSet = new TreeSet<>();
name = Conventions.getVariableName(integerTreeSet);
print("Set<Integer> integerTreeSet = new TreeSet<>();", name);*/
}
private static void print (Object obj, String declaration) {
String name = Conventions.getVariableName(obj);
System.out.printf("%40s: %s%n", declaration, name);
}
private static class MyNestedObject {
}
}
Output
"test string": string
new String[]{"one", "two"};: stringList
5: integer
new Integer(5): integer
'z': character
Arrays.asList(1, 2, 3): integerList
new LinkedList<>(Arrays.asList(1, 2, 3)): integerList
new HashSet<>(Arrays.asList("1", "2")): stringList
new HashMap<String, Integer>(): hashMap
new LinkedHashMap<>(): linkedHashMap
new TreeMap<>(): treeMap
MyNestedObject(): myNestedObject
new TheController(): theController
Example Project
Dependencies and Technologies Used: - Spring Boot 1.4.3.RELEASE
Corresponding Spring Version 4.3.5.RELEASE - spring-boot-starter-web : Starter for building web, including RESTful, applications using Spring
MVC. Uses Tomcat as the default embedded container.
- tomcat-embed-jasper 8.5.6: Core Tomcat implementation.
- JDK 1.8
- Maven 3.3.9
|
|