我是 JSF 的新手,还在学习。我尝试为下面描述的特定问题寻找解决方案,但我找不到任何东西。如果是因为我在寻找错误的东西,请指出我正确的方向,但希望这是尚未回答的问题,答案可以使每个人受益。
以下示例说明了我遇到的问题。该示例被简化以关注问题并隐藏发生问题的实际项目的复杂性。
考虑以下页面/类:
- /resources/test/custom.xhtml;
- /test/CharsetProvider.java;
- /test/CharsetHello.java;
- /testWith.xhtml;
- /testWithout.xhtml;
/resources/test/custom.xhtml
这是具有一个属性和默认值的复合组件。该组件只需获取属性值并将其作为参数传递给下面描述的 CDI bean 以获得用于输出的模型对象。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html">
<cc:interface>
<cc:attribute name="charset"
default="#{charsetProvider.defaultCharset}"
type="java.nio.charset.Charset" />
</cc:interface>
<cc:implementation>
<h:outputText value="#{charsetProvider.createCharsetHello(cc.attrs.charset).hello}"/>
</cc:implementation>
</html>
测试/CharsetProvider.java
这是一个 CDI bean,它只包含一个在整个应用程序中使用的默认值,并具有一个创建用作组件模型的对象的方法。我使用 CDI bean 而不是支持 bean 的原因是因为在我的特定项目中,默认值需要在运行时注入,但支持 bean 不是注入的候选者。
package test;
import java.nio.charset.Charset;
import javax.annotation.PostConstruct;
import javax.faces.bean.SessionScoped;
import javax.inject.Named;
@Named
@SessionScoped
public class CharsetProvider {
private Charset defaultCharset;
@PostConstruct
protected void postConstruct() {
this.defaultCharset = Charset.forName("UTF-8");
}
public Charset getDefaultCharset() {
return defaultCharset;
}
public Charset getCharsetForName(String name) {
return Charset.forName(name);
}
public CharsetHello createCharsetHello(Charset cs) {
return new CharsetHello(cs);
}
}
测试/CharsetHello.java
这是“模型”对象。它只是转换“Hello world!” 到一个字节数组并使用给定的字符集返回。
package test;
import java.nio.charset.Charset;
public class CharsetHello {
private static final String HW = "Hello World!";
private final byte[] data;
private final Charset cs;
public CharsetHello(Charset cs) {
this.cs = cs;
this.data = CharsetHello.HW.getBytes(this.cs);
}
public String getHello() {
return new String(this.data, this.cs);
}
}
testWith.xhtml
这是一个测试页面,它通过指定组件属性的值来使用上面定义的复合组件。页面正确呈现,即“Hello World!” 打印在屏幕上。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:test="http://java.sun.com/jsf/composite/test">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<test:custom charset="#{charsetProvider.getCharsetForName('UTF-16')}" />
</h:body>
</html>
testWithout.xhtml
这是一个测试页面,没有将自定义值传递给组件的属性,打算使用默认值。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:test="http://java.sun.com/jsf/composite/test">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<test:custom />
</h:body>
</html>
上面的页面会导致一个带有以下消息的 JSF 错误页面:
/resources/test/custom.xhtml @14,94 value="#{charsetProvider.createCharsetHello(cc.attrs.charset).hello}": Cannot convert UTF-8 of type class java.lang.String to class java.nio.charset.Charset
似乎在最后一种情况下,默认值在传递给方法之前被转换为 java.lang.String 。
首先,这是预期的行为吗?为什么?
如果这是预期的行为,您能否建议不同的实现?
先感谢您!