CDI ViewScope 和 PrettyFaces:多次调用 @PostConstruct (JSF 2.2)
CDI ViewScope & PrettyFaces: Multiple calls to @PostConstruct (JSF 2.2)
我已经检查了声明 JSF 2.1 有此错误的类似问题,但我使用的是 JSF 2.2 让我们详细说明:
我的环境:
- CDI:1.1
- 动态网络模块:3.0
- Java: 1.7
- JSF: 2.2
- PrettyFaces:2.0.12.Final
我的豆子:
@Named(value = "home")
@javax.faces.view.ViewScoped
public class HomeBean implements Serializable {
@Inject
private HomeController controller;
private List<Store> myPopularStores;
@PostConstruct
public void postConstruct() {
myPopularStores = controller.getStores();
LOG.log(Level.FINE, "HomeBean: initialized");
}
public String buttonClicked() {
// whatever
}
}
那个控制器,现在只是一个模拟,returns 一个单元素列表。
@Named
public class HomeController implements Serializable {
public List<Store> getStores() {
// mocked
}
}
我用的是漂亮的脸蛋,pretty-config.xml
如下:
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces
http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd">
<url-mapping id="Home">
<pattern value="/" />
<view-id value="/home.xhtml" />
</url-mapping>
<url-mapping id="cityIndex">
<pattern value="/#{provinceName}" />
<view-id value="/home.xhtml" />
</url-mapping>
</pretty-config>
在 home.xhtml
中,我将省略不相关的代码,但我会调用 N 次 homeBean
;例如 #{home.buttonClicked()}
好的;现在的问题。
每个对 HomeBean
的引用都会创建一个新的 HomeBean 实例;如果我在 @PostConstruct
处用断点调试它,它会被调用 N 次;所以控制器被调用 N 次并且日志行 "HomeBean: initialized" 被打印 N 次。
它是 @ViewScopped
,所以我认为它会在整个视图中都处于活动状态,不是吗?
比方说,它最终正确地呈现了主页...但是控制器将成为数据库访问...我不希望每个图像都有新的数据库访问! O_O
[编辑]
它肯定与 pretty-faces
相关,因为如果我删除它,它就可以正常工作。我在 web.xml
中将 Pretty faces 配置如下
<filter>
<filter-name>OCPsoft Rewrite Filter</filter-name>
<filter-class>org.ocpsoft.rewrite.servlet.RewriteFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>OCPsoft Rewrite Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ASYNC</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
Pom 依赖项是(prettyfaces.version 是 2.0.12.Final):
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-servlet</artifactId>
<version>${prettyfaces.version}</version>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-integration-faces</artifactId>
<version>${prettyfaces.version}</version>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-config-prettyfaces</artifactId>
<version>${prettyfaces.version}</version>
</dependency>
那里发生了什么事?非常感谢。
问题是由这个映射引起的:
<url-mapping id="cityIndex">
<pattern value="/#{provinceName}" />
<view-id value="/home.xhtml" />
</url-mapping>
此映射基本上匹配以 /
开头的每个 URL。所以它不仅匹配 /foobar
,还匹配 /style.css
和 /scripts.js
和 /jquery.min.js
等等。
基本上有两种方法可以解决这个问题。首先,您可以尝试使用 custom regular expression 来限制允许包含的路径参数。例如,您可以使用这样的东西:
<url-mapping id="cityIndex">
<pattern value="/#{ /[a-z]+/ provinceName }" />
<view-id value="/home.xhtml" />
</url-mapping>
这告诉 PrettyFaces 省名只能包含字母,不能包含数字、句点等。这类似于 style.css
将不再匹配。
第二种选择是使用某种 URL 前缀,如下所示:
<url-mapping id="cityIndex">
<pattern value="/province/#{provinceName}" />
<view-id value="/home.xhtml" />
</url-mapping>
这是我通常推荐的方法,因为它是最简单直接的方法。 :)
我已经检查了声明 JSF 2.1 有此错误的类似问题,但我使用的是 JSF 2.2 让我们详细说明:
我的环境:
- CDI:1.1
- 动态网络模块:3.0
- Java: 1.7
- JSF: 2.2
- PrettyFaces:2.0.12.Final
我的豆子:
@Named(value = "home")
@javax.faces.view.ViewScoped
public class HomeBean implements Serializable {
@Inject
private HomeController controller;
private List<Store> myPopularStores;
@PostConstruct
public void postConstruct() {
myPopularStores = controller.getStores();
LOG.log(Level.FINE, "HomeBean: initialized");
}
public String buttonClicked() {
// whatever
}
}
那个控制器,现在只是一个模拟,returns 一个单元素列表。
@Named
public class HomeController implements Serializable {
public List<Store> getStores() {
// mocked
}
}
我用的是漂亮的脸蛋,pretty-config.xml
如下:
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces
http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd">
<url-mapping id="Home">
<pattern value="/" />
<view-id value="/home.xhtml" />
</url-mapping>
<url-mapping id="cityIndex">
<pattern value="/#{provinceName}" />
<view-id value="/home.xhtml" />
</url-mapping>
</pretty-config>
在 home.xhtml
中,我将省略不相关的代码,但我会调用 N 次 homeBean
;例如 #{home.buttonClicked()}
好的;现在的问题。
每个对 HomeBean
的引用都会创建一个新的 HomeBean 实例;如果我在 @PostConstruct
处用断点调试它,它会被调用 N 次;所以控制器被调用 N 次并且日志行 "HomeBean: initialized" 被打印 N 次。
它是 @ViewScopped
,所以我认为它会在整个视图中都处于活动状态,不是吗?
比方说,它最终正确地呈现了主页...但是控制器将成为数据库访问...我不希望每个图像都有新的数据库访问! O_O
[编辑]
它肯定与 pretty-faces
相关,因为如果我删除它,它就可以正常工作。我在 web.xml
<filter>
<filter-name>OCPsoft Rewrite Filter</filter-name>
<filter-class>org.ocpsoft.rewrite.servlet.RewriteFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>OCPsoft Rewrite Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ASYNC</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
Pom 依赖项是(prettyfaces.version 是 2.0.12.Final):
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-servlet</artifactId>
<version>${prettyfaces.version}</version>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-integration-faces</artifactId>
<version>${prettyfaces.version}</version>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-config-prettyfaces</artifactId>
<version>${prettyfaces.version}</version>
</dependency>
那里发生了什么事?非常感谢。
问题是由这个映射引起的:
<url-mapping id="cityIndex">
<pattern value="/#{provinceName}" />
<view-id value="/home.xhtml" />
</url-mapping>
此映射基本上匹配以 /
开头的每个 URL。所以它不仅匹配 /foobar
,还匹配 /style.css
和 /scripts.js
和 /jquery.min.js
等等。
基本上有两种方法可以解决这个问题。首先,您可以尝试使用 custom regular expression 来限制允许包含的路径参数。例如,您可以使用这样的东西:
<url-mapping id="cityIndex">
<pattern value="/#{ /[a-z]+/ provinceName }" />
<view-id value="/home.xhtml" />
</url-mapping>
这告诉 PrettyFaces 省名只能包含字母,不能包含数字、句点等。这类似于 style.css
将不再匹配。
第二种选择是使用某种 URL 前缀,如下所示:
<url-mapping id="cityIndex">
<pattern value="/province/#{provinceName}" />
<view-id value="/home.xhtml" />
</url-mapping>
这是我通常推荐的方法,因为它是最简单直接的方法。 :)