问题:

这个是在Spring Cloud配置中心(Config Server)拉取配置文件时引起的报错。

公司Config Server使用的版本库是GitLab。在启动时会访问微服务配置的GitLab地址,正常的情况下在GitLab中需要配置Webhooks信息,系统访问GitLab后会对Webhooks配置地址进行回调处理,报错就发生在微服务解析回调信息时,报错内容如下:

Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse 
    error: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token; nested exception is 
    com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of
     `java.lang.String` out of START_OBJECT token at [Source: (PushbackInputStream); line: 1, column: 449]
     (through reference chain: java.util.LinkedHashMap["project"])

解决:

这个错误是因为GitLab11.10之后,使用Webhook返回响应JSON对象无法使用Jackson进行反序列化导致。

因此只需要在Spring Cloud配置中心(Config Server)中增加过滤器进行JSON数据序列化就可以了。

UrlFilter.java

package io.yzh.component.filter;

import java.io.BufferedReader;
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import io.yzh.component.wrapper.CustometRequestWrapper;

/**
 * @Function url过滤器
 */
@WebFilter(filterName = "urlFilter", urlPatterns = "/*")
@Order(1)
@Component
public class UrlFilter implements Filter {

	public static final Logger logger = LoggerFactory.getLogger(UrlFilter.class);

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		String url = new String(httpServletRequest.getRequestURI());
		// 只过滤/actuator/bus-refresh请求
		if (!url.endsWith("/bus-refresh")) {
			chain.doFilter(request, response);
			return;
		}
		CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);
		chain.doFilter(requestWrapper, response);
	}

	@Override
	public void destroy() {
	}

	/**
	 * 以char形式读取
	 * 
	 * @param request
	 * @return
	 */
	public static String readAsChars(HttpServletRequest request) {
		BufferedReader br = null;
		StringBuilder sb = new StringBuilder("");
		try {
			br = request.getReader();
			String str;
			while ((str = br.readLine()) != null) {
				sb.append(str);
			}
			br.close();
		} catch (IOException e) {
			logger.info(" --------- An exception occurred : " + e.getMessage() + " --------- ");
		} finally {
			if (null != br) {
				try {
					br.close();
				} catch (IOException e) {
					logger.info(" --------- An exception occurred : " + e.getMessage() + " --------- ");
				}
			}
		}
		return sb.toString();
	}
}

CustometRequestWrapper.java

package io.yzh.component.wrapper;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * @Function 自定义请求包装器
 */
public class CustometRequestWrapper extends HttpServletRequestWrapper {

	public CustometRequestWrapper(HttpServletRequest request) {
		super(request);
	}

	/**
	 * 以流输出
	 */
	@Override
	public ServletInputStream getInputStream() throws IOException {
		byte[] bytes = new byte[0];
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);

		return new ServletInputStream() {
			@Override
			public boolean isFinished() {
				return byteArrayInputStream.read() == -1 ? true : false;
			}

			@Override
			public boolean isReady() {
				return false;
			}

			@Override
			public void setReadListener(ReadListener readListener) {
			}

			@Override
			public int read() throws IOException {
				return byteArrayInputStream.read();
			}
		};
	}
}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