<%@ taglib uri="
http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri=" http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
< %@page contentType="text/html;charset=gb2312"%>
< %@page import="java.util.*"%>
<%!
private static class User{
private int id;
private String name;
private String hello;
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public void setHello(String hello){
this.hello = hello;
}
public String getHello(){
return "hello";
}
@Override
public String toString() {return "User [id=" + id + ", name=" + name + "]";}
public User(int id, String name) {this.id = id;this.name = name;}
public User() {}
}
%>
<%@ taglib uri=" http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
< %@page contentType="text/html;charset=gb2312"%>
< %@page import="java.util.*"%>
<%!
private static class User{
private int id;
private String name;
private String hello;
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public void setHello(String hello){
this.hello = hello;
}
public String getHello(){
return "hello";
}
@Override
public String toString() {return "User [id=" + id + ", name=" + name + "]";}
public User(int id, String name) {this.id = id;this.name = name;}
public User() {}
}
%>
<%
Map<Long,User> userMap = new HashMap<Long,User>();
userMap.put(1L,new User(1,"xujsh"));
userMap.put(2L,new User(2,"dm"));
pageContext.setAttribute("userMap",userMap);
pageContext.setAttribute("key",1L);//这种赋值方式能明确的知道key的类型
%>
<c:forEach items="${userMap}" var="entry">
<c:out value="${entry.key}" />
<c:out value="${entry.value}" />
</c:forEach><br/>
user:<c:out value="${userMap[key]}" /><br/>
现在稍微做一下改动:<br/>
<%
Map<Long,User> userMap2 = new HashMap<Long,User>();
userMap2.put(1L,new User(1,"xujsh"));
userMap2.put(2L,new User(2,"dm"));
pageContext.setAttribute("userMap2",userMap2);
//pageContext.setAttribute("key",1L);//不是用这种方式设置值
%>
<c:forEach items="${userMap2}" var="entry">
<c:out value="${entry.key}" />
<c:out value="${entry.value}" />
</c:forEach><br/>
<c:set var="key" value="1" /><!--用这种方式设置,这个值无论是“1L”还是“1”,都取不出值来,貌似是当成字符串了!-->
<!--
查看jsp对应的servlet,我们可以看出来,确实是当成字符串了!
_jspx_th_c_005fset_005f0.setVar("key");
_jspx_th_c_005fset_005f0.setValue(new String("1"));
-->
user:<c:out value="${userMap2[key]}" /><br/>
user:<c:out value="${userMap2[1]}" /><br/> <!--直接使用数字1是可以取出来的-->
<pre>
对于这个问题,参考:
http://stackoverflow.com/questions/924451/jstl-access-a-map-value-by-key
Basically autoboxing puts an Integer object into the Map. ie:
map.put(new Integer(0), "myValue")
也就是说,如果map的key是数字类型,自动装箱会把数字转化成Integer。
EL (Expressions Languages) evaluates 0 as a Long and thus goes looking for a Long as the key in the map. ie it evaluates:
map.get(new Long(0))
当从map里面取的时候,它会把数字key的类型当做是Long。
【结论】我们在往map里面放数据的时候,需要明确的指定key是Long类型,才能正确取出数据来。
Just another helpful hint in addition to the above comment would be when you have a string value contained in some variable such as a request parameter.
In this case, passing this in will also result in JSTL keying the value of say "1" as a sting and as such no match being found in a Map hashmap.
One way to get around this is to do something like this.
<c:set var="longKey" value="${param.selectedIndex + 0}"/><!--如此丑陋的解决方式!-->
This will now be treated as a Long object and then has a chance to match an object when it is contained withing the map Map or whatever.
Then, continue as usual with something like:${map[longKey]}
Map<Long,User> userMap = new HashMap<Long,User>();
userMap.put(1L,new User(1,"xujsh"));
userMap.put(2L,new User(2,"dm"));
pageContext.setAttribute("userMap",userMap);
pageContext.setAttribute("key",1L);//这种赋值方式能明确的知道key的类型
%>
<c:forEach items="${userMap}" var="entry">
<c:out value="${entry.key}" />
<c:out value="${entry.value}" />
</c:forEach><br/>
user:<c:out value="${userMap[key]}" /><br/>
现在稍微做一下改动:<br/>
<%
Map<Long,User> userMap2 = new HashMap<Long,User>();
userMap2.put(1L,new User(1,"xujsh"));
userMap2.put(2L,new User(2,"dm"));
pageContext.setAttribute("userMap2",userMap2);
//pageContext.setAttribute("key",1L);//不是用这种方式设置值
%>
<c:forEach items="${userMap2}" var="entry">
<c:out value="${entry.key}" />
<c:out value="${entry.value}" />
</c:forEach><br/>
<c:set var="key" value="1" /><!--用这种方式设置,这个值无论是“1L”还是“1”,都取不出值来,貌似是当成字符串了!-->
<!--
查看jsp对应的servlet,我们可以看出来,确实是当成字符串了!
_jspx_th_c_005fset_005f0.setVar("key");
_jspx_th_c_005fset_005f0.setValue(new String("1"));
-->
user:<c:out value="${userMap2[key]}" /><br/>
user:<c:out value="${userMap2[1]}" /><br/> <!--直接使用数字1是可以取出来的-->
<pre>
对于这个问题,参考:
http://stackoverflow.com/questions/924451/jstl-access-a-map-value-by-key
Basically autoboxing puts an Integer object into the Map. ie:
map.put(new Integer(0), "myValue")
也就是说,如果map的key是数字类型,自动装箱会把数字转化成Integer。
EL (Expressions Languages) evaluates 0 as a Long and thus goes looking for a Long as the key in the map. ie it evaluates:
map.get(new Long(0))
当从map里面取的时候,它会把数字key的类型当做是Long。
【结论】我们在往map里面放数据的时候,需要明确的指定key是Long类型,才能正确取出数据来。
Just another helpful hint in addition to the above comment would be when you have a string value contained in some variable such as a request parameter.
In this case, passing this in will also result in JSTL keying the value of say "1" as a sting and as such no match being found in a Map hashmap.
One way to get around this is to do something like this.
<c:set var="longKey" value="${param.selectedIndex + 0}"/><!--如此丑陋的解决方式!-->
This will now be treated as a Long object and then has a chance to match an object when it is contained withing the map Map or whatever.
Then, continue as usual with something like:${map[longKey]}
同样,对于我们的问题:很显然,<c:set var="key" value="1" />是把1当成了字符串,因此<c:out value="${userMap2[key]}" />就取不到数据了!我们要做的就是强制把key的类型转化成数字类型:<c:out value="${userMap2[key+0]}" />。
虽然很ugly,终归算是解决问题了!
</pre>
--------------速查备忘----------------<br/>
---------------String---------------<br/>
<%
pageContext.setAttribute("op","add");
%>
<c:if test="${op == 'add'}">
op = "add"
</c:if>
<c:if test="${op != 'add'}">
op != "add"
</c:if> <br/>
<%
pageContext.setAttribute("email","");
%>
<c:if test="${empty email}">
email = empty
</c:if>
<c:if test="${!empty email}">
email != empty
</c:if><br/>
-------------null---------------<br/>
<%
pageContext.setAttribute("host",null);
%>
<c:if test="${host == null}">
host == null
</c:if>
<c:if test="${host != null }">
host != null
</c:if> <br/>
<c:if test="${empty host}">
host = empty
</c:if>
<c:if test="${! empty host}">
host != empty
</c:if> <br/>
【注意】null可以用empty,也可以用null来判断<br/>
-------------boolean---------------<br/>
<%
pageContext.setAttribute("verified",true);
%>
<c:if test="${verified}">
verified == true
</c:if>
<c:if test="${! verified }">
verified == false
</c:if> <br/>
<c:set var="hasError" value="true" />
<c:if test="${hasError}">
hasError = true
</c:if>
<c:if test="${!hasError}">
hasError = fasle
</c:if><br/>
-------------int---------------<br/>
<%
pageContext.setAttribute("type",Integer.valueOf(1));
%>
<c:if test="${type == 1}">
type == 1
</c:if>
<c:if test="${type != 1 }">
type != 1
</c:if> <br/>
<c:if test="${type > 0 and type < 2}">
type > 0 and type < 2
</c:if><br/>
-------------if/else---------------<br/>
<%
pageContext.setAttribute("user",null);
%>
<c:choose>
<c:when test="${empty user or user.id == 1}">
empty user or user.id == 1
</c:when>
<c:otherwise>
not empty user and user.id != 1
</c:otherwise>
</c:choose><br/>
-------------list----------------<br/>
<%
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("yes");
pageContext.setAttribute("list",list);
%>
<c:if test="${fn:length(list) > 0}"><!--为什么不能直接用size来访问?悲哀!-->
list.size > 0
</c:if>
<c:if test="${fn:length(list) <= 0}">
list.size <= 0
</c:if>
<br/>
<c:forEach var="out_item" items="${list}" varStatus="out_status" step="2" begin="0">
${out_item}
<c:forEach var="in_item" items="${list}" varStatus="in_status" begin="${out_status.index+1}" end="${out_status.index+1}" >
${in_item}
</c:forEach>
<br/>
</c:forEach>
【注意】通过两个循环,每次输出多个元素<br/>
虽然很ugly,终归算是解决问题了!
</pre>
--------------速查备忘----------------<br/>
---------------String---------------<br/>
<%
pageContext.setAttribute("op","add");
%>
<c:if test="${op == 'add'}">
op = "add"
</c:if>
<c:if test="${op != 'add'}">
op != "add"
</c:if> <br/>
<%
pageContext.setAttribute("email","");
%>
<c:if test="${empty email}">
email = empty
</c:if>
<c:if test="${!empty email}">
email != empty
</c:if><br/>
-------------null---------------<br/>
<%
pageContext.setAttribute("host",null);
%>
<c:if test="${host == null}">
host == null
</c:if>
<c:if test="${host != null }">
host != null
</c:if> <br/>
<c:if test="${empty host}">
host = empty
</c:if>
<c:if test="${! empty host}">
host != empty
</c:if> <br/>
【注意】null可以用empty,也可以用null来判断<br/>
-------------boolean---------------<br/>
<%
pageContext.setAttribute("verified",true);
%>
<c:if test="${verified}">
verified == true
</c:if>
<c:if test="${! verified }">
verified == false
</c:if> <br/>
<c:set var="hasError" value="true" />
<c:if test="${hasError}">
hasError = true
</c:if>
<c:if test="${!hasError}">
hasError = fasle
</c:if><br/>
-------------int---------------<br/>
<%
pageContext.setAttribute("type",Integer.valueOf(1));
%>
<c:if test="${type == 1}">
type == 1
</c:if>
<c:if test="${type != 1 }">
type != 1
</c:if> <br/>
<c:if test="${type > 0 and type < 2}">
type > 0 and type < 2
</c:if><br/>
-------------if/else---------------<br/>
<%
pageContext.setAttribute("user",null);
%>
<c:choose>
<c:when test="${empty user or user.id == 1}">
empty user or user.id == 1
</c:when>
<c:otherwise>
not empty user and user.id != 1
</c:otherwise>
</c:choose><br/>
-------------list----------------<br/>
<%
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("yes");
pageContext.setAttribute("list",list);
%>
<c:if test="${fn:length(list) > 0}"><!--为什么不能直接用size来访问?悲哀!-->
list.size > 0
</c:if>
<c:if test="${fn:length(list) <= 0}">
list.size <= 0
</c:if>
<br/>
<c:forEach var="out_item" items="${list}" varStatus="out_status" step="2" begin="0">
${out_item}
<c:forEach var="in_item" items="${list}" varStatus="in_status" begin="${out_status.index+1}" end="${out_status.index+1}" >
${in_item}
</c:forEach>
<br/>
</c:forEach>
【注意】通过两个循环,每次输出多个元素<br/>
really ugly!