Java 在 JSP EL 中连接字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/296398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Concatenate strings in JSP EL?
提问by matt b
I have a List of beans, each of which has a property which itself is a List of email addresses.
我有一个 bean 列表,每个 bean 都有一个属性,它本身就是一个电子邮件地址列表。
<c:forEach items="${upcomingSchedule}" var="conf">
<div class='scheduled' title="${conf.subject}" id="scheduled<c:out value="${conf.id}"/>">
...
</div>
</c:forEach>
This renders one <div>
per bean in the List.
这<div>
为列表中的每个 bean呈现一个。
For the sublist, what I'd like to be able to do is to concatenate each of the entries in the list to form a single String, to be displayed as a part of the <div>
's title
attribute. Why? Because we are using a javascript library (mootools) to turn this <div>
into a floating tool tip, and the library turns the title
into the text of the tooltip.
对于子列表,我希望能够将列表中的每个条目连接起来形成一个字符串,作为<div>
'stitle
属性的一部分显示。为什么?因为我们使用了一个 javascript 库(mootools)将其<div>
转换为浮动工具提示,而该库将title
转换为工具提示的文本。
So, if ${conf.subject}
was "Subject", ultimately I'd like the title
of the <div>
to be "Subject: [email protected], [email protected], etc.", containing all of the email addresses of the sub-list.
所以,如果${conf.subject}
是“主题”,最后我想要title
的<div>
是“主题:[email protected],[email protected]等”,包含所有子列表的电子邮件地址。
How can I do this using JSP EL? I'm trying to stay away from putting scriptlet blocks in the jsp file.
如何使用 JSP EL 执行此操作?我试图避免将 scriptlet 块放在 jsp 文件中。
采纳答案by matt b
Figured out a somewhat dirty way to do this:
想出了一个有点肮脏的方法来做到这一点:
<c:forEach items="${upcomingSchedule}" var="conf">
<c:set var="title" value="${conf.subject}: "/>
<c:forEach items="${conf.invitees}" var="invitee">
<c:set var="title" value="${title} ${invitee}, "/>
</c:forEach>
<div class='scheduled' title="${title}" id="scheduled<c:out value="${conf.id}"/>">
...
</div>
</c:forEach>
I just use <c:set>
repeatedly, referencing it's own value, to append/concatenate the strings.
我只是<c:set>
重复使用,引用它自己的值,来附加/连接字符串。
回答by lucas
Could you use this? Seems like it wants an array instead of a list..
你能用这个吗?似乎它想要一个数组而不是一个列表..
${fn:join(array, ";")}
http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/fn/join.fn.html
http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/fn/join.fn.html
回答by alexmeia
If your sublist is an ArrayList and you do this:
如果您的子列表是一个 ArrayList 并且您这样做:
<div class='scheduled' title="${conf.subject}: ${conf.invitees}" id="scheduled${conf.id}">
you obtain almost what you need.
你几乎得到了你需要的东西。
The only difference is that the title will be: "Subject: [[email protected], [email protected], etc.]".
唯一的区别是标题将是:“主题:[[email protected]、[email protected] 等]”。
Maybe can be good enough for you.
也许对你来说已经足够好了。
回答by erickson
The "clean" way to do this would be to use a function. As the JSTL join
function won't work on a Collection
, you can write your own without too much trouble, and reuse it all over the place instead of cut-and-pasting a large chunk of loop code.
做到这一点的“干净”方法是使用函数。由于 JSTLjoin
函数不适用于Collection
,您可以轻松编写自己的函数,并在所有地方重用它,而不是剪切和粘贴一大块循环代码。
You need the function implementation, and a TLD to let your web application know where to find it. Put these together in a JAR and drop it into your WEB-INF/lib directory.
您需要函数实现和 TLD,让您的 Web 应用程序知道在哪里可以找到它。将它们放在一个 JAR 中,然后将其放入您的 WEB-INF/lib 目录中。
Here's an outline:
这是一个大纲:
com/x/taglib/core/StringUtil.java
com/x/taglib/core/StringUtil.java
package com.x.taglib.core;
public class StringUtil {
public static String join(Iterable<?> elements, CharSequence separator) {
StringBuilder buf = new StringBuilder();
if (elements != null) {
if (separator == null)
separator = " ";
for (Object o : elements) {
if (buf.length() > 0)
buf.append(separator);
buf.append(o);
}
}
return buf.toString();
}
}
META-INF/x-c.tld:
META-INF/xc.tld:
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>x-c</short-name>
<uri>http://dev.x.com/taglib/core/1.0</uri>
<function>
<description>Join elements of an Iterable into a string.</description>
<display-name>Join</display-name>
<name>join</name>
<function-class>com.x.taglib.core.StringUtil</function-class>
<function-signature>java.lang.String join(java.lang.Iterable, java.lang.CharSequence)</function-signature>
</function>
</taglib>
While the TLD is a little verbose, knowing your way around one is a good skill for any developer working with JSP. And, since you've chosen a standard like JSP for presentation, there's a good chance you have tools that will help you out.
虽然 TLD 有点冗长,但对于任何使用 JSP 的开发人员来说,了解自己的方法是一项很好的技能。而且,由于您选择了 JSP 之类的标准进行演示,因此您很有可能拥有可以帮助您解决问题的工具。
This approach has many advantages over the alternative of adding more methods to the underlying model. This function can be written once, and reused in any project. It works with a closed-source, third-party library. Different delimiters can be supported in different contexts, without polluting a model API with a new method for each.
与向底层模型添加更多方法的替代方法相比,这种方法具有许多优点。此函数可编写一次,并可在任何项目中重复使用。它与封闭源代码的第三方库一起使用。可以在不同的上下文中支持不同的分隔符,而不会使用新的方法来污染模型 API。
Most importantly, it supports a separation of view and model-controller development roles.Tasks in these two areas are often performed by different people at different times. Maintaining a loose coupling between these layers minimizes complexity and maintenance costs. When even a trivial change like using a different delimiter in the presentation requires a programmer to modify a library, you have a very expensive and cumbersome system.
最重要的是,它支持视图和模型控制器开发角色的分离。这两个领域的任务往往由不同的人在不同的时间执行。保持这些层之间的松散耦合可以最大限度地降低复杂性和维护成本。当即使是像在演示文稿中使用不同的分隔符这样的微不足道的更改也需要程序员修改库时,您将拥有一个非常昂贵且笨重的系统。
The StringUtil
class is the same whether its exposed as a EL function or not. The only "extra" necessary is the TLD, which is trivial; a tool could easily generate it.
StringUtil
无论是否公开为 EL 函数,该类都是相同的。唯一需要的“额外”是 TLD,这是微不足道的;一个工具可以很容易地生成它。
回答by Spanky Quigman
I think this is what you want:
我认为这就是你想要的:
<c:forEach var="tab" items="${tabs}">
<c:set var="tabAttrs" value='${tabAttrs} ${tab.key}="${tab.value}"'/>
</c:forEach>
In this case, I had a hashmap with tab ID (key) and URL (value). The tabAttrs variable isn't set prior to this. So it just sets the value to the current value of tabAttrs ('' to start) plus the key/value expression.
在这种情况下,我有一个带有选项卡 ID(键)和 URL(值)的哈希图。在此之前未设置 tabAttrs 变量。所以它只是将值设置为 tabAttrs ('' to start) 的当前值加上键/值表达式。
回答by Sandro
Just put the string byside the var from server, like this:
只需将字符串放在服务器的 var 旁边,如下所示:
<c:forEach items="${upcomingSchedule}" var="conf">
<div class='scheduled' title="${conf.subject}"
id="scheduled${conf.id}">
...
</div>
</c:forEach>
Too late!!!
为时已晚!!!
回答by Tim B
The way tag libraries are implemented seems to have moved on considerably since this answer was originally posted so I ended up making some drastic changes to get things working. My final result was:
标签库的实现方式似乎有了很大的变化,因为这个答案最初是发布的,所以我最终做了一些剧烈的改变来让事情正常工作。我的最终结果是:
Tag Library File:
标签库文件:
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
<tlib-version>1.0</tlib-version>
<short-name>string_util</short-name>
<uri>/WEB-INF/tlds/string_util</uri>
<info>String Utilities</info>
<tag>
<name>join</name>
<info>Join the contents of any iterable using a separator</info>
<tag-class>XXX.taglib.JoinObjects</tag-class>
<body-content>tagdependent</body-content>
<attribute>
<name>iterable</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.Iterable</type>
</attribute>
<attribute>
<name>separator</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.String</type>
</attribute>
</tag>
<tag>
<name>joinints</name>
<info>Join the contents of an integer array using a separator</info>
<tag-class>XXX.taglib.JoinInts</tag-class>
<body-content>tagdependent</body-content>
<attribute>
<name>integers</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.Integer[]</type>
</attribute>
<attribute>
<name>separator</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.String</type>
</attribute>
</tag>
</taglib>
JoinInts.java
JoinInts.java
public class JoinInts extends TagSupport {
int[] integers;
String separator = ",";
@Override
public int doStartTag() throws JspException {
if (integers != null) {
StringBuilder buf = new StringBuilder();
if (separator == null) {
separator = " ";
}
for (int i: integers) {
if (buf.length() > 0) {
buf.append(separator);
}
buf.append(i);
}
try {
pageContext.getOut().print(buf);
} catch (IOException ex) {
Logger.getLogger(JoinInts.class.getName()).log(Level.SEVERE, null, ex);
}
}
return SKIP_BODY;
}
@Override
public int doEndTag() throws JspException {
return EVAL_PAGE;
}
public int[] getIntegers() {
return integers;
}
public void setIntegers(int[] integers) {
this.integers = integers;
}
public String getSeparator() {
return separator;
}
public void setSeparator(String separator) {
this.separator = separator;
}
}
To use it:
要使用它:
<%@ taglib prefix="su" uri="/WEB-INF/tlds/string_util.tld" %>
[new Date(${row.key}), <su:joinints integers="${row.value}" separator="," />],
回答by George Siggouroglou
You can use the EL 3.0 Stream API. For example if you have a list of strings,
您可以使用 EL 3.0 Stream API。例如,如果您有一个字符串列表,
<div>${stringList.stream().reduce(",", (n,p)->p.concat(n))}</div>
In case you have a list of objects for ex. Person(firstName, lastName) and you wish to concat only one property of them (ex firstName) you can use map,
如果您有 ex 的对象列表。Person(firstName, lastName) 并且您希望仅连接其中的一个属性(例如 firstName),您可以使用 map,
<div>${personList.stream().map(p->p.getFirstName()).reduce(",", (n,p)->p.concat(n))}</div>
In your case you could use something like that (remove the last ',' also),
在您的情况下,您可以使用类似的东西(也删除最后一个 ','),
<c:forEach items="${upcomingSchedule}" var="conf">
<c:set var="separator" value=","/>
<c:set var="titleFront" value="${conf.subject}: "/>
<c:set var="titleEnd" value="${conf.invitees.stream().reduce(separator, (n,p)->p.concat(n))}"/>
<div class='scheduled' title="${titleFront} ${titleEnd.isEmpty() ? "" : titleEnd.substring(0, titleEnd.length()-1)}" id="scheduled<c:out value="${conf.id}"/>">
...
</div>
</c:forEach>
Be careful!The EL 3.0 Stream APIwas finalized before the Java 8 StreamAPI and it is different than that. They can't sunc both apis because it will break the backward compatibility.
当心!该EL 3.0流API是在之前敲定的Java 8个流API,它比不同。他们不能同时使用两个 api,因为它会破坏向后兼容性。