RESTEasy中的通用异常处理ExceptionMapper

RESTEasy是JBoss提供的一个Restful基础框架,使用它我们可以很方便的构建我们的Restful服务,而且它也完全符合Java的JAX-RS2.0标准,很多第三方Restful框架也都是基于RESTEasy开发的。

在任何框架中都不可避免的涉及到异常处理,Restful框架也是如此。按照我们一般传统异常处理方式,在Restful的最外层,我们一般会对所有的业务调用都加上try catch,以免异常被用户接收到,比如我们有这么一个Restful服务:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.spi.validation.ValidateRequest;

@Path("/rest")
public class UserApi
{
    @Autowire
    UserService userService;
    @Path("/users/{id}")
    @GET
    @ValidateRequest
    public Response getUserBId  ( @PathParam("id") String id ) throws RuntimeException
    {
        try{
            User user=userService.getUser(id);
        } catch(IllegalArgumentException e) {
            //if exception occured
            return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
        } catch(Exception e) {
            //if exception occured
            return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
        }
        //if success
        return Response.ok().entity("User with ID " + id + " found !!").build();
    }
}

上面UserApi接口中的getUserBId()方法调用了userService.getUser()服务,这个服务会抛出一些异常,UserApi需要捕获异常并返回客户的一个错误的响应。还有一点我们一般会在API层catch一个Exception异常,也就是捕获所有可能发生的异常情况,以免前端出现不友好的错误提示。

这么做也没什么问题,但是我们的接口不只是一个,每个接口需要进行try catch来处理异常,这么做显然不符合我们的编程思想,我们希望把所有异常集中到一个地方处理。

如果我们的Restful框架是基于RESTEasy的,那么我们就可以使用ExceptionMapper来实现一个通用异常处理类。

使用ExceptionMapper进行通用异常处理

ExceptionMapper是provider的一个协议,它会将Java的异常映射到Response对象。所以要进行通用异常处理,我们只需要写一个类来实现ExceptionMapper接口,并把它声明为一个provider即可:

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class MyApplicationExceptionHandler implements ExceptionMapper<MyApplicationException>
{
    @Override
    public Response toResponse(Exception exception)
    {
        return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
    }
}

上面的ExceptionMapper的实现已经写好了,下面我们写个Restful API来测试下:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.spi.validation.ValidateRequest;

@Path("/rest")
public class UserApi
{
    @Autowire
    UserService userService;
    @Path("/users/{id}")
    @GET
    @ValidateRequest
    public Response getUserBId  ( @PathParam("id") String id ) throws RuntimeException
    {
        try{
            User user=userService.getUser(id);
        } catch(IllegalArgumentException e) {
           throw new RuntimeException("id is not a number !!");
        }
        return Response.ok().entity("User with ID " + id + " found !!").build();
    }
}

在这个接口中,我们并没有对异常做特殊处理,也没有catch一个Exception异常,仅仅是把异常抛出,而所有的异常处理都集中在了MyApplicationExceptionHandler中。

我们测一下这个接口,首先我们写一个合法的请求:

http://localhost:8080/RESTEasyExceptionMapperDemo/rest/users/1

我们再写一个不合法的请求,请求的参数是个字符串而不是数值:

http://localhost:8080/RESTEasyExceptionMapperDemo/rest/users/abc

时间: 2024-10-24 22:32:10

RESTEasy中的通用异常处理ExceptionMapper的相关文章

DNN模块开发系列文章(6)——DNN中的通用控件(下)

TextEditor: 开发系列文章(6)--DNN中的通用控件(下)-通用语言模块">简介: 富文本编辑器控件.功能就不用多说了吧,大家都经常用到的.DNN利用Providers模式可以很方便的集成多种富文本编辑器.据我所知就有:FreeTextBox,FCKEditor,WebHtmlEditor,CuteEditor.大家可以通过配置web.config就可以很容易的选择使用一种了,具体的配置方法在每一个富文本编辑器Providers中应该都有详细的说明. 位置:controls\T

