Można to zrobić ze zwyczajem ViewDeclarationLanguage
czym zmierzyć createView()
, buildView()
, renderView()
a jeśli niezbędne restoreView()
metod.
Oto przykład kickoff:
public class VdlLogger extends ViewDeclarationLanguageWrapper {
private static final Logger logger = Logger.getLogger(VdlLoggerFactory.class.getName());
private ViewDeclarationLanguage wrapped;
public VdlLogger(ViewDeclarationLanguage wrapped) {
this.wrapped = wrapped;
}
@Override
public UIViewRoot createView(FacesContext context, String viewId) {
long start = System.nanoTime();
UIViewRoot view = super.createView(context, viewId);
long end = System.nanoTime();
logger.info(String.format("create %s: %.6fms", viewId, (end - start)/1e6));
return view;
}
@Override
public void buildView(FacesContext context, UIViewRoot view) throws IOException {
long start = System.nanoTime();
super.buildView(context, view);
long end = System.nanoTime();
logger.info(String.format("build %s: %.6fms", view.getViewId(), (end - start)/1e6));
}
@Override
public void renderView(FacesContext context, UIViewRoot view) throws IOException {
long start = System.nanoTime();
super.renderView(context, view);
long end = System.nanoTime();
logger.info(String.format("render %s: %.6fms", view.getViewId(), (end - start)/1e6));
}
@Override
public ViewDeclarationLanguage getWrapped() {
return wrapped;
}
}
Aby go uruchomić, należy utworzyć poniższego fabryczne:
public class VdlLoggerFactory extends ViewDeclarationLanguageFactory {
private ViewDeclarationLanguageFactory wrapped;
public VdlLoggerFactory(ViewDeclarationLanguageFactory wrapped) {
this.wrapped = wrapped;
}
@Override
public ViewDeclarationLanguage getViewDeclarationLanguage(String viewId) {
return new VdlLogger(wrapped.getViewDeclarationLanguage(viewId));
}
@Override
public ViewDeclarationLanguageFactory getWrapped() {
return wrapped;
}
}
i zarejestrować go jako poniżej faces-config.xml
:
<factory>
<view-declaration-language-factory>com.example.VdlLoggerFactory</view-declaration-language-factory>
</factory>
createView()
to krok tworzenia konkretnego egzemplarza instancji UIViewRoot
sed na <f:view>
i <f:metadata>
obecnych w plikach widoku. Podczas używania Facelets (XHTML) jako widoku, podczas tego kroku wszystkie skojarzone pliki XHTML będą analizowane przez analizator składni SAX i buforowane przez czas określony w javax.faces.FACELETS_REFRESH_PERIOD
. Może się więc zdarzyć, że jest to jeden czas stosunkowo powolny, a drugi czas szybko się rozpala.
Numer buildView()
jest etapem wypełniania drzewa komponentów JSF (getChildren()
z UIViewRoot
) na podstawie kompozycji widoku (XHTML). Podczas tego kroku wykonywane są wszystkie znaczniki (JSTL i przyjaciele) i wszystkie wyrażenia EL w tych znacznikach i atrybutach składnika id
i binding
są oceniane (szczegóły, patrz także JSTL in JSF2 Facelets... makes sense?). Jeśli więc fasola jest tworzona po raz pierwszy podczas budowania widoku i wywoływania logiki biznesowej podczas @PostConstruct
, może się zdarzyć, że jest to czasochłonne.
renderView()
jest etapem generowania wyjścia HTML na podstawie drzewa komponentów JSF i modelu, zaczynając od UIViewRoot#encodeAll()
. Jeśli więc fasola jest tworzona po raz pierwszy podczas renderowania czasu wyświetlania i wywoływania logiki biznesowej podczas @PostConstruct
, może się zdarzyć, że jest to czasochłonne.
Jeśli fasola jest nieprawidłowo wykonująca logikę biznesową w metodach getter zamiast w @PostConstruct
lub innym jednorazowym detektorze zdarzeń cyklu życia, może się zdarzyć, że zajmie to jeszcze więcej czasu. Zobacz także Why JSF calls getters multiple times.
To po prostu ... niesamowite. Dziękuję Ci! – user2271933
Nie ma za co. – BalusC
[ViewDeclarationLanguageWrapper] (http://docs.oracle.com/javaee/7/api/javax/faces/view/ViewDeclarationLanguageWrapper.html) został dodany w wersji 2.2. Czy uważasz, że byłoby łatwo zmodyfikować to, aby działało z wersją 2.1, czy lepiej byłoby, gdyby szukałem innego sposobu na jego implementację? –