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

Quarkus自定义PartialSearch拦截器未执行问题求助

拦截器未执行的原因及修复方案

1. 接口注解未被动态实现类继承

Quarkus的PanacheEntityResource通过动态代理生成实现类,你在UserResource接口的list方法上标注的@PartialSearch注解,默认不会被继承到动态生成的实现方法中,拦截器绑定无法识别到该注解,自然不会触发。

修复:给@PartialSearch添加@Inherited元注解,确保接口方法的注解能被实现类继承:

@InterceptorBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited // 新增该元注解
public @interface PartialSearch {
    String value() default "name";
}

2. 返回值类型不匹配导致拦截器逻辑崩溃

你的拦截器假设context.proceed()返回Response,但list方法实际返回的是反应式类型Uni<List<User>>,强制类型转换会抛出ClassCastException,导致拦截器日志无法输出、逻辑直接终止。

修复:修改拦截器适配反应式返回值:

@Priority(1)
@Interceptor
@PartialSearch
public class PartialSearchInterceptor {

    @Context
    UriInfo uriInfo;

    @AroundInvoke
    public Object intercept(InvocationContext context) throws Exception {
        Log.info("Inside of interceptor");

        try {
            Object result = context.proceed();
            // 处理反应式Uni类型
            if (result instanceof Uni<?>) {
                Uni<?> uniResult = (Uni<?>) result;
                return uniResult.onItem().transform(originalEntity -> {
                    if (originalEntity instanceof List<?> originalEntities) {
                        PartialSearch partialSearch = context.getMethod().getAnnotation(PartialSearch.class);
                        String searchProperty = partialSearch.value();
                        String searchTerm = uriInfo.getQueryParameters().getFirst(searchProperty);

                        if (searchTerm == null || searchTerm.isBlank()) {
                            return originalEntities;
                        }

                        List<Object> filteredEntities = new ArrayList<>();
                        for (Object entity : originalEntities) {
                            try {
                                if (matchesSearchCriteria(entity, searchProperty, searchTerm)) {
                                    filteredEntities.add(entity);
                                }
                            } catch (SearchCriteriaException e) {
                                throw new RuntimeException(e);
                            }
                        }
                        return filteredEntities;
                    }
                    return originalEntity;
                }).onFailure().recoverWithItem(e -> {
                    if (e.getCause() instanceof SearchCriteriaException sce) {
                        Problem problem = new Problem(
                                "https://example.com/problem/invalid-property",
                                "INVALID_SEARCH_PROPERTY",
                                Response.Status.BAD_REQUEST.getStatusCode(),
                                sce.getMessage(),
                                uriInfo.getAbsolutePath().toString());
                        return Response.status(Response.Status.BAD_REQUEST).entity(problem).build();
                    }
                    throw new RuntimeException(e);
                });
            }
            return result;
        } catch (SearchCriteriaException sce) {
            Problem problem = new Problem(
                    "https://example.com/problem/invalid-property",
                    "INVALID_SEARCH_PROPERTY",
                    Response.Status.BAD_REQUEST.getStatusCode(),
                    sce.getMessage(),
                    uriInfo.getAbsolutePath().toString());
            return Response.status(Response.Status.BAD_REQUEST).entity(problem).build();
        }
    }

    // 保留原matchesSearchCriteria和SearchCriteriaException方法不变
}

3. 拦截器未被正确注册

确保Quarkus的Arc容器扫描到你的拦截器:

  • 检查拦截器类是否在Quarkus的扫描路径下(默认是项目主包及子包)
  • 可在application.properties中添加日志验证拦截器是否被加载:
quarkus.log.category."io.quarkus.arc".level=DEBUG

启动后查看日志,确认PartialSearchInterceptor被Arc容器注册。

额外优化:改用数据库层面模糊查询

拦截器是在内存中过滤全匹配结果,性能较低。更优方案是直接在实体类中定义模糊查询方法,覆盖list接口:

  1. 在User实体中添加查询方法:
@Entity
public class User extends PanacheEntityBase {
    public UUID id;
    public String email;
    // 其他字段

    public static Uni<List<User>> findByEmailLike(String email) {
        return find("email LIKE ?1", "%" + email + "%").list();
    }
}
  1. 在UserResource中自定义list方法:
@ResourceProperties(path = "/users")
public interface UserResource extends PanacheEntityResource<User, UUID> {

    @GET
    @Path("")
    default Uni<List<User>> list(@QueryParam("email") String email, Page page, Sort sort) {
        if (email != null && !email.isBlank()) {
            return User.findByEmailLike(email).page(page).sort(sort);
        }
        return User.findAll().page(page).sort(sort).list();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 04:21:00