Spring ControllerAdvice Usage。
我們在寫AP程式時, 有時候會因為一些流程上的規劃,需要在一些特定情況下拋出例外條件並做處理(eg. 跳警告視窗、導頁)。
本次將會使用 Ajax 從前端送出 request 給 Spring 後台後拋出 Exception 進行導頁。
1. 首先先自訂一個 Exception 的 class,以利模擬之後丟出 Exception 使用。
public class AppException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String redirectUrl;
public AppException() {
super();
}
public AppException(String message, Throwable cause) {
super(message, cause);
}
public AppException(String message) {
super(message);
}
public String getRedirectUrl() {
return redirectUrl;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
}
2. 撰寫起始頁面與導向頁面,步驟如下:
a. 撰寫 exception.jsp,設定利用 viewController 直接導向,於頁面onload完成後利用 /spring_ryuichi/exceptionCatcher導向controller。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<script src="${pageContext.request.contextPath}/static/js/jquery-ui/external/jquery/jquery.js"></script>
<script src="${pageContext.request.contextPath}/static/js/jquery-ui/jquery-ui.js"></script>
<script src="${pageContext.request.contextPath}/static/js/exception.js"></script>
</head>
<body onload="onReady()">
準備導頁
</body>
</html>
@Override
public void addViewControllers(ViewControllerRegistry registry) {
/**
* we can register view controllers that create a direct mapping between the URL and the view name using the ViewControllerRegistry.
* This way, there’s no need for any Controller between the two
* 意即, 在此註冊路徑mapping, 於畫面上要取改jsp頁面時, 不需要額外寫controller去控制導向該頁
*/
//eg. 設定此行, 要access WEB-INF/view下的index.jsp, 於畫面上打 http://localhost:8080/spring_ryuichi/
//他就會自動導向該頁面 index.jsp
registry.addViewController("/exception").setViewName("exception");
}
function onReady() {
alert("準備導頁");
$.ajax({
url:'/spring_ryuichi/exceptionCatcher', //導向controller準備丟出Appexception
type:"post",
//dataType (default: Intelligent Guess (xml, json, script, or html))
processData:false,
contentType:false,
success:function(data) {
alert("success " + data);
//導向指定的jsp
if(data.redirectUrl != null) {
//導頁
location.replace(data.redirectUrl);
}
},
error:function(data) {
alert("error " + data);
alert(data.redirectUrl)
//導向指定的jsp
if(data.redirectUrl != null) {
//導頁
location.replace(data.redirectUrl);
}
}
});
}
b.controller準備丟出Appexception。
@Controller
@ComponentScan("com.spring.tku")
public class TkuController {
private static Logger logger = Logger.getLogger(TkuController.class);
@RequestMapping("/sample")
public String sample() {
logger.info("進入Sample Controller");
return "sample";
}
@RequestMapping("/exceptionCatcher")
public String exceptionCatcher() throws AppException {
AppException app = new AppException("例外接收測試");
app.setRedirectUrl("/spring_ryuichi/sample");//設定丟出exception後要導向的頁面
throw app;
//return "exceptionCatcher";
}
}
3. 定義 controlleraDvice,接收拋出的 AppException。
@ControllerAdvice
//GlobalExceptionHandler:處理Controller中的異常
public class GlobalExceptionHandler {
/**
* Method handles the AppException
*
* @param ex
* @return Map<String, Object>
*/
@ExceptionHandler(AppException.class) //// 攔截所有AppException,value可設定攔截條件
public @ResponseBody Map<String, Object> handleAppException(AppException ex) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("exception", ex.getMessage());
map.put("redirectUrl", ex.getRedirectUrl());
return map;
}
}
於 Ajax 呼叫完後判斷 redirectUrl 是否有值,若有則進行導頁,這邊順帶一提,經過Spring controllerAdvice處理回傳過後。
若想要從 Ajax 的 success 執行,則須在方法名前面加上@ResponseBody,讓 Spring 將你所回傳的內容轉成JSON格式,讓 Ajax 可以認得出格式來。
Ajax 若沒指定 datatype,預設接收格式會去猜 xml、json、script or html。
認不出格式的話,會導向error的區塊,反之,則進入success區塊。
4. 範例結果如下,輸入 http://localhost:8080/spring_ryuichi/exception 後的頁面變化。