在Javalin+Guice项目中实现自定义@Regex注解自动生效方案咨询
实现方案:利用Guice AOP自动处理@Regex注解
Guice的AOP(面向切面编程)可以自动拦截带有自定义注解的方法/字段,无需手动调用处理器方法。下面是完整的实现示例:
1. 定义@Regex注解
设置正确的保留策略与目标类型,确保Guice能在运行时识别并拦截:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD}) // 支持作用在方法或字段上 public @interface Regex { String pattern(); // 匹配正则表达式 String replacement(); // 替换内容 }
2. 实现Guice方法拦截器
拦截带有@Regex注解的方法,自动处理返回值的正则替换:
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class RegexInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { // 先执行原方法获取返回值 Object result = invocation.proceed(); // 仅处理字符串类型返回值,且方法带有@Regex注解的情况 if (result instanceof String) { Regex regexAnnotation = invocation.getMethod().getAnnotation(Regex.class); if (regexAnnotation != null) { return ((String) result).replaceAll(regexAnnotation.pattern(), regexAnnotation.replacement()); } } return result; } }
3. 配置Guice模块
绑定拦截器与@Regex注解,指定拦截规则:
import com.google.inject.AbstractModule; import com.google.inject.matcher.Matchers; public class AppModule extends AbstractModule { @Override protected void configure() { // 拦截所有带有@Regex注解的方法 bindInterceptor(Matchers.any(), Matchers.annotatedWith(Regex.class), new RegexInterceptor()); // 绑定项目其他服务/实现类,示例: // bind(UserService.class).to(UserServiceImpl.class); } }
4. 整合Javalin与Guice
让Javalin通过Guice管理Bean,确保拦截器生效:
import com.google.inject.Guice; import com.google.inject.Injector; import io.javalin.Javalin; public class MainApp { public static void main(String[] args) { Injector injector = Guice.createInjector(new AppModule()); Javalin app = Javalin.create(config -> { // 配置Javalin使用Guice进行依赖注入 config.dependencyInjector(injector::getInstance); }); // 注册由Guice管理的控制器 app.get("/test", injector.getInstance(TestController.class)::handleTest); app.start(8080); } }
5. 使用@Regex注解的示例控制器
直接在方法上标注注解,无需手动调用处理器:
import io.javalin.http.Context; public class TestController { @Regex(pattern = "\\d+", replacement = "***") public String handleTest(Context ctx) { // 返回的字符串会被自动替换数字为*** return "我的手机号是13812345678"; } }
访问/test时,返回内容自动变为我的手机号是***。
扩展:处理字段自动替换
如果需要对类字段自动处理(如身份证号脱敏),可以实现字段监听处理器:
import com.google.inject.TypeLiteral; import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; import com.google.inject.spi.MembersInjector; import java.lang.reflect.Field; // 字段监听类 public class RegexFieldListener implements TypeListener { @Override public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) { for (Field field : typeLiteral.getRawType().getDeclaredFields()) { if (field.isAnnotationPresent(Regex.class)) { Regex regex = field.getAnnotation(Regex.class); typeEncounter.register(new RegexFieldInjector<>(field, regex)); } } } } // 字段注入处理器 class RegexFieldInjector<T> implements MembersInjector<T> { private final Field field; private final Regex regex; public RegexFieldInjector(Field field, Regex regex) { this.field = field; this.regex = regex; field.setAccessible(true); } @Override public void injectMembers(T instance) { try { Object value = field.get(instance); if (value instanceof String) { String processed = ((String) value).replaceAll(regex.pattern(), regex.replacement()); field.set(instance, processed); } } catch (IllegalAccessException e) { throw new RuntimeException(e); } } }
在Guice模块中注册字段监听:
@Override protected void configure() { // ... 原有拦截器绑定 bindListener(Matchers.any(), new RegexFieldListener()); }
之后实例化带有@Regex注解字段的类时,字段值会自动被处理。
内容的提问来源于stack exchange,提问作者Ger
相关产品推荐
相关产品推荐

