Angularjs - Spring MVC Rest:如何处理异常
Angularjs - Spring MVC Rest : how to handle exceptions
我正在使用 angularjs 和 Spring Mcv Rest 开发单页应用程序。
我像 Angularjs 中那样调用我的服务(使用 javax 邮件发送邮件):SendProformaFax.get({idCommande:$scope.commande.id})
在服务器端我的服务:
@RequestMapping(value = "/sendProformaFax/{idCommande}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public void imprimeProforma(@PathVariable String idCommande) {
Commande commande = commandeRepository.findOne(new Long(idCommande));
List<Vente> ventes = venteRepository.findAllByCommande(commande);
blService.sendProformaFax(ventes);
}
我想在函数 sendProformaFax 抛出 MessagingException 时显示消息。
我不知道如何 return 我的 RestController 中的这个异常以及如何在 Angularjs 中捕获它。
如果有人可以帮助我...
谢谢。
编辑:
在服务器端,我正在这样做:
@ExceptionHandler(value = Exception.class)
public ErrorView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
// If the exception is annotated with @ResponseStatus rethrow it and let
// the framework handle it - like the OrderNotFoundException example
// at the start of this post.
// AnnotationUtils is a Spring Framework utility class.
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
throw e;
// Otherwise setup and send the user to a default error-view.
ErrorView mav = new ErrorView();
mav.setException(e.getMessage());
mav.setUrl(req.getRequestURL().toString());
mav.setMessage("Veuillez contacter le support informatique.");
return mav;
}
在Angularjs这边我正在做这个
CreateFichierCiel.get({params:param}, function (response) {
$scope.infoMessage = "La génération du fichier CIEL est terminée."
$activityIndicator.stopAnimating();
$("#messageModal").modal('show');
$scope.find();
}, function (reason) {
$("#errorModal").modal('show');
})
但是'reason'对象是这样的:
config: Object data: Object error: "Internal Server Error" exception:
"java.lang.NullPointerException" message: "No message available" path:
"/api/createFichierCiel/15-00005" status: 500 timestamp: 1438430232307
proto: Object headers: function (name) { status: 500 statusText:
"Internal Server Error" proto: Object
所以我没有收到服务器发送的 ErrorView class。
如果有人能看出我哪里错了...
谢谢
您可以为 MessagingException
设置 ExceptionHandler
并设置 HTTPStatus
以指示响应有错误(例如 BAD_REQUEST
)
@ExceptionHandler(MessagingException.class)
@ResponseStatus(HTTPStatus.BAD_REQUEST)
@ResponseBody
public ErrorView handleMessagingException(MessagingException ex) {
// do something with exception and return view
}
在 AngularJS 中,您可以像这样从资源服务中捕获它:
MessagingService.get({idCommande: 1}, function (data) {
// this is success
}, function (reason) {
// this is failure, you can check if this is a BAD_REQUEST and parse response from exception handler
};
用$http
就差不多了。
添加 kTT 的答案,从 Spring 4
开始,您可以将 @ExceptionHandler
方法包装在 class 注释中 @ControllerAdvice
这样您将在整个应用程序中收到相同类型异常的相同消息。更多可以看看here
我就是这样做的,我们在项目中使用 spring mvc 和 angularjs。
我有这个 controllerAdvice class
@ControllerAdvice
public class ExceptionControllerAdvice {
@ExceptionHandler(ServiceException.class)
public ResponseEntity<ErrorResponse> rulesForCustomerNotFound(HttpServletRequest req, ServiceException e)
{
ErrorResponse error = new ErrorResponse();
error.portalErrorCode = e.getExceptionCode();
error.message = e.getMessage();
return new ResponseEntity<ErrorResponse>(error, HttpStatus.NOT_FOUND);
}
}
class ErrorResponse {
public int portalErrorCode;
public String message;
}
然后在 restful 控制器中,其中 ServiceException 是自定义的可运行异常:
@Override
@RequestMapping("/getControls/{entity}")
public List<Control> getControls(@PathVariable(value="entity") String entity) throws ServiceException {
List<Control> controls = ImmutableList.of();
try {
controls = dao.selectControls(entity);
} catch (Exception e) {
logger.error("getting list of controls encountered an error ", e);
throw new ServiceException(50, "getting list of controls encountered an error.");
}
return controls;
}
在我的 app.js 文件中 angularjs 我使用
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($q, $location) {
return {
'response': function (response) {
//Will only be called for HTTP up to 300
return response;
},
'responseError': function (rejection) {
if(rejection.status === 0) {
alert('There is a problem connecting to the server. Is the server probably down?!');
}
else {
$location.url('/error').search({rejection: rejection});
}
return $q.reject(rejection);
}
};
});
}])
并在 error.controller.js
function init() {
ctrl.rejection = $location.search().rejection;
ctrl.portalErrorCode = ctrl.rejection.data.portalErrorCode;
ctrl.errorMessage = ctrl.rejection.data.message;
$log.info('An error occured while trying to make an ajax call' + ctrl.errorMessage + ': ' + ctrl.portalErrorCode);
}
当然还有 error.tpl.html
<h2>
{{ctrl.rejection.status}} {{ctrl.rejection.statusText}}
</h2>
<h3 class="error-details">
Sorry, an error has occurred!
</h3>
<h3 class="error-details">
{{ctrl.errorMessage}}
</h3>
我正在使用 angularjs 和 Spring Mcv Rest 开发单页应用程序。
我像 Angularjs 中那样调用我的服务(使用 javax 邮件发送邮件):SendProformaFax.get({idCommande:$scope.commande.id})
在服务器端我的服务:
@RequestMapping(value = "/sendProformaFax/{idCommande}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public void imprimeProforma(@PathVariable String idCommande) {
Commande commande = commandeRepository.findOne(new Long(idCommande));
List<Vente> ventes = venteRepository.findAllByCommande(commande);
blService.sendProformaFax(ventes);
}
我想在函数 sendProformaFax 抛出 MessagingException 时显示消息。
我不知道如何 return 我的 RestController 中的这个异常以及如何在 Angularjs 中捕获它。
如果有人可以帮助我...
谢谢。
编辑: 在服务器端,我正在这样做:
@ExceptionHandler(value = Exception.class)
public ErrorView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
// If the exception is annotated with @ResponseStatus rethrow it and let
// the framework handle it - like the OrderNotFoundException example
// at the start of this post.
// AnnotationUtils is a Spring Framework utility class.
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
throw e;
// Otherwise setup and send the user to a default error-view.
ErrorView mav = new ErrorView();
mav.setException(e.getMessage());
mav.setUrl(req.getRequestURL().toString());
mav.setMessage("Veuillez contacter le support informatique.");
return mav;
}
在Angularjs这边我正在做这个
CreateFichierCiel.get({params:param}, function (response) {
$scope.infoMessage = "La génération du fichier CIEL est terminée."
$activityIndicator.stopAnimating();
$("#messageModal").modal('show');
$scope.find();
}, function (reason) {
$("#errorModal").modal('show');
})
但是'reason'对象是这样的:
config: Object data: Object error: "Internal Server Error" exception: "java.lang.NullPointerException" message: "No message available" path: "/api/createFichierCiel/15-00005" status: 500 timestamp: 1438430232307 proto: Object headers: function (name) { status: 500 statusText: "Internal Server Error" proto: Object
所以我没有收到服务器发送的 ErrorView class。 如果有人能看出我哪里错了...
谢谢
您可以为 MessagingException
设置 ExceptionHandler
并设置 HTTPStatus
以指示响应有错误(例如 BAD_REQUEST
)
@ExceptionHandler(MessagingException.class)
@ResponseStatus(HTTPStatus.BAD_REQUEST)
@ResponseBody
public ErrorView handleMessagingException(MessagingException ex) {
// do something with exception and return view
}
在 AngularJS 中,您可以像这样从资源服务中捕获它:
MessagingService.get({idCommande: 1}, function (data) {
// this is success
}, function (reason) {
// this is failure, you can check if this is a BAD_REQUEST and parse response from exception handler
};
用$http
就差不多了。
添加 kTT 的答案,从 Spring 4
开始,您可以将 @ExceptionHandler
方法包装在 class 注释中 @ControllerAdvice
这样您将在整个应用程序中收到相同类型异常的相同消息。更多可以看看here
我就是这样做的,我们在项目中使用 spring mvc 和 angularjs。 我有这个 controllerAdvice class
@ControllerAdvice
public class ExceptionControllerAdvice {
@ExceptionHandler(ServiceException.class)
public ResponseEntity<ErrorResponse> rulesForCustomerNotFound(HttpServletRequest req, ServiceException e)
{
ErrorResponse error = new ErrorResponse();
error.portalErrorCode = e.getExceptionCode();
error.message = e.getMessage();
return new ResponseEntity<ErrorResponse>(error, HttpStatus.NOT_FOUND);
}
}
class ErrorResponse {
public int portalErrorCode;
public String message;
}
然后在 restful 控制器中,其中 ServiceException 是自定义的可运行异常:
@Override
@RequestMapping("/getControls/{entity}")
public List<Control> getControls(@PathVariable(value="entity") String entity) throws ServiceException {
List<Control> controls = ImmutableList.of();
try {
controls = dao.selectControls(entity);
} catch (Exception e) {
logger.error("getting list of controls encountered an error ", e);
throw new ServiceException(50, "getting list of controls encountered an error.");
}
return controls;
}
在我的 app.js 文件中 angularjs 我使用
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($q, $location) {
return {
'response': function (response) {
//Will only be called for HTTP up to 300
return response;
},
'responseError': function (rejection) {
if(rejection.status === 0) {
alert('There is a problem connecting to the server. Is the server probably down?!');
}
else {
$location.url('/error').search({rejection: rejection});
}
return $q.reject(rejection);
}
};
});
}])
并在 error.controller.js
function init() {
ctrl.rejection = $location.search().rejection;
ctrl.portalErrorCode = ctrl.rejection.data.portalErrorCode;
ctrl.errorMessage = ctrl.rejection.data.message;
$log.info('An error occured while trying to make an ajax call' + ctrl.errorMessage + ': ' + ctrl.portalErrorCode);
}
当然还有 error.tpl.html
<h2>
{{ctrl.rejection.status}} {{ctrl.rejection.statusText}}
</h2>
<h3 class="error-details">
Sorry, an error has occurred!
</h3>
<h3 class="error-details">
{{ctrl.errorMessage}}
</h3>