是否可以使用注释连接Spring MVC Interceptor?

Jam*_*hon 27 spring annotations spring-mvc autowired interceptor

是否可以使用注释连接Spring MVC Interceptor,如果是这样,有人可以提供一个如何操作的示例吗?

通过注释通过注释,我指的是尽可能少地在XML配置中做.例如,我在http://www.vaannila.com/spring/spring-interceptors.html找到了这个配置文件;

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:interceptors-ref="loggerInterceptor" />
<bean id="loggerInterceptor" class="com.vaannila.interceptor.LoggerInterceptor" />
Run Code Online (Sandbox Code Playgroud)

你有多少配置可以逃脱?我想是一个@Autowired将删除在第2行显式声明bean的需要,但是也可以用注释去掉第1行吗?

Mar*_*sch 75

在搜索这个问题时偶然发现了这个问题.最后我发现它在Spring 3.1中使用@EnableWebMVC和WebMvcConfigurerAdapter一起工作.

简单示例:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages="webapp.base.package")
public class WebApplicationConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggerInterceptor());
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 我认为这应该是一个公认的答案.有一点需要注意,如果你想自动装配你的自定义拦截器,在一个`@Configuration`类中将它声明为`@ Bean`,并通过它的bean方法添加创建它. (11认同)

axt*_*avt 19

据我所知,没有办法在没有XML的情况下配置Spring MVC拦截器.

但是,mvc最新版本的Spring 3.0.x(不是Spring 3.0.0!)中有一些名称空间的简化:

<mvc:interceptors>
    <bean class="com.vaannila.interceptor.LoggerInterceptor" />
</mvc:interceptors>
Run Code Online (Sandbox Code Playgroud)

也可以看看:


Bri*_*ace 7

@Interceptor本着 Spring@Controller注释的精神使用自定义注释实现了一个可行的解决方案:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Component
public @interface Interceptor {
  String[] pathPatterns() default {};
  String[] excludePathPatterns() default {};
}
Run Code Online (Sandbox Code Playgroud)

此注释应应用于如下HandlerInterceptor类型:

@Interceptor
public class BuildTimestampInterceptor extends HandlerInterceptorAdapter {
  private final String buildTimestamp;

  public BuildTimestampInterceptor(@Value("${build.timestamp}") String buildTimestamp) {
    this.buildTimestamp = buildTimestamp;
  }

  @Override
  public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
    req.setAttribute("buildTimestamp", buildTimestamp);
    return true;
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,处理器类InterceptorProcessor是一个 Spring bean,它扩展WebMvcConfigurerAdapter和实现BeanPostProcessor以扫描自定义@Interceptor注释并将具有该注释的 bean 注册为HandlerInterceptors 在重写addInterceptors方法中:

@Component
public class InterceptorProcessor extends WebMvcConfigurerAdapter implements BeanPostProcessor {
  private final Map<HandlerInterceptor,Interceptor> interceptors = new HashMap<>();

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    scanForInterceptorAnnotation(bean, beanName);
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String string) throws BeansException {
    return bean;
  }

  protected void scanForInterceptorAnnotation(Object bean, String beanName) {
    Optional<Interceptor> optionalInterceptor = getInterceptorAnnotation(bean.getClass());
    if (optionalInterceptor.isPresent() && bean instanceof HandlerInterceptor) {
      interceptors.put((HandlerInterceptor) bean, optionalInterceptor.get());
    }
  }

  private Optional<Interceptor> getInterceptorAnnotation(Class cls) {
    Annotation[] annotations = cls.getAnnotationsByType(Interceptor.class);
    if (hasValue(annotations)) {
      return Optional.of((Interceptor) annotations[0]);
    }
    return Optional.empty();
  }

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    interceptors.forEach((HandlerInterceptor key, Interceptor val) -> {
      InterceptorRegistration registration = registry.addInterceptor(key);
      if (hasValue(val.pathPatterns())) {
        registration.addPathPatterns(val.pathPatterns());
      }

      if (hasValue(val.excludePathPatterns())) {
        registration.excludePathPatterns(val.excludePathPatterns());
      }
    });
  }

  private static <T> boolean hasValue(T[] array) {
    return array != null && array.length > 0;
  }
}
Run Code Online (Sandbox Code Playgroud)

请记住让您的 spring 应用程序扫描此处理器 bean,以便让它实际注册您的@Interceptors。就像是:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"org.my.controller", "org.my.utils.processor"})
public class WebConfig extends WebMvcConfigurerAdapter {...
Run Code Online (Sandbox Code Playgroud)