You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JaxRS中@QueryParam绑定Long类型参数的非数字输入异常处理

处理JAX-RS中Long类型QueryParam的非数字参数异常

当请求传入非数字类型的id参数时,JAX-RS会在参数转换阶段抛出BadRequestException(或对应实现的子类,如Resteasy的ReaderException),原因是无法将字符串转换为Long类型。以下是两种无需将Long改为String的解决方案:

方案一:自定义异常映射器(ExceptionMapper)

通过实现ExceptionMapper接口捕获参数转换异常,返回友好的错误响应。

通用BadRequestException映射器

适用于大多数JAX-RS实现(如Jersey):

import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

@Provider
public class BadRequestExceptionMapper implements ExceptionMapper<BadRequestException> {
    @Override
    public Response toResponse(BadRequestException exception) {
        // 精准匹配Long转换失败的场景
        if (exception.getCause() instanceof NumberFormatException) {
            return Response.status(Response.Status.BAD_REQUEST)
                    .entity("参数id必须为有效的数字类型")
                    .build();
        }
        // 处理其他请求参数错误场景
        return Response.status(Response.Status.BAD_REQUEST)
                .entity("请求参数格式错误")
                .build();
    }
}

Resteasy专属ReaderException映射器

如果使用Resteasy框架,参数转换失败会抛出ReaderException,可针对性处理:

import org.jboss.resteasy.spi.ReaderException;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

@Provider
public class ReaderExceptionMapper implements ExceptionMapper<ReaderException> {
    @Override
    public Response toResponse(ReaderException exception) {
        if (exception.getCause() instanceof NumberFormatException) {
            return Response.status(Response.Status.BAD_REQUEST)
                    .entity("参数id必须为有效的数字类型")
                    .build();
        }
        return Response.status(Response.Status.BAD_REQUEST).build();
    }
}

说明:添加@Provider注解后,JAX-RS会自动注册该映射器,异常发生时自动触发响应处理。

方案二:自定义参数转换器(ParamConverter)

在参数转换阶段直接校验并处理异常,实现更精细的控制。

实现Long参数转换器及提供者

import jakarta.ws.rs.ext.ParamConverter;
import jakarta.ws.rs.ext.ParamConverterProvider;
import jakarta.ws.rs.ext.Provider;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

// 自定义Long类型转换器
public class LongParamConverter implements ParamConverter<Long> {
    @Override
    public Long fromString(String value) {
        if (value == null) {
            return null;
        }
        try {
            return Long.parseLong(value);
        } catch (NumberFormatException e) {
            // 转换失败直接抛出BadRequestException
            throw new jakarta.ws.rs.BadRequestException("参数id必须为有效的数字");
        }
    }

    @Override
    public String toString(Long value) {
        return value == null ? null : value.toString();
    }
}

// 注册转换器提供者
@Provider
public class LongParamConverterProvider implements ParamConverterProvider {
    @Override
    public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
        // 仅对Long类型生效
        if (rawType.equals(Long.class) || rawType.equals(long.class)) {
            return (ParamConverter<T>) new LongParamConverter();
        }
        return null;
    }
}

说明:该方案在参数解析时就完成校验,转换失败立即抛出异常,可结合方案一的异常映射器统一处理响应,也可直接在转换器中定义错误信息。

方案对比

  • 异常映射器:通用性强,可一次性处理所有参数转换失败的场景,无需修改现有接口代码。
  • 自定义转换器:灵活性高,可针对特定类型定制转换逻辑,适合需要复杂校验的场景。

内容的提问来源于stack exchange,提问作者mah454

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 13:05:39