使用OpenFeign远程调用时请求头处理报错问题
1. 错误信息
basic.result.exception.OtherException: feign error:系统异常:Content type 'multipart/form-data;boundary=--------------------------679449061975336133574827;charset=UTF-8' not supported.请联系管理员
at com.assembly.oauth.web.exception.auth.FeignErrorDecoder.decode(FeignErrorDecoder.java:26)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:149)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:78)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at com.sun.proxy.$Proxy191.addStationModelList(Unknown Source)
at com.assembly.dg.online.controller.TestController.importStation(TestController.java:326)
at com.assembly.dg.online.controller.TestController$$FastClassBySpringCGLIB$$1.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
at com.assembly.dg.online.controller.TestController$$EnhancerBySpringCGLIB$$1.importStation(<generated>)
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.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
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.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
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.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:117)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:106)
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:200)
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 com.assembly.oauth.web.authorization.interceptor.CrossFilter.doFilter(CrossFilter.java:57)
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.core.StandardContextValve.invoke(StandardContextValve.java:41002)
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.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
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:834)
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)
2. 使用场景以及问题出现的原因
在本地微服务中使用Spring MVC 上传文件时, 因为使用了MultipartFile 对象接受, 所以前端设置 请求头"Content-type"为multipart/form-data; ,这在本地 微服务中是没有问题的,
但是在处理请求的过程中, 使用了OpenFeign 远程调用了 其他的微服务保存信息, 就有问题了,
@RequestMapping(value = "importStation")
@NoAuthorization
public void importStation(MultipartFile file, HttpServletRequest request) throws IOException {
// ... 业务处理
// RPC远程调用 保存信息
dgRpcRemote.addStationModelList(stationModelList);
}
本项目中使用的是OpenFeign进行远程调用, 为了在调用时,可以携带调用方的请求头信息,例如token等等, 项目中自定义了一个拦截器进行处理:
@Component
public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
public FeignBasicAuthRequestInterceptor() {
}
public void apply(RequestTemplate requestTemplate) {
try {
//获取 ThreadLocal中的 本地Request对象
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
if (attributes == null) {
return;
}
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
String type;
String tenantCode;
if (headerNames != null) {
// 全盘拷贝过去
while(headerNames.hasMoreElements()) {
type = (String)headerNames.nextElement();
tenantCode = request.getHeader(type);
requestTemplate.header(type, new String[]{tenantCode});
}
}
type = TenantContextHolder.getAuthorizationType();
if (StringUtils.isNotBlank(type)) {
requestTemplate.header("tenantAuthorization", new String[]{type});
}
tenantCode = TenantContextHolder.getTenantCode();
if (StringUtils.isNotBlank(tenantCode)) {
requestTemplate.header("tenantCode", new String[]{tenantCode});
}
String tokenId = TenantContextHolder.getTokenId();
if (StringUtils.isNotBlank(tokenId)) {
requestTemplate.header("tenantToken", new String[]{tokenId});
}
requestTemplate.header("Content-Type", new String[]{"application/json;charset=UTF-8"});
} catch (Exception var8) {
var8.printStackTrace();
}
}
}
只需实现 接口RequestInterceptor 并被Spring扫描到即可,OpenFeign会自动调用,此类重写的 apply 方法中就 将本地的请求Request对象的请求头全部拷贝到 新的请求中用于调用,这样multipart/form-data; 也就拷贝了过去,但是在RPC 调用的接受方,确只是普通的 Rest 接口, 需要的是application/json ,所以就报了上述错误.
如果项目中在使用Feign进行远程调用,并有需要进行请求头传递的需求,可以参考此方式
3. 解决方式
因为在拦截器中获取的是 ThreadLocal 中保存的本地 请求Request 信息,所以 只需保证 在调用时不在请求所在线程即可:
new Thread(() ->dgRpcRemote.addStationModelList(stationModelList) ).start();
在调用时另启动一个线程进行调用即可, 如果有更好的方式,欢迎指教
使用OpenFeign远程调用时请求头处理报错问题的更多相关文章
- C#编译器优化那点事 c# 如果一个对象的值为null,那么它调用扩展方法时为甚么不报错 webAPI 控制器(Controller)太多怎么办? .NET MVC项目设置包含Areas中的页面为默认启动页 (五)Net Core使用静态文件 学习ASP.NET Core Razor 编程系列八——并发处理
C#编译器优化那点事 使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的.优化代码 ...
- java调用本地方法的时候报错 could not find the main class:xx.program will exit
如图所示,当在java调用本地方法的时候报错 我的解决办法是把dll文件放到System.out.println(System.getProperty("java.library.path& ...
- 安装php时,make步骤报错make: *** [ext/gd/gd.lo] Error 1
安装PHP时,make步骤报错make: *** [ext/gd/gd.lo] Error 1 /usr/local/src/LAMP+memcahed+catci/php-5.4.0/ext/gd/ ...
- vue项目初始化时npm run dev报错webpack-dev-server解决方法
vue项目初始化时npm run dev报错webpack-dev-server解决方法 原因:这是新版webpack存在的BUG,卸载现有的新版本webpack,装老版本就好webpack-dev- ...
- python踩坑系列之导入包时下划红线及报错“No module named”问题
python踩坑系列之导入包时下划红线及报错“No module named”问题 使用pycharm编写Python时,自己写了一个包(commontool),在同级另一个路径下(fileshand ...
- Python模块学习之xlrd 读取Excel时传入formatting_info=True报错:NotImplementedError: formatting_info=True not yet implemented
问题:xlrd读取Excel时传入 formatting_info=True 报错 之前我们使用读取xls文件的时候都是使用的xlrd库,但是这个库只能操作 .xls格式,对于后来的 .xlsx的版本 ...
- webRTC中回声消除(AEC)模块编译时aec_rdft.c文件报错:
webRTC中回声消除(AEC)模块编译时aec_rdft.c文件报错. 原因是: 局部变量ip跟全局变量冲突的问题,可以将局部变量重新命名一下,就可以通过编译了. aec_rdft.c修改以后文件代 ...
- OpenFeign远程调用原理
之前对OpenFeign 了解到只用在接口上面打个注解,然后就可以通过内部调用去调用远程地址.研究完Feign生成对象以及代理对象的作用过程之后发现这个过程用到了Spring的好多东西,在之后的过程中 ...
- 使用Java的URL/HttpURLConnection进行远程调用(POST请求)
利用Java的HttpURLConnection进行远程url请求(调用远程接口) 测试类:请求类型为json,以post方式请求,利用OutputStream写入数据 实体类: public cla ...
- RestTemplate远程调用POST请求:HTTP 415 Unsupported Media Type
这是本项目的接口 称为client @POST @Path("/{urlcode}") @Consumes(MediaTypes.JSON_UTF_8) @Produces(Med ...
随机推荐
- 修改微信PC通知声音
安装软件 下载地址如下 点我下载 提取码:1314 找到微信的位置 选择版本号文件夹进去 搜索关键词:WeChatResource.dll 拖拽到软件当中,选择如下分类 118是通知声音 119是来电 ...
- pycharm的docstring多了一行type
注释中多了一行:type 设置为Epytext PyCharm 2020.3.5 (Community Edition) def test(param1,param2,param3): "& ...
- 小白学k8s(4)使用k8s发布go应用
k8s发布go应用 前言 部署 镜像打包 编写yaml文件 使用ingress 什么是ingress呢 ingress与ingress-controller ingress 部署ingress 配置i ...
- 4.4 EAT Hook 挂钩技术
EAT(Export Address Table)用于修改动态链接库(DLL)中导出函数的调用.与IAT Hook不同,EAT Hook是在DLL自身中进行钩子操作,而不是修改应用程序的导入表.它的原 ...
- 遥感图像处理笔记之【FastAI Multi-label image classification】
遥感图像处理学习(4) 前言 遥感系列第4篇.遥感图像处理方向的学习者可以参考或者复刻 本文初编辑于2023年12月15日 2024年1月24日搬运至本人博客园平台 文章标题:FastAI Multi ...
- Docker生命周期,一张图秒懂docker
- Java 中,byte 数据类型的取值范围为什么是 -128 - 127 ?其它数值类型 都雷同
byte 的取值范围:-128 - 127 基本的数学计算方法,一个byte占8位,第一位为符号位,还有7位,7位能表示最大为:2^7 - 1 怎么来的呢:看如下数学计算 1111 111 = 2^0 ...
- 2023年多校联训NOIP层测试7+【LGR-149-Div.3】洛谷基础赛 #2 & qw Round -1
普及模拟3 \(T1\) 最大生成树 \(100pts\) 简化题意:给定一个 \(n(1 \le n \le 1 \times 10^5)\) 个点的完全图,给定各点的点权 \(a_i(1 \le ...
- JS leetcode 至少是其他数字的两倍的最大数 解答思路分析
壹 ❀ 引 刷leetcode的第二天,那么今天做的也是一道难度为简单的题目至少是其他数字的两倍的最大数,老规矩,先说说我的实现思路后,再来分析优质答案,原题如下: 在一个给定的数组nums中,总是存 ...
- python常用的搜索字符内容函数详解:re.findall/findfiter
区别findall返回listfinditer返回一个MatchObject类型的iterator详细举例介绍1.findall在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹 ...