最近项目转型使用SpringCloud框架下的微服务架构,各微服务之间使用Feign进行调用。期间,发现若被调用方法涉及到文件上传且仅存在单个文件时,一切正常,代码片段如下:
1@RequestMapping(value="/if/****/add",method=RequestMethod.POST,consumes=MediaType.MULTIPART_FORM_DATA_VALUE) 2JSONObjectadd(@RequestPart(value="file")MultipartFilefile);但若同时需要传递其他form-data数据时,则一直报错。
1@RequestMapping(value="/if/****",method=RequestMethod.POST,consumes=MediaType.MULTIPART_FORM_DATA_VALUE) 2Objectadd(@RequestParam(name="objectCode")StringobjectCode,@RequestPart(name="file")MultipartFilefile);报错信息为:
1org.springframework.web.multipart.support.MissingServletRequestPartException:Requiredrequestpartfileisnotpresent 2atorg.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:193) 3atorg.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109) 4atorg.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) 5atorg.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158) 6atorg.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) 7atorg.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) 8atorg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 9atorg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 10atorg.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 11atorg.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) 12atorg.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) 13atorg.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 14atorg.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) 15atjavax.servlet.http.HttpServlet.service(HttpServlet.java:661) 16atorg.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 17atjavax.servlet.http.HttpServlet.service(HttpServlet.java:742) 18atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 19atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 20atorg.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 21atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 22atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 23atorg.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) 24atorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 25atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 26atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)此时,feign日志为:
12018-12-2203:42:37.591DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]--->POSThttp://assembly-uiif/if/test1/public/t1?objectCode=test%3ASat+Dec+22+03%3A42%3A31+CST+2018HTTP/1.1 22018-12-2203:42:37.593DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]Content-Type:multipart/form-data;charset=UTF-8;boundary=167d24a8200 32018-12-2203:42:37.594DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]Content-Length:161 42018-12-2203:42:37.595DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1] 52018-12-2203:42:37.596DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]Binarydata 62018-12-2203:42:37.599DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]--->ENDHTTP(161-bytebody) 72018-12-2203:42:37.618INFO66057---[io-31023-exec-2]s.c.a.AnnotationConfigApplicationContext:Refreshingorg.springframework.context.annotation.AnnotationConfigApplicationContext@65669249:startupdate[SatDec2203:42:37CST2018];parent:org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@47df5041 82018-12-2203:42:37.777INFO66057---[io-31023-exec-2]f.a.AutowiredAnnotationBeanPostProcessor:JSR-330javax.inject.Injectannotationfoundandsupportedforautowiring 92018-12-2203:42:38.615INFO66057---[io-31023-exec-2]c.netflix.config.ChainedDynamicProperty:Flippingproperty:assembly-uiif.ribbon.ActiveConnectionsLimittouseNEXTproperty:niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit=2147483647 102018-12-2203:42:38.677INFO66057---[io-31023-exec-2]c.n.u.concurrent.ShutdownEnabledTimer:Shutdownhookinstalledfor:NFLoadBalancer-PingTimer-assembly-uiif 112018-12-2203:42:38.786INFO66057---[io-31023-exec-2]c.netflix.loadbalancer.BaseLoadBalancer:Client:assembly-uiifinstantiatedaLoadBalancer:DynamicServerListLoadBalancer:{NFLoadBalancer:name=assembly-uiif,currentlistofServers=[],Loadbalancerstats=Zonestats:{},Serverstats:[]}ServerList:null 122018-12-2203:42:38.796INFO66057---[io-31023-exec-2]c.n.l.DynamicServerListLoadBalancer:UsingserverListUpdaterPollingServerListUpdater 132018-12-2203:42:38.860INFO66057---[io-31023-exec-2]c.netflix.config.ChainedDynamicProperty:Flippingproperty:assembly-uiif.ribbon.ActiveConnectionsLimittouseNEXTproperty:niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit=2147483647 142018-12-2203:42:38.863INFO66057---[io-31023-exec-2]c.n.l.DynamicServerListLoadBalancer:DynamicServerListLoadBalancerforclientassembly-epsic-uiifinitialized:DynamicServerListLoadBalancer:{NFLoadBalancer:name=assembly-uiif,currentlistofServers=[192.168.43.31:20008],Loadbalancerstats=Zonestats:{defaultzone=[Zone:defaultzone;Instancecount:1;Activeconnectionscount:0;Circuitbreakertrippedcount:0;Activeconnectionsperserver:0.0;] 15},Serverstats:[[Server:192.168.43.31:20008;Zone:defaultZone;TotalRequests:0;Successiveconnectionfailure:0;Totalblackoutseconds:0;Lastconnectionmade:ThuJan0108:00:00CST1970;Firstconnectionmade:ThuJan0108:00:00CST1970;ActiveConnections:0;totalfailurecountinlast(1000)msecs:0;averageresptime:0.0;90percentileresptime:0.0;95percentileresptime:0.0;minresptime:0.0;maxresptime:0.0;stddevresptime:0.0] 16]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@114d8fc3 172018-12-2203:42:39.606DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]<---HTTP/1.1200(2006ms) 182018-12-2203:42:39.607DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]cache-control:no-cache,no-store,max-age=0,must-revalidate 192018-12-2203:42:39.608DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]content-type:application/json;charset=UTF-8 202018-12-2203:42:39.608DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]date:Fri,21Dec201819:42:39GMT 212018-12-2203:42:39.609DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]expires:0 222018-12-2203:42:39.610DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]pragma:no-cache 232018-12-2203:42:39.610DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]transfer-encoding:chunked 242018-12-2203:42:39.610DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]x-application-context:assembly-uiif:develop:20008 252018-12-2203:42:39.610DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]x-content-type-options:nosniff 262018-12-2203:42:39.613DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]x-frame-options:SAMEORIGIN 272018-12-2203:42:39.613DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]x-xss-protection:1;mode=block 282018-12-2203:42:39.613DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1] 292018-12-2203:42:39.615DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]{"head":{"orgId":0,"orgCode":"","vers":null,"reqId":null,"errorCode":1,"errorCodeI18n":"i18n.errorCode.1","errorMessage":"Requiredrequestpartfileisnotpresent","errorStack":"org.springframework.web.multipart.support.MissingServletRequestPartException:Requiredrequestpartfileisnotpresent\n\tatorg.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:193)\n\tatorg.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109)\n\tatorg.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)\n\tatorg.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)\n\tatorg.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)\n\tatorg.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)\n\tatorg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)\n\tatorg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)\n\tatorg.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)\n\tatorg.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)\n\tatorg.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)\n\tatorg.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)\n\tatorg.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)\n\tatjavax.servlet.http.HttpServlet.service(HttpServlet.java:661)\n\tatorg.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)\n\tatjavax.servlet.http.HttpServlet.service(HttpServlet.java:742)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatcom.egoonet.devtools.springstarter.iam.sso.config.web.MyFilterSecurityInterceptor.invoke(MyFilterSecurityInterceptor.java:61)\n\tatcom.egoonet.devtools.springstarter.iam.sso.config.web.MyFilterSecurityInterceptor.doFilter(MyFilterSecurityInterceptor.java:31)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)\n\tatorg.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)\n\tatorg.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatcom.***.web.MyFilterSecurityInterceptor.invoke(MyFilterSecurityInterceptor.java:61)\n\tatcom.***.web.MyFilterSecurityInterceptor.doFilter(MyFilterSecurityInterceptor.java:31)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:150)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\n\tatorg.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)\n\tatorg.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)\n\tatorg.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)\n\tatorg.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)\n\tatorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tatorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n\tatorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n\tatorg.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)\n\tatorg.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)\n\tatorg.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)\n\tatorg.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)\n\tatorg.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)\n\tatorg.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)\n\tatorg.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)\n\tatorg.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)\n\tatorg.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\n\tatorg.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\n\tatorg.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)\n\tatorg.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n\tatjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n\tatjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n\tatorg.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tatjava.lang.Thread.run(Thread.java:748)\n","userId":0,"appId":108},"info":{"now":"SatDec2203:42:39CST2018"}} 302018-12-2203:42:39.615DEBUG66057---[io-31023-exec-2]c.e.l.c.m.t.f.TestFileFeignController:[TestFileFeignController#t1]<---ENDHTTP(12082-bytebody)很显然,feign发送的报文不对,正常的报文应该是:
1POST/if/test1/public/t1HTTP/1.1 2Host:localhost:20008 3cache-control:no-cache 4Postman-Token:1c879cba-fdf3-4b9a-b1ef-e3d5af7be37e 5Content-Type:multipart/form-data;boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW 6 7Content-Disposition:form-data;name="objectCode" 8 9abcd 10 11Content-Disposition:form-data;name="file";filename="/Users/***/Downloads/03.jpg 12 13 14------WebKitFormBoundary7MA4YWxkTrZu0gW--ok,到此可知,问题出在feign发送报文时发送错误。
查阅feign源码,参考网络资料,实现一个自定义注解:
1/** 2*Feign代理方法上,与RequestPart一起组成多参数模式的注解 3*/ 4@Target(ElementType.PARAMETER) 5@Retention(RetentionPolicy.RUNTIME) 6@Documented 7public@interfaceRequestPartParam{ 8 9Stringname()default""; 10 11booleanrequired()defaulttrue; 12 13}实现自定义注解处理器:
1importfeign.MethodMetadata; 2importorg.springframework.cloud.netflix.feign.AnnotatedParameterProcessor; 3 4importjava.lang.annotation.Annotation; 5importjava.lang.reflect.Method; 6importjava.util.Map; 7 8importstaticfeign.Util.checkState; 9importstaticfeign.Util.emptyToNull; 10 11/** 12* 13*/ 14publicclassRequestPartParamParameterProcessorimplementsAnnotatedParameterProcessor{ 15 16privatestaticfinalClass<RequestPartParam>ANNOTATION=RequestPartParam.class; 17 18@Override 19publicClass<?extendsAnnotation>getAnnotationType(){ 20returnANNOTATION; 21} 22 23@Override 24publicbooleanprocessArgument(AnnotatedParameterContextcontext,Annotationannotation,Methodmethod){ 25intparameterIndex=context.getParameterIndex(); 26Class<?>parameterType=method.getParameterTypes()[parameterIndex]; 27MethodMetadatadata=context.getMethodMetadata(); 28 29if(Map.class.isAssignableFrom(parameterType)){ 30checkState(data.queryMapIndex()==null,"Querymapcanonlybepresentonce."); 31data.queryMapIndex(parameterIndex); 32 33returntrue; 34} 35 36RequestPartParamrequestPartParam=ANNOTATION.cast(annotation); 37Stringname=requestPartParam.name(); 38checkState(emptyToNull(name)!=null, 39"RequestPartParam.name()wasemptyonparameter%s", 40parameterIndex); 41context.setParameterName(name); 42 43data.formParams().add(name); 44 45returntrue; 46} 47 48}实现自定义的编码器:
1importfeign.RequestTemplate; 2importfeign.codec.EncodeException; 3importfeign.codec.Encoder; 4importfeign.form.FormEncoder; 5importfeign.form.MultipartFormContentProcessor; 6importfeign.form.spring.SpringManyMultipartFilesWriter; 7importfeign.form.spring.SpringSingleMultipartFileWriter; 8importlombok.val; 9importorg.springframework.web.multipart.MultipartFile; 10 11importjava.lang.reflect.ParameterizedType; 12importjava.lang.reflect.Type; 13importjava.util.HashSet; 14importjava.util.Map; 15importjava.util.Set; 16 17importstaticfeign.form.ContentType.MULTIPART; 18importstaticjava.util.Collections.singletonMap; 19 20/** 21* 22*/ 23publicclassFeignSpringFormEncoderextendsFormEncoder{ 24 25publicFeignSpringFormEncoder(){ 26this(newEncoder.Default()); 27} 28 29publicFeignSpringFormEncoder(Encoderdelegate){ 30super(delegate); 31 32valprocessor=(MultipartFormContentProcessor)getContentProcessor(MULTIPART); 33processor.addWriter(newSpringSingleMultipartFileWriter()); 34processor.addWriter(newSpringManyMultipartFilesWriter()); 35} 36 37@Override 38publicvoidencode(Objectobject,TypebodyType,RequestTemplatetemplate)throwsEncodeException{ 39if((bodyTypeinstanceofParameterizedType)&&((ParameterizedType)bodyType).getRawType().equals(Map.class)){ 40valdata=(Map<String,Object>)object; 41Set<String>nullSet=newHashSet<>(); 42for(Map.Entry<String,Object>entry:data.entrySet()){ 43if(entry.getValue()==null){ 44nullSet.add(entry.getKey()); 45} 46} 47for(Strings:nullSet){ 48data.remove(s); 49} 50super.encode(data,MAP_STRING_WILDCARD,template); 51return; 52}elseif(bodyType.equals(MultipartFile.class)){ 53valfile=(MultipartFile)object; 54valdata=singletonMap(file.getName(),object); 55super.encode(data,MAP_STRING_WILDCARD,template); 56return; 57}elseif(bodyType.equals(MultipartFile[].class)){ 58valfile=(MultipartFile[])object; 59if(file!=null){ 60valdata=singletonMap(file.length==0?"":file[0].getName(),object); 61super.encode(data,MAP_STRING_WILDCARD,template); 62return; 63} 64} 65super.encode(object,bodyType,template); 66} 67 68}定义bean:
1@Bean 2publicRequestPartParamParameterProcessorrequestPartParamParameterProcessor(){ 3returnnewRequestPartParamParameterProcessor(); 4} 5 6@Bean 7publicPathVariableParameterProcessorpathVariableParameterProcessor(){ 8returnnewPathVariableParameterProcessor(); 9} 10 11@Bean 12publicRequestParamParameterProcessorrequestParamParameterProcessor(){ 13returnnewRequestParamParameterProcessor(); 14} 15 16@Bean 17publicRequestHeaderParameterProcessorrequestHeaderParameterProcessor(){ 18returnnewRequestHeaderParameterProcessor(); 19}注意,参阅org.springframework.cloud.netflix.feign.support.SpringMvcContract中的代码可知,使用自定义注解处理器时,必须自行处理另外3个系统默认注解处理器。
至此,重新编译,运行,工作正常。问题解决。
本文内容总结:
原文链接:https://www.cnblogs.com/oilamp/p/10159741.html