打造Tapestry5中的智能的错误页面。

我们一般需要为生产和开发环境准备两套error page。 tapestry在开发环境下的error page做得非常漂亮。 非常详细, 但是在生产环境下就不能暴露太多的信息。 而且error page的外观也需要定制。 这时候tapestry默认的error page就不行了。 所以我们期望的是在开发的时候我们需要tapestry自带的error page, 而在生产环境下我们需要定制自己的error page。

http://wiki.apache.org/tapestry/Tapestry5ExceptionPage
上面这篇文章告诉我们怎样替换掉tapestry自带的error page。 但是我们需要更灵活的方式。

OK, 下面开始写代码。 我们在AppModule class 添加以下代码段。

    // handle RedirectException
public static RequestExceptionHandler decorateRequestExceptionHandler(
final Object delegate, final Response response,
final RequestPageCache requestPageCache, final LinkFactory linkFactory,
final ComponentClassResolver resolver,
@Symbol(SymbolConstants.PRODUCTION_MODE) final
boolean productionMode, final PageResponseRenderer renderer
)
{
return new RequestExceptionHandler()
{
public void handleRequestException(Throwable exception) throws IOException
{
// check if wrapped
Throwable cause = exception;
if (exception.getCause() instanceof RedirectException)
{
cause = exception.getCause();
}

//Better way to check if the cause is RedirectException. Sometimes it's wrapped pretty deep..
int i = 0;
while(true){
if(cause == null || cause instanceof RedirectException || i > 1000){
break;
}
i++;
cause = cause.getCause();
}

// check for redirect
if (cause instanceof RedirectException)
{
// check for class and string
RedirectException redirect = (RedirectException)cause;
URL url = redirect.getUrl();
if (url != null) {
response.sendRedirect(url.toString());
return ;
}
Link pageLink = redirect.getPageLink();
if (pageLink == null)
{
// handle Class (see ClassResultProcessor)
String pageName = redirect.getMessage();
Class<?> pageClass = redirect.getPageClass();
if (pageClass != null)
{
pageName = resolver.resolvePageClassNameToPageName(pageClass.getName());
}

// handle String (see StringResultProcessor)
Page page = requestPageCache.get(pageName);
pageLink = linkFactory.createPageLink(page, false);
}

// handle Link redirect
if (pageLink != null)
{
response.sendRedirect(pageLink.toRedirectURI());
return;
}
}
if (productionMode) {
Page page = requestPageCache.get("ProductionExceptionReport");
ExceptionReporter rootComponent = (ExceptionReporter) page.getRootComponent();
rootComponent.reportException(exception);
renderer.renderPageResponse(page);
}else {
// no redirect so pass on the exception
((RequestExceptionHandler)delegate).handleRequestException(exception);
}
}
};
}


我们只要关注64至72行的代码。 64行以上的代码是实现Tapestry4中的RedirectException作用的。我们可以只看64至72行的代码就行了。 这段代码很简单。 如果是productionMode(我们运行时servlet container时加了-Dtapestry.production-mode 参数)的话, 我们去拿"ProductionExceptionReport"页面。 然后调用reportException方法。 最后转到ProductionExceptionReport页面。 如果不是production mode的话,我们使用tapestry默认的RequestExceptionHandler去处理这个异常。 这样tapestry就使用自带的异常页面了。

import java.util.List;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.services.ExceptionAnalysis;
import org.apache.tapestry5.ioc.services.ExceptionAnalyzer;
import org.apache.tapestry5.ioc.services.ExceptionInfo;
import org.apache.tapestry5.services.ExceptionReporter;

public class ProductionExceptionReport implements ExceptionReporter {

@Property(write=false)
private Throwable exception;

@Inject
private ExceptionAnalyzer analyzer;

@Property
private List<ExceptionInfo> stack;

public void reportException(Throwable exception) {
this.exception = exception;
ExceptionAnalysis analysis = analyzer.analyze(exception);
stack = analysis.getExceptionInfos();
sendExceptionByEmail();
}

private void sendExceptionByEmail() {
System.out.println(".......................Send Email ..............");
}

@Override
public Asset[] getCsses() {
return new Asset[] {getIndexCssAsset()};
}

}


ProductionExceptionReport页面实现了tapestry5的ExceptionReporter 接口。 这里要注意的是
ExceptionReporter rootComponent = (ExceptionReporter)page.getRootComponent();

你不能把它cast成ProductionExceptionReporter, 这是由tapestry5的classloader超成的。 tapestry5文档中有说明。 你可以在reportException方法中做些事情。 比如发邮件通知管理员。

下面是个简单的error page的模板页面。
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<t:layout home="false" errorPage="true" showAddNewSite="false" showSideBar="false" title="literal:Error" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<font color="red">有错误发生,请联系管理员。</font>
<br/>
<a t:type="pagelink" t:page="Index">重新开始</a>
</t:layout>


OK。大工告成!

在你开发的环境中启动参数中加上-Dtapestry.production-mode=false


参考:
http://wiki.apache.org/tapestry/Tapestry5ExceptionPage
http://tapestry.apache.org/tapestry5/cookbook/exceptions.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值