【问题标题】:Spring Interceptor is not compatible with @RepositoryRestResourceSpring 拦截器与 @RepositoryRestResource 不兼容
【发布时间】:2021-05-16 11:29:38
【问题描述】:
@Component
    public class TestInterceptor implements HandlerInterceptor {
        @Override
        public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {
            System.out.println("afterCompletion");
        }
        @Override
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {
            System.out.println("postHandle");
        }
        @Override
        public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
            System.out.println("preHandle");
            return true;
        }
    }

和

@SpringBootConfiguration
public class AnnotationSecurityConfiguration implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TestInterceptor()).addPathPatterns("/api/**");
    }
}

最后,使用@RepositoryRestController 将实体呈现为REST,如下所示:

@RepositoryRestResource(excerptProjection = UserSummaryProjection.class)
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}

然后调用

curl -X GET https://localhost:8080/api/v1/users 

但是没有调用拦截器。

因为 REST 资源是使用 @RepositoryRestController 管理 Spring Data Rest 的,所以不会调用拦截器。但是,如果我使用 @RestController 编写 REST 资源,它将起作用。

如何使拦截器与 @RepositoryRestController 一起工作?

【问题讨论】:

  • 你试过用@Component注解TestInterceptor吗?
  • 刚试过,一样的
  • 如果TestInterceptor被容器扫描和管理,那么你应该注入它而不是new TestInterceptor()。它是这样工作的吗? @Autowired TestInterceptor testInterceptor; 和 registry.addInterceptor(testInterceptor).addPathPatterns("/api/**");
  • 刚试过自动接线,同样的事情
  • 确保正在创建 testinterceptor bean 并将其注入到配置 bean 中?在registry.addInterceptor...、assert testInterceptor != null; 行之前?

标签: spring spring-boot spring-mvc spring-security spring-data-rest


【解决方案1】:

我得到了它的工作(在/ 上下文路径和一个简单的User 类,spring-boot v2.4.2)与以下配置/spring-boot 应用程序:

...
import org.springframework.web.servlet.handler.MappedInterceptor
...    

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
       
    @Bean
    public org.springframework.web.servlet.handler.MappedInterceptor myInterceptor() {
        return new MappedInterceptor(
                new String[]{"/users/**"},  // null => maps to any repository/path
                new MyInterceptorImpl()
        );
    }

    private class MyInterceptorImpl implements HandlerInterceptor  {
         @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
            return true;
        }

        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
        }

        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
           System.out.println("afterCompletion");
        }
    }
}

我用了一个简化的:

@RepositoryRestResource
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> { }

【讨论】:

  • 我不想显得粗鲁,但你至少应该通过引用它来承认这个解决方案的原作者......你甚至在你的代码中因为混淆了错误的注释我在上面的评论中链接了两个答案:stackoverflow.com/questions/66176504/…
【解决方案2】:

您必须将 TestInterceptor 添加为 bean 并使用 @Autowired 对其进行注释,只需添加这些更改即可将拦截器注册到拦截器注册表中:

@Configuration
@SpringBootApplication
public class DemoApplication extends WebMvcConfigurerAdapter {
    @Autowired
    private TestInterceptor testInterceptor;
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(testInterceptor).addPathPatterns("/api/**");
    }

处理程序拦截器:

@Component
public class TestInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(TestInterceptor.class);
        @Override
        public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {
            System.out.println("afterCompletion");
            long startTime = Instant.now().toEpochMilli();
            logger.info("Request URL::" + arg0.getRequestURL().toString() +
                    ":: Start Time=" + Instant.now());
            arg0.setAttribute("startTime", startTime);
        }
        @Override
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {
            System.out.println("postHandle");
        }
        @Override
        public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
            System.out.println("preHandle");
            return true;
        }
}

作为示例,我已将“/api/”更改为“/”,此处的日志示例如下:

2021-02-13 00:36:31.075  INFO 14340 --- [on(2)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 22 ms
preHandle
postHandle
afterCompletion
2021-02-13 00:36:35.300  INFO 14340 --- [nio-8080-exec-1] com.example.demo.TestInterceptor         : Request URL::http://localhost:8080/time:: Start Time=2021-02-12T22:36:35.289832Z

【讨论】:

    猜你喜欢
    • 2019-08-03
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2014-03-10
    • 2023-03-31
    • 2023-03-17
    • 1970-01-01
    相关资源
    最近更新 更多