我的需求是要将consumer的数据传到provinder层
我定义了2个拦截器
- consumer
RpcContext.getContext().setAttachment()
- provinder
RpcContext.getContext().getAttachment()
我使用的dubbo版本是2.5.3
放到服务器运行后,部分程序接口就报错了。我们观察到dubbo协议下,没有任何问题,但是在hessian协议下,provinder无法获取到数据。
官网似乎没有这个的说明,网上看到一篇文章
htchz.cc/1632594101.…
里讲到,dubbo在2.6.3下解决了这个问题,它将数据保存到headers里面,并贴上了源码,但是文章中并没有说清楚保存到headers后,provinder方如果获取。
于是我想,既然是http请求,我要想办法获取到request对象,然后就可以获取到request的headers,试过了Filter,Interceptor,Handler,想在provinder的Filter拦截器前面,获取到request,但是程序运行起来,发现拦截器根本拦截不到(可能是自己问题,我确实没找到办法)
于是只能翻看dubbo源码,看看源码里能不能自定义扩展下,找了半天没找到,正想吐槽这dubbo源码太垃圾了,没有提供扩展的时候, 发现了如下代码
这个类定义在HessianProtocol类中,由servlet调用,他获取到headers的数据,然后重新放入到Attachment中。
private class HessianHandler implements HttpHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
String uri = request.getRequestURI();
HessianSkeleton skeleton = skeletonMap.get(uri);
if (!request.getMethod().equalsIgnoreCase("POST")) {
response.setStatus(500);
} else {
RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort());
<!--将headers的数据取出来,重新放入到Attachment中 -->
Enumeration<String> enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
if (key.startsWith(Constants.DEFAULT_EXCHANGER)) {
RpcContext.getContext().setAttachment(key.substring(Constants.DEFAULT_EXCHANGER.length()),
request.getHeader(key));
}
}
try {
skeleton.invoke(request.getInputStream(), response.getOutputStream());
} catch (Throwable e) {
throw new ServletException(e);
}
}
}
}
系统在初始化的时候,调用addHttpHandler()方法设置了handlers的值,handlers里放的是不同的协议对应的hander,这里根据请求类型request.getLocalPort(),获取到响应的handler进行后续处理。
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 5766349180380479888L;
private static final Map<Integer, HttpHandler> handlers = new ConcurrentHashMap<Integer, HttpHandler>();
private static DispatcherServlet INSTANCE;
public DispatcherServlet() {
DispatcherServlet.INSTANCE = this;
}
public static void addHttpHandler(int port, HttpHandler processor) {
handlers.put(port, processor);
}
public static void removeHttpHandler(int port) {
handlers.remove(port);
}
public static DispatcherServlet getInstance() {
return INSTANCE;
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
<!-- 获取到对应的hander -->
HttpHandler handler = handlers.get(request.getLocalPort());
if (handler == null) {// service not found.
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Service not found.");
} else {
<!-- 调用【HessianHandler】执行具体的逻辑处理 -->
handler.handle(request, response);
}
}
}
我继续想,既然值放进去了,那为啥获取不到,最后通过打断点发现了问题,原来在设置头的手,将字母的大写变成了小写;(因为最开始是放到服务器试运行的,所以没有debug)
原来dubbo在2.6.3下面已经帮我们解决了这个问题,只是这个大写变小写真是有点坑, 为啥变小写,我也不知道,有知道的告诉我,谢谢啦!