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接口:
- 在
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(); } }
- 在
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
相关产品推荐
相关产品推荐

