实际业务中需要在request header中获取数据。
然而header可以拿到数据,request.getParameterMap 却变成空的了,导致流程走不下去。
百度查了一下
通过request.getInputStream() 本以为这样问题就解决了,然而并没有紧接着就抛出了 Stream closed 。
查了一下问题是request.getInputStream() 只可以读一次。
解决方案如下:
首先封装一下HttpServletRequestWrapper
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public ParameterRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
下面是Interceptor的代码
public class CommonInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws IOException {
if (obj instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) obj;
Method method = handlerMethod.getMethod();
MacValidate annotation = method.getAnnotation(MacValidate.class);
if (annotation != null) {
MacUtil.validateMac(request,annotation.data());
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView modelAndView) {
log.info("view:{},url:{}", modelAndView, request.getRequestURL());
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
log.info("afterCompletion");
}
}
工具类 MacUtil
public class MacUtil {
public static void validateMac(HttpServletRequest request, String[] data) throws ParameterException, IOException {
// 获取token
String v = request.getHeader("token");
log.info(v);
if (StringUtils.isEmpty(v)) {
// 抛出异常
}
if (!StringUtils.isEmpty(v)) {
if (!checkData(v, request, data)) {
// 抛出异常
}
}
}
private static boolean checkData(String mac, HttpServletRequest request, String[] data) throws IOException {
String value = getValue(request, data);
log.info(value);
// do Something
}
private static String getValue(HttpServletRequest request, String[] data) throws IOException {
// 通过封装方法 获取到数据
// form data 方式
ParameterRequestWrapper myRequestWrapper = new ParameterRequestWrapper((HttpServletRequest) request);
String body = myRequestWrapper.getBody();
Map map = null;
if (StringUtils.isNotBlank(body)) {
map = (Map) JSON.parse(body);
} else {
// json
map = new HashMap();
Enumeration enu = request.getParameterNames();
// do Something
}
}
还有filter
@Slf4j
public class MacFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest) {
requestWrapper = new ParameterRequestWrapper((HttpServletRequest) request);
}
// 将request 传递下去
if (requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy() {
}
}
最后一步
@Configuration
public class FilterRegister {
@Bean
public FilterRegistrationBean macFilter() {
FilterRegistrationBean macFilter = new FilterRegistrationBean();
macFilter.setOrder(0);
macFilter.setFilter(new MacFilter());
xssFilter().addUrlPatterns("/*");
xssFilter().setEnabled(true);
return macFilter;
}
}
代码贴完了,大体逻辑就是这样的。
还有一种思路就是 通过 request.getInputStream() 获取到的数据再次给"setParameter"回去,有想法的朋友可以尝试一下。