RESTEasy中的通用异常处理ExceptionMapper

简介: RESTEasy是JBoss提供的一个Restful基础框架,使用它我们可以很方便的构建我们的Restful服务,而且它也完全符合Java的JAX-RS2.0标准,很多第三方Restful框架也都是基于RESTEasy开发的。在任何框架中都不可避免的涉及到异常处理,Restful框架也是如此。按照我们一般传统异常处理方式,在Restful的最外层,我们一般会对所有的业务调

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

这里写图片描述

目录
相关文章
|
缓存 Java 应用服务中间件
面试官:如何实现多级缓存?
面试官:如何实现多级缓存?
663 1
|
自然语言处理 Java 索引
Elastic:如何查询特殊字符
某些业务场景下我们需要使用特殊符号来进行查询,但是es的默认分词器以及ik分词器等大多数分词器都会将特殊符号过滤掉,导致后续无法通过特殊符号查询到数据。 那么我们如何来解决这个问题呢,下面列举出几种处理方案
1746 0
|
5月前
|
人工智能 前端开发 Serverless
如何用 Claude AWS配合阿里云函数计算搭建AI应用
企业核心业务在阿里云,却需调用AWS Bedrock的Claude模型?推荐用阿里云函数计算(FC)构建Serverless代理网关:安全隐藏AK/SK、弹性抗并发、网络更稳定。架构为“用户→API网关→FC→Bedrock”,百毫秒延迟,轻量高效。
|
消息中间件 运维 监控
加一个JVM参数,让系统可用率从95%提高到99.995%
本文针对一个高并发(10W+ QPS)、低延迟(毫秒级返回)的系统因内存索引切换导致的不稳定问题,深入分析并优化了JVM参数配置。通过定位问题根源为GC压力大,尝试了多种优化手段:调整MaxTenuringThreshold、InitialTenuringThreshold、AlwaysTenure等参数让索引尽早晋升到老年代;探索PretenureSizeThreshold和G1HeapRegionSize实现索引直接分配到老年代;加速索引复制过程以及升级至JDK11使用ZGC。
871 82
加一个JVM参数,让系统可用率从95%提高到99.995%
|
存储 Java
Java中判断一个对象是否是空内容
在 Java 中,不同类型的对象其“空内容”的定义和判断方式各异。对于基本数据类型的包装类,空指对象引用为 null;字符串的空包括 null、长度为 0 或仅含空白字符,可通过 length() 和 trim() 判断;集合类通过 isEmpty() 方法检查是否无元素;数组的空则指引用为 null 或长度为 0。
|
Web App开发 移动开发 JavaScript
纯CSS3+SVG实现的节日庆祝五彩纸屑动画效果源码
这是一款基于纯CSS3+SVG实现的节日庆祝五彩纸屑动画效果源码。画面中左下角是一个圆锥形礼炮卡通效果,呈现出节日庆祝时礼花爆破、五彩纸屑纷飞的动画特效。整体动画效果采用纯css3+svg实现,没有引入任何外部图形或js脚本元素。建议使用支持HTML5与css3效果较好的火狐(Firefox)或谷歌(Chrome)等浏览器预览本源码。
428 6
|
存储 Java 开发者
成功优化!Java 基础 Docker 镜像从 674MB 缩减到 58MB 的经验分享
本文分享了如何通过 jlink 和 jdeps 工具将 Java 基础 Docker 镜像从 674MB 优化至 58MB 的经验。首先介绍了选择合适的基础镜像的重要性,然后详细讲解了使用 jlink 构建自定义 JRE 镜像的方法,并通过 jdeps 自动化模块依赖分析,最终实现了镜像的大幅缩减。此外,文章还提供了实用的 .dockerignore 文件技巧和选择安全、兼容的基础镜像的建议,帮助开发者提升镜像优化的效果。
|
前端开发 JavaScript
HTML+CSS如何打造撒花动画效果?3分钟学会,炫酷到爆!
HTML+CSS如何打造撒花动画效果?3分钟学会,炫酷到爆!
|
Oracle Java 关系型数据库
JLink 使用教程:从入门到精通
本文提供了JLink工具的使用教程,包括入门、进阶和高级篇,涉及创建运行时镜像、添加模块、自定义启动器、压缩镜像、自定义运行时参数和配置文件等内容,旨在帮助用户创建独立的Java应用程序运行时环境。
2510 0