问题
Is there any proper way to override the way JSF accesses the beans fields from an Expression Language? The idea is to mimic this behavior in order to access a Map<String, ?>
values, where the bean fields would be the map keys.
In other words, is it possible anyhow to use #{beanContainingNestedMap.keyOfSaidNestedMap}
, just as if keyOfSaidNestedMap
were a field of the beanContainingNestedMap
?
If not, what other solution may I have?
Example:
Holder.java
public class Holder {
private Map<String, Object> objects = new HashMap<String, Object>();
public void add(String key, Object value) {
objects.put(key, value);
}
public Object getObject(String key) {
return objects.get(key);
}
}
ExampleBean.java
public class ExampleBean {
private Holder holder = new Holder();
public ExampleBean() {
holder.add("foo", 42);
holder.add("bar", 'X');
}
public Holder getHolder() {
return holder;
}
}
example.xhtml
<c:out value="#{exampleBean.holder.foo}" /> <!-- should print "42" -->
<c:out value="#{exampleBean.holder.bar}" /> <!-- should print "X" -->
What would be great is if I could do something like (kind of pseudo-code since I don't know if such a method exists ;)
):
@Override // override JSF's (if any...)
public Object resolveEl(String el) {
try {
super.resolveEl(el);
} catch (ElException e) {
Object bean = e.getBean();
String fieldName = e.getFieldName();
if (bean instanceof Holder) {
Holder holder = (Holder) bean;
Object value = holder.getObject(fieldName);
if (value == null) {
throw e;
} else {
return value;
}
}
}
}
回答1:
You can directly use map by EL.
Holder.java
public class Holder {
private Map<String, Object> objects = new HashMap<String, Object>();
public void add(String key, Object value) {
objects.put(key, value);
}
public Map<String, Object> getObjectsMap() {
return objects;
}
}
EL
#{exampleBean.holder.objectsMap[your-key]}
回答2:
This problem is not about JSF but EL. As noted in @BalusC comment, you can directly use the notation you already want/need with Map
objects. I've prepared a basic example on this (note: this is just an example and should remain as is or improved since it uses scriptlets and we must avoid scriptlets usage but made it for a quick dirty test):
<%@page import="edu.home.model.entity.User"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%
//Scriptlets usage, sorry. This code must be moved to a Servlet or another controller component
//defining the map
Map<String, User> aMap = new HashMap<String, User>();
//defining a value for the map
User user = new User();
user.setFirstName("Luiggi");
user.setLastName("Mendoza");
//adding the value in the map
aMap.put("userLM", user);
//making the map accesible in EL through PageContext attribute
pageContext.setAttribute("aMap", aMap);
%>
<!-- Accessing directly to the userLM key and its attributes -->
${aMap.userLM.firstName} - ${aMap.userLM.lastName}
</body>
</html>
User class code (minimized for test purposes):
public class User {
private String firstName;
private String lastName;
//empty constructor
//getters and setters
}
This generates a JSP page that prints:
Luiggi - Mendoza
Note that this (except the scriptlet part) will work on a Facelets page as well since this is EL and not JSF.
来源:https://stackoverflow.com/questions/17884028/make-jsf-access-a-mapstring-values-from-an-el-instead-of-a-bean-fields