CDI ViewScope和PrettyFaces:多次调用@PostConstruct(JSF 2.2) [英] CDI ViewScope & PrettyFaces: Multiple calls to @PostConstruct (JSF 2.2)
问题描述
我已经检查过类似的问题,这些问题声明JSF 2.1存在此错误,但我使用的是JSF 2.2,让我们详细介绍:
I'v already check similar questions which declare that JSF 2.1 had this bug, but I'm using JSF 2.2 Let's detail:
我的环境:
- CDI:1.1
- 动态Web模块: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
}
}
该控制器现在只是一个模拟,它返回一个元素列表.
That controller, right now is just a mock which returns a one-element list.
@Named
public class HomeController implements Serializable {
public List<Store> getStores() {
// mocked
}
}
我正在使用漂亮的脸蛋,pretty-config.xml
如下:
I'm using pretty faces, the pretty-config.xml
is the following:
<?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()}
In the home.xhtml
I'm going to omit irrelevant code but say that I call N times the homeBean
; for example #{home.buttonClicked()}
好;现在的问题.
其中每个对HomeBean
的引用都创建一个新的 HomeBean 实例;如果我在@PostConstruct
处使用断点调试它,则称为 N 次;因此,控制器被调用了N次,并且日志行"HomeBean:已初始化" 被打印了N次.
Each one of those references to the HomeBean
, creates a new HomeBean instance; If I debug it with a breakpoint at the @PostConstruct
it's called N times; so the controller is called N times and the log line "HomeBean: initialized" is printed N times.
这是一个@ViewScopped
,所以我认为它对于整个视图都是有效的,不是吗?
It's a @ViewScopped
, so I assume it will be alive for the entire view isn't it?
比方说,最终它可以正确呈现主页...但是控制器将成为数据库访问对象...我不希望每个图像都有新的数据库访问权限! O_O
Let's say, finally it renders the home page correctly... but the controller is going to be a DB access... I don't want a new DB access per image! O_O
它肯定与pretty-faces
有关,因为如果我删除它,它就可以很好地工作.我已经在web.xml
It's definitely related with pretty-faces
because if I remove it, it works perfectly fine. I've configured Pretty faces as the following in the 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):
And the Pom dependencies are (prettyfaces.version is 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>
那里发生了什么?非常感谢.
What's going on there? Thx very much.
推荐答案
问题是由以下映射引起的:
The problem is caused by this mapping:
<url-mapping id="cityIndex">
<pattern value="/#{provinceName}" />
<view-id value="/home.xhtml" />
</url-mapping>
此映射基本上匹配每个以/
开头的URL.因此,它不仅与/foobar
匹配,而且还与/style.css
和/scripts.js
和/jquery.min.js
等匹配.
This mapping is basically matching every URL beginning with a /
. So it doesn't just match /foobar
but also /style.css
and /scripts.js
and /jquery.min.js
and so on.
There are basically two ways to fix this. First you could try to use a custom regular expression to restrict what the path parameter is allowed to contain. You could for example use something like this:
<url-mapping id="cityIndex">
<pattern value="/#{ /[a-z]+/ provinceName }" />
<view-id value="/home.xhtml" />
</url-mapping>
这告诉PrettyFaces,省名只能包含字母,而不能包含数字,句点等.这与style.css
类似,将不再匹配.
This tells PrettyFaces that the province name must only contain letters, but no number, periods, etc. This was something like style.css
won't be matched any more.
第二个选择是使用某种URL前缀,如下所示:
The second option is to use some kind of URL prefix like this:
<url-mapping id="cityIndex">
<pattern value="/province/#{provinceName}" />
<view-id value="/home.xhtml" />
</url-mapping>
我通常建议这样做,因为这是最简单直接的方法. :)
That's what I usually recommend as it is the most simply and straight forward way. :)
这篇关于CDI ViewScope和PrettyFaces:多次调用@PostConstruct(JSF 2.2)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!