背景前提
以下参考JSF源码类NavigationHandlerImpl
调用NavigationHandlerImplhandleNavigation方法获取跳转视图路径
outcome = ((MethodInvocation)node.getExpression()).arguments().get(2).toString().replace("\"", "");
CaseStruct caseStruct = NavigationHandlerImpl.handleNavigation(node, packageName, className, outcome);
if (caseStruct != null) {
assert (null != caseStruct);
viewId = caseStruct.viewId;
}
1.NavigationHandlerImpl
1.1初始化
private static Map<String, List<ConfigNavigationCase>> caseListMap = CommonConst.CASE_LIST_MAP;
private static Set<String> wildCardSet = CommonConst.WILD_CARD_SET;
private static boolean navigationConfigured = (wildCardSet != null && caseListMap != null);
1.2获取跳转下一个画面视图路径,Method「handleNavigation」
public static CaseStruct handleNavigation(ASTNode node, String packageName, String className, String outcome) {
MethodDeclaration md = CommonUtils.findMethodDeclaration(node);
String viewId = "";
String[] split = packageName.split("\\.");
if(split.length == 0) {
viewId = "/" + className.replace(".java", "");
}else {
viewId = packageName.substring(packageName.indexOf(".")).replace(".", "/");
viewId = viewId + "/" + className.replace(".java", "");
}
String fromAction = md.getName().getFullyQualifiedName();
CaseStruct caseStruct = null;
if (viewId != null) {
caseStruct = NavigationHandlerImpl.findExactMatch(viewId, fromAction, outcome);
if (caseStruct == null) {
caseStruct = findWildCardMatch(viewId, fromAction, outcome);
}
}
if (caseStruct == null) {
caseStruct = NavigationHandlerImpl.findDefaultMatch(fromAction, outcome);
}
return caseStruct;
}
1.3在caseListMap查询根节点viewId,Method「findExactMatch」
private CaseStruct findExactMatch(String viewId,
String fromAction,
String outcome) {
if (!navigationConfigured) {
return null;
}
List<ConfigNavigationCase> caseList = caseListMap.get(viewId);
if (caseList == null) {
return null;
}
return determineViewFromActionOutcome(caseList, fromAction, outcome);
}
1.4在wildCardSet中查询fromViewId标签值以「*」结尾,Method「findWildCardMatch」
private CaseStruct findWildCardMatch(String viewId,
String fromAction,
String outcome) {
CaseStruct result = null;
if (!navigationConfigured) {
return null;
}
for (String fromViewId : wildCardSet) {
if (!viewId.startsWith(fromViewId)) {
continue;
}
String wcFromViewId = new StringBuilder(32).append(fromViewId).append('*').toString();
List<ConfigNavigationCase> caseList = caseListMap.get(wcFromViewId);
if (caseList == null) {
return null;
}
result = determineViewFromActionOutcome(caseList, fromAction, outcome);
if (result != null) {
break;
}
}
return result;
}
1.5在caseListMap查询key为「*」,Method「findDefaultMatch」
private CaseStruct findDefaultMatch(String fromAction,
String outcome) {
if (!navigationConfigured) {
return null;
}
List<ConfigNavigationCase> caseList = caseListMap.get("*");
if (caseList == null) {
return null;
}
return determineViewFromActionOutcome(caseList, fromAction, outcome);
}
1.6匹配fromAction和outcome,并返回faces-config.xml结果
private CaseStruct determineViewFromActionOutcome(List<ConfigNavigationCase> caseList,
String fromAction,
String outcome) {
CaseStruct result = new CaseStruct();
for (ConfigNavigationCase cnc : caseList) {
String cncFromAction = cnc.getFromAction();
String fromOutcome = cnc.getFromOutcome();
String toViewId = cnc.getToViewId();
if ((cncFromAction != null) && (fromOutcome != null)) {
if ((cncFromAction.equals(fromAction)) &&
(fromOutcome.equals(outcome))) {
result.viewId = toViewId;
result.navCase = cnc;
return result;
}
}
if ((cncFromAction == null) && (fromOutcome != null)) {
if (fromOutcome.equals(outcome)) {
result.viewId = toViewId;
result.navCase = cnc;
return result;
}
}
if ((cncFromAction != null) && (fromOutcome == null)) {
if (cncFromAction.equals(fromAction)) {
result.viewId = toViewId;
result.navCase = cnc;
return result;
}
}
if ((cncFromAction == null) && (fromOutcome == null)) {
result.viewId = toViewId;
result.navCase = cnc;
return result;
}
}
return null;
}
2.ConfigNavigationCase类 存放fromViewId和navigation-case标签中子标签值
public class ConfigNavigationCase {
private String fromViewId = null;
private String fromAction = null;
private String fromOutcome = null;
private String toViewId = null;
private String key = null;
private boolean redirect;
public ConfigNavigationCase(String fromViewId,
String fromAction,
String fromOutcome,
String toViewId,
boolean redirect) {
this.fromViewId = fromViewId;
this.fromAction = fromAction;
this.fromOutcome = fromOutcome;
this.toViewId = toViewId;
this.key = fromViewId
+ ((fromAction == null) ? "-" : fromAction)
+ ((fromOutcome == null) ? "-" : fromOutcome);
this.redirect = redirect;
}
public String getFromViewId() {
return (this.fromViewId);
}
public void setFromViewId(String fromViewId) {
this.fromViewId = fromViewId;
}
public String getFromAction() {
return (this.fromAction);
}
public void setFromAction(String fromAction) {
this.fromAction = fromAction;
}
public String getFromOutcome() {
return (this.fromOutcome);
}
public void setFromOutcome(String fromOutcome) {
this.fromOutcome = fromOutcome;
}
public String getToViewId() {
return (this.toViewId);
}
public void setToViewId(String toViewId) {
this.toViewId = toViewId;
}
public boolean hasRedirect() {
return redirect;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String toString() {
StringBuilder sb = new StringBuilder(64);
sb.append("from-view-id=").append(getFromViewId());
sb.append(" from-action=").append(getFromAction());
sb.append(" from-outcome=").append(getFromOutcome());
sb.append(" to-view-id=").append(getToViewId());
sb.append(" redirect=").append(hasRedirect());
return sb.toString();
}
}
3.CaseStruct类 存储跳转画面key和action接口与faces-config.xml进行匹配后,存放对象
public class CaseStruct {
public String viewId;
public ConfigNavigationCase navCase;
}