DNN模块开发系列文章(5)——DNN中的通用控件(上)

DNN中的通用控件主要在DotNetNuke.UI命名空间下,而与模块开发紧密相关的都在DotNetNuke.UI.UserControls中,它们是开发具有DNN风格模块不可缺少的元素. LabelControl 文章(5)--DNN中的通用控件(上)-通用语言模块"> 简介: 标签控件.这个应该是用的最多的一个控件了.主要起到在输入框前起提示作用,如果点击问号图标开可以给出详细的说明. 位置: controls\LabelControl.ascx 属性: ControlName:对应控

Visual C++中的结构异常处理

1.引言 在"C++中例外的处理"一文中(见计算机世界网2001年12月20日),我们讨论了C++中的例外(或异常)处理.本文将进一步探讨Visual C++中的结构异常处理. 想象一下,如果在编程过程中你不需要考虑任何错误,你的程序永远不会出错,有足够的内存,你需要的文件永远存在,这将是一件多么愉快的事.这时你的程序不需要太多的if语句转来转去,非常容易写,容易读,也容易理解.如果你认为这样的编程环境是一种梦想,那么你就会喜欢结构异常处理(structu reed exception

link中结构化异常处理方面的问题?如果我希望忽略异常请问怎么做?

问题描述 link中结构化异常处理方面的问题?如果我希望忽略异常请问怎么做? link中结构化异常处理方面的问题?如果我希望忽略异常请问怎么做? 解决方案 在lambda表达式内处理异常,不要丢出异常

[译]Swift 中的通用数据源

本文讲的是[译]Swift 中的通用数据源, 原文地址:Generic Data Sources in Swift 原文作者:Andrea Prearo 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:Swants 校对者:iOSleep Swift 中的通用数据源 在我开发的绝大多数 iOS app 中, tableView 和 collectionView 绝对是最常用的 UI 组件.鉴于设置一个 tableView 或 collectionVie

C++builder中关于excel异常处理

问题描述 C++builder中关于excel异常处理 1C 如题哦.小弟初次接触BCB在使用其做一个Excel保存数据的时候,在数据写入部分的如果出现异常 则仅仅是退出Excel,而并没有关闭Excel里面已经打开的工作薄.而在数据保存的时候是关闭了工作薄并退出了Excel.想向各位大牛求助,如果在数据写入出现了异常,仅仅退出了Excel而没有关闭excel中的工作薄会出现什么样的bug? 现在再调试的时候发现,在保存数据之后关闭excel后,保存的excel双击不能打开了.必须从开始,所有程

django-Django中的通用视图是个难点吗

问题描述 Django中的通用视图是个难点吗 今天搞了一天.这个通用视图,我是一点没懂.网上也查不到详细的资料.求助啊 解决方案 http://www.jb51.net/article/65418.htm 解决方案二: django的通用视图Django 通用视图django 通用视图----------------------

Winform界面中实现通用工具栏按钮的事件处理

在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和我标准的界面处理方式有所不同,标准的列表界面,一般在界面中放置了一些常规的按钮,如查询/更新.新建.编辑.删除.导入.导出等常规操作,现在是需要把这些提升到主界面的层次上放置按钮,这种处理方式也算是提供一种方便吧.本篇随笔介绍实现这个功能的思路和代码实现逻辑. 1.界面功能介绍 这里要实现的通用工具栏按钮的事件处理,具体的界面是这样的,

PHP中一些通用和易混淆技术点的最佳编程实践

最新改进&维护 本文档最后一次于2013年3月8日审核.最后一次修改是在2013年3月8日. 这由我, Alex Cabal维护的.到现在我已经写了很长时间PHP代码了, 目前我运行Scribophile,为严肃作家提供的在线写作小组, Writerfolio, 为自由职业者提供的简单的在线写作文件夹, 和 Standard Ebooks, 有插画的出版物,无数字版权的公共领域电子图书 . 偶尔我会自由的去找那些让我感兴趣的项目和客户. 如果你认为我能够帮你些什么,或者有些关于本文的建议或勘误的