昨日的程式沒有跑出來最後發現是我自己超連結網址打錯,不是程式錯誤,上一篇已更新,今天來分享@ExceptionHandler的用途。
不管是開發的時候或是遇到使用者非預期的存取web應用程式未定義的功能或是找不到網頁等等HTTP Error的時候,常見的錯誤HTTP Status Error Code如500(Internal Server Error), 404(Not Found), 406(Media Type Not Acceptable),Tomcat的標準網頁都長得很醜,Spring MVC中@ExceptionHandler就是來協助開發者自行定義錯誤訊息網頁,@ExceptionHandler接受的參數為繼承xxxxException的class,例如@ExceptionHandler(IOException.class),今天要分享的是存取一個在資料庫不存在的紀錄,因為此操作在Web已經初始化完成了,故屬於Runtime Exception,因此首先先新增DCNNotFouncException.class於tw.blogger.springtech.springmvc.controller.exception下並繼承RuntimeException,接著需要在class level上宣告@ResponseStatus,這個annotation會向DispatcherServlet註冊ResponseStatusExceptionResolver,簡單說就是告訴DispatchSerlvet某些HTTP Exception的資訊由此class提供,@ResponseStatus參數value要指定這個class要處理哪一個HTTP Status Error Code, 參數Reason對應到錯誤訊息的字串,另外我們需要在這個class宣告產生Exception的相關參數,以及產生對應的getter方法,以便Controller裡可以存取exception有關的參數,其code如下
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR, reason="No DCN Records are found") //HTTP Status Error Code:500
public class DCNNotFoundException extends RuntimeException{
private static final long serialVersionUID = 197995355855327591L;
private String dcnNo;
private Integer rev;
public DCNNotFoundException(String dcnNo, Integer rev) {
this.dcnNo = dcnNo;
this.rev=rev;
}
public String getDcnNo() {
return dcnNo;
}
public Integer getRev() {
return rev;
}
}
先測試DCNNotFoundException是否catch到Runtime Exception,以及自行定義的錯誤訊息有沒有出現在錯誤網頁,故先更新DCNRepositoryImp code如下:
@Repository("DCNRepository")
@Transactional(propagation =Propagation.REQUIRED)
public class DCNRepositoryImp implements DCNRepository {
@PersistenceContext
private EntityManager entityManager;
.....
@Override
public DCN findByNoAndRev(String dcnNo, Integer rev) {
// TODO Auto-generated method stub
Query query=entityManager.createQuery("select d from DCN d where d.no =:no and d.rev =:rev");
query.setParameter("no", dcnNo);
query.setParameter("rev", rev);
DCN dcn=new DCN();
try{
dcn=(DCN)query.getSingleResult();
}catch(PersistenceException ex){
ex.printStackTrace();
throw new DCNNotFoundException(dcnNo, rev); //如果搜尋不到紀錄則丟出自行定義的Exception class
}
return dcn;
}
}
啟動Server,網址列打入一個不存在的紀錄,出現畫面如下:
message已有更新,再來我們要新增@ExceptionHandler於Controller中來指定此類錯誤網頁,其Code如下:
@Controller
@RequestMapping("/dcn")
public class DCNController {
......
@ExceptionHandler(DCNNotFoundException.class)
public ModelAndView handleDCNRecordError(DCNNotFoundException exception){
ModelAndView mav=new ModelAndView();
mav.addObject("invalidDCN", exception.getDcnNo()); //取得產生exception的變數
mav.addObject("invalidRev", exception.getRev());
mav.setViewName("DCNNotFound");//錯誤網頁名稱為DCNNotFound.jsp
return mav;
}
}
接著新增DCNNotFound.jsp:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${invalidDCN } R${invalidRev } Not Found</title>
<div class="grid">
<div class="row">
<div class="span1"></div>
<div class="span10">
<div class="notice marker-on-bottom bg-darkRed">
<div class="fg-white">
${invalidDCN } R${invalidRev } Not Found. Please Check If DCN No Is Wrong Or A New DCN Record Need Be Added
</div>
</div>
<br/>
<p class="text-center">
<a href="<spring:url value="/dcn"/>" class="button info">Back To DCN List</a>
</p>
</div>
</div>
</div>
重新啟動Server,畫面如下