当前位置: 首页 > 知识库问答 >
问题:

在Springboot应用程序中使用Rest模板调用用@Async注释的方法

娄森
2023-03-14

我对@Async和Rest模板调用有问题;下面是我的主要应用程序类,带有一个任务执行器Bean和EnableAsync注释

@SpringBootApplication
@ComponentScan({"org.***"})
@EnableAspectJAutoProxy
@EnableAsync
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
@EnableFeignClients(basePackages = {"org.service.feign"})
public class MainApplication extends SpringBootServletInitializer {

    /**
     * <p>main.</p>
     *
     * @param args an array of {@link java.lang.String} objects.
     */
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }

    @Bean(name = "threadPoolTaskExecutor")
      public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix(“CustomLookup-");
        executor.initialize();
        return executor;
      }
    /**
     * Configure.
     *
     * @param application the application
     * @return the spring application builder
     */
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(MainApplication.class);
    }
    
    /**
     * <p>requestContextListener.</p>
     *
     * @return a {@link org.springframework.web.context.request.RequestContextListener} object.
     */
    @Bean
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
   }
}

这是我在Rest控制器中调用的带有异步注释的my测试服务:

@Service
public class TestService {

   

    @Async("threadPoolTaskExecutor")
    public ResponseEntity<Object> test()
            throws Exception{
        PagedRequest<SearchRequest> request = new PagedRequest<SearchRequest>();

        SearchRequest filters = new Request();

        filters.setCod(“abcdeg");

        request.setFilters(filters);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setInterceptors(Collections.singletonList(new RestInterceptor()));  // here I set a custom headers
        final HttpHeaders theJsonHeader = new HttpHeaders();
        theJsonHeader.setContentType(MediaType.APPLICATION_JSON);
        final MultiValueMap<String, Object> theMultipartRequest = new LinkedMultiValueMap<>();
        ObjectMapper objectMapper = new ObjectMapper();
        String someJsonString = objectMapper.writeValueAsString(request);
        theMultipartRequest.add("request", new HttpEntity<>(someJsonString, theJsonHeader));
        ResponseEntity<Object> response = null;
        final HttpEntity<PagedRequest<SearchRequest>> theHttpEntity = new HttpEntity<>(request, theJsonHeader);

        String path = “http://...”; //url removed for privacy

        response = restTemplate.postForEntity(path, theHttpEntity, Object.class);
        return response;
        
    }

}

此服务在rest模板上返回一个nullPointer;这是stacktrace

java.lang.NullPointerException: null
    at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:61) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:773) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:677) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:452) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.REL
public class RestInterceptor implements ClientHttpRequestInterceptor {

   
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null)
            return null;
        
        HttpServletRequest req = requestAttributes.getRequest();
        if (req == null || req.getHeader(PrevConstants.USER_KEY)==null || req.getHeader(PrevConstants.JWT_HEADER_NAME)==null)
            return null;


        String userKey = req.getHeader(PrevConstants.USER_KEY);

        String jwt = req.getHeader(PrevConstants.JWT_HEADER_NAME);
        
        if (jwt == null) {
            jwt = "custom jwt";
        }
       
        else if ( !jwt.startsWith("Bearer")) {                     jwt = "Bearer " + jwt;                 }

        request.getHeaders().set(PrevConstants.USER_KEY, userKey);
        request.getHeaders().set(PrevConstants.JWT_HEADER_NAME, jwt);         
        
        ClientHttpResponse response = execution.execute(request, body);
        return response;
    }
}

但是如果我删除@enableAsync和@Async,那么简单的Rest模板可以很好地工作。

当我传递HttpServlet请求时,Eclipse调试显示如下:

共有1个答案

江棋
2023-03-14

@Andy,对于第一个RequestAttributes和第二个HttpServletRequest,我直接通过了Rest控制器,但结果是相同的,即nullPointer。你有我可以看的片段吗?

@Async("threadPoolTaskExecutor")
public ResponseEntity<Object> test(HttpServletRequest req) throws Exception {
    // …
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setInterceptors(Collections.singletonList(new RestInterceptor(req)));
    // …
}

public class RestInterceptor implements ClientHttpRequestInterceptor {
private HttpServletRequest req;


public RestInterceptor(HttpServletRequest req){
    this.req=req;
}
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        
       
        
        HttpServletRequest req = this.req;
        if (req == null || req.getHeader(PrevConstants.USER_KEY)==null || req.getHeader(PrevConstants.JWT_HEADER_NAME)==null)
            return null;


        String userKey = req.getHeader(PrevConstants.USER_KEY);

        String jwt = req.getHeader(PrevConstants.JWT_HEADER_NAME);
        
        if (jwt == null) {
            jwt = "custom token";
        }
       
        else if ( !jwt.startsWith("Bearer")) {                     jwt = "Bearer " + jwt;                 }

        request.getHeaders().set(PrevConstants.USER_KEY, userKey);
        request.getHeaders().set(PrevConstants.JWT_HEADER_NAME, jwt);         
        
        ClientHttpResponse response = execution.execute(request, body);
        return response;
    }
 类似资料:
  • 我正在使用Spring4 AsyncRestTemplate调用外部REST API服务。 在该方法中,我注册来自REST API调用的ListenableFuture响应的回调。 除了单元测试,我不使用返回的ListenableFuture。回调将根据请求的成功或失败来处理我想采取的实际操作。 ExternalServiceImpl.class

  • 我在简单的Spring Boot应用程序上工作,并希望在它上使用并发线程。为了实现这一点,我在服务方法上使用@Async注释,但是当我添加@Async注释时,SpringDI崩溃。它的工作没有@Async在一个线程没有问题。为了调用服务方法,我创建了jUnit test。错误日志显示DI不起作用,也没有为服务类找到这样的bean。请帮助在Spring上使用@Async运行多个线程。 编辑我试图将测

  • 下面的@Retryable代码适用于直接调用方法的情况,但通过@Async annotated method调用Retryable方法会引发异常。有什么建议吗? 这是我的服务课 这是Junit测试类 这里是Spring Boot应用程序类 例外如下。请对此提出任何建议。 retryWithException-0

  • 我想把spring注释@Scheduled添加到spring bean中,并在另一个类中的方法中启动task。在spring引用中只有一种启动task的方法--Scheduling-Tasks。如何在没有@SpringBootApplication和Spring Boot运行器的情况下启动它。

  • 我是kubernetes的新手,需要在openshift平台上使用k8s confimap将springboot应用程序的属性文件外部化。我已将属性文件保存在git repo中,作为“greeter.message=Spring Bootmyapplication.properties已在库伯内特斯上挂载为卷!”并使用“oc create confimap myconfig--from-file=

  • 我有一个带有KafkaListener方法的Spring组件: 现在,我想测试这个方法。我想确保此方法正确接收消息。我尝试创建: 但我不知道接下来会发生什么。如何测试此方法?