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

如何对Jakarta REST手动实例化的子资源进行约束验证?

解决Jakarta REST子资源的验证失效问题

问题核心在于:你手动实例化的SampleResource不受CDI容器管理,因此Jakarta Bean Validation的注解(如@NotNull)无法被自动触发校验。而根资源SamplesResource是@RequestScoped的容器管理Bean,所以它的方法校验能正常执行。

以下是三种可行的解决方案:


方案一:将子资源改为CDI管理Bean(推荐)

通过让容器负责子资源的实例化和依赖注入,自动触发验证逻辑。

修改子资源代码

将SampleResource标记为CDI作用域,去掉带参数的构造方法,改用@PathParam注入路径参数:

package fr.laboiteadodo.trysub;

import jakarta.enterprise.context.RequestScoped;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.*;

/**
 * 子资源
 */
@RequestScoped
public class SampleResource {
    @PathParam("code")
    private String code;

    // 保留无参构造方法,供容器实例化
    public SampleResource() {}

    @GET
    public String getSample() {
        return code;
    }

    @POST
    public String update(@FormParam("code") @NotNull String code) {
        this.code = code;
        return code;
    }
}

修改根资源的子资源方法

让容器负责创建子资源实例,返回子资源的Class类型即可:

@Path("{code}")
public Class<SampleResource> getSample() {
    return SampleResource.class;
}

方案二:手动触发验证(适配必须保留带参构造的场景)

如果业务需求要求保留带参数的构造方法,可手动注入Validator并主动校验参数。

修改子资源代码

添加Validator注入逻辑,并在方法内手动校验:

package fr.laboiteadodo.trysub;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.*;
import java.util.Set;

/**
 * 子资源
 */
public class SampleResource {
    private String code;
    private Validator validator;

    public SampleResource(String code) {
        this.code = code;
    }

    // 提供setter供根资源注入Validator
    public void setValidator(Validator validator) {
        this.validator = validator;
    }

    @GET
    public String getSample() {
        return code;
    }

    @POST
    public String update(@FormParam("code") @NotNull String code) {
        // 手动校验参数
        Set<ConstraintViolation<SampleResource>> violations = validator.validateValue(SampleResource.class, "update", code);
        if (!violations.isEmpty()) {
            throw new jakarta.validation.ValidationException(violations.iterator().next().getMessage());
        }
        this.code = code;
        return code;
    }
}

修改根资源代码

注入Validator并传递给子资源实例:

package fr.laboiteadodo.trysub;

import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.validation.Validator;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;

/**
 * 根资源
 */
@RequestScoped
@Path("samples")
public class SamplesResource {
    @Inject
    private Validator validator;

    @Path("{code}")
    public SampleResource getSample(@PathParam("code") String code) {
        SampleResource resource = new SampleResource(code);
        resource.setValidator(validator);
        return resource;
    }

    @POST
    @Produces(MediaType.TEXT_PLAIN)
    public String create(@FormParam("code") @NotNull String code) {
        return code;
    }
}

方案三:使用CDI Producer创建子资源实例

通过Producer方法封装子资源的实例化逻辑,让容器管理实例生命周期并触发验证。

创建Producer类

package fr.laboiteadodo.trysub;

import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.ws.rs.PathParam;

@RequestScoped
public class SampleResourceProducer {

    @Produces
    @RequestScoped
    public SampleResource produceSampleResource(@PathParam("code") String code) {
        return new SampleResource(code);
    }
}

修改根资源代码

注入Producer生成的子资源实例:

package fr.laboiteadodo.trysub;

import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;

/**
 * 根资源
 */
@RequestScoped
@Path("samples")
public class SamplesResource {
    @Inject
    private SampleResource sampleResource;

    @Path("{code}")
    public SampleResource getSample() {
        return sampleResource;
    }

    @POST
    @Produces(MediaType.TEXT_PLAIN)
    public String create(@FormParam("code") @NotNull String code) {
        return code;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:54:51