定义Spring @Async并返回CompletableFuture <string>类型

时间:2019-05-20 14:58:40

标签: spring asynchronous web.xml completable-future

我在web.xml中声明了异步支持,并且 在setvlet-context.xml中设置任务配置。但是,我无法返回CompletableFuture类型。

如何使用异步注释和CompletableFuture?

我一直想知道怎么了?

web.xml显示如下:

  <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ASYNC</dispatcher>
    </filter-mapping>

<servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/config/servlet-context.xml</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>

        <async-supported>true</async-supported>

        <multipart-config />

    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


servlet-context.xml如下所示:

 <task:annotation-driven />
   <task:executor id="taskExecutor" pool-size="5-10" queue-capacity="25" />

    <mvc:annotation-driven>
        <mvc:message-converters>
            <ref bean="mappingJackson2HttpMessageConverter" />
        </mvc:message-converters>

        <mvc:async-support default-timeout="5000" task-executor="taskExecutor" />
    </mvc:annotation-driven>

    <context:component-scan base-package="com.mango.study" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
        <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController" />
    </context:component-scan>

异步注释如下所示:

   package com.mango.study.common.util;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Calendar;
import java.util.concurrent.CompletableFuture;

@Component
public class FileUtil {
    public static final String SAVE_PATH = "/home/mingyu/photo/";

    @Async
    public CompletableFuture<String> saveFile(MultipartFile multiFile) throws IOException {

        if (!multiFile.isEmpty()) {
            String fileName = multiFile.getOriginalFilename();
            String extName = fileName.substring(fileName.lastIndexOf("."));
            String newFilePath = SAVE_PATH + makeFilename(extName);

            File file = new File(newFilePath);

            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            multiFile.transferTo(file);
        }

        System.out.println("The End to upload file");

        return CompletableFuture.completedFuture("login/loginView");
    }

    public String makeFilename(String exetension) {
        Calendar cal = Calendar.getInstance();

        String year    = String.valueOf(cal.get(Calendar.YEAR));
        String month   = String.valueOf(cal.get(Calendar.MONTH));
        String day     = String.valueOf(cal.get(Calendar.DAY_OF_MONTH));
        String hour    = String.valueOf(cal.get(Calendar.HOUR_OF_DAY));
        String min     = String.valueOf(cal.get(Calendar.MINUTE));
        String sec     = String.valueOf(cal.get(Calendar.SECOND));
        String milSec  = String.valueOf(cal.get(Calendar.MILLISECOND));

        return year + month + day + hour + min + sec + milSec + exetension;
    }
}

返回CompletableFuture如下所示:

 @RequestMapping(value = "/login/loginView", method = RequestMethod.POST)
    public CompletableFuture<String> loginViewPost(@Validated(LoginUser.FreeAccount.class) LoginUser inputLoginUser,
                                           BindingResult result,
                                           RedirectAttributes redirectAttributes) throws IOException {

        redirectAttributes.addFlashAttribute(inputLoginUser);

        if (result.hasErrors()) {
            System.out.println("is it a password error? " + result.hasFieldErrors("password"));
        }

        MultipartFile file = inputLoginUser.getFile();

        return fileUtil.saveFile(file);
    }

错误消息如下所示:

 java.lang.IllegalStateException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml.
    at org.springframework.util.Assert.state(Assert.java:70)
    at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.startAsync(StandardServletAsyncWebRequest.java:109)
    at org.springframework.web.context.request.async.WebAsyncManager.startAsyncProcessing(WebAsyncManager.java:456)
    at org.springframework.web.context.request.async.WebAsyncManager.startDeferredResultProcessing(WebAsyncManager.java:434)
    at org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler.handleReturnValue(DeferredResultMethodReturnValueHandler.java:107)
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:113)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:122)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

20-May-2019 23:35:11.467 정보 [main] org.apache.catalina.core.ApplicationContext.log Destroying Spring FrameworkServlet 'dispatcher'
20-May-2019 23:35:11.477 경고 [main] org.apache.catalina.session.StandardSession.doWriteObject Cannot serialize session attribute [loginUser] for session [85939D636C7093B24F1944AB47CDBB8A]
 java.io.NotSerializableException: org.apache.catalina.core.ApplicationPart
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at org.apache.catalina.session.StandardSession.doWriteObject(StandardSession.java:1667)
    at org.apache.catalina.session.StandardSession.writeObjectData(StandardSession.java:1065)
    at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:315)
    at org.apache.catalina.session.StandardManager.unload(StandardManager.java:267)
    at org.apache.catalina.session.StandardManager.stopInternal(StandardManager.java:382)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:257)
    at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5327)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:257)
    at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1448)
    at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1437)
    at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
    at java.util.concurrent.FutureTask.run(FutureTask.java)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1004)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:257)
    at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1448)
    at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1437)
    at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
    at java.util.concurrent.FutureTask.run(FutureTask.java)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1004)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:257)
    at org.apache.catalina.core.StandardService.stopInternal(StandardService.java:474)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:257)
    at org.apache.catalina.core.StandardServer.stopInternal(StandardServer.java:822)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:257)
    at org.apache.catalina.startup.Catalina.stop(Catalina.java:768)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:730)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492)

20-May-2019 23:35:11.478 정보 [main] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext

0 个答案:

没有答案