SpringBoot之在拦截器获取http请求的json数据公共参数的验证
Posted zengnansheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot之在拦截器获取http请求的json数据公共参数的验证相关的知识,希望对你有一定的参考价值。
HTTP请求中的是字符串数据
//字符串读取 void charReader(HttpServletRequest request) { BufferedReader br = request.getReader(); String str, wholeStr = ""; while((str = br.readLine()) != null){ wholeStr += str; } System.out.println(wholeStr); } //二进制读取 void binaryReader(HttpServletRequest request) { int len = request.getContentLength(); ServletInputStream iii = request.getInputStream(); byte[] buffer = new byte[len]; iii.read(buffer, 0, len); }
注意:
request.getInputStream(); request.getReader(); 和request.getParameter("key");
这三个函数中任何一个函数执行一次后(可正常读取body数据),之后再执行就无效了,比如在Controller里面就不能再调用了。
解决方法: 包装HttpServletRequest对象,缓存body数据,再次读取的时候将缓存的值写出
新建RequestWrapper
import lombok.extern.slf4j.Slf4j; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; import java.nio.charset.Charset; /** * @description 包装HttpServletRequest,目的是让其输入流可重复读 **/ @Slf4j public class RequestWrapper extends HttpServletRequestWrapper { /** * 存储body数据的容器 */ private final byte[] body; public RequestWrapper(HttpServletRequest request) throws IOException { super(request); // 将body数据存储起来 String bodyStr = getBodyString(request); body = bodyStr.getBytes(Charset.defaultCharset()); } /** * 获取请求Body * * @param request request * @return String */ public String getBodyString(final ServletRequest request) { try { return inputStream2String(request.getInputStream()); } catch (IOException e) { log.error("", e); throw new RuntimeException(e); } } /** * 获取请求Body * * @return String */ public String getBodyString() { final InputStream inputStream = new ByteArrayInputStream(body); return inputStream2String(inputStream); } /** * 将inputStream里的数据读取出来并转换成字符串 * * @param inputStream inputStream * @return String */ private String inputStream2String(InputStream inputStream) { StringBuilder sb = new StringBuilder(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset())); String line; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { log.error("", e); throw new RuntimeException(e); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { log.error("", e); } } } return sb.toString(); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return inputStream.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } }
新建RequestWrapperFilter
import lombok.extern.slf4j.Slf4j; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * @description RequestWrapperFilter **/ @Slf4j @WebFilter(filterName = "requestWrapperFilter", urlPatterns = "/*") public class RequestWrapperFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("RequestWrapperFilter初始化..."); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { ServletRequest requestWrapper = new RequestWrapper((HttpServletRequest) request); chain.doFilter(requestWrapper, response); } @Override public void destroy() { log.info("RequestWrapperFilter 销毁..."); } }
springboot启动类增加@ServletComponentScan注解
在拦截器就可以获取请求参数了
新建一个拦截器ApiInterceptor
@Slf4j public class ApiInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Gson gson = new GsonBuilder().serializeNulls().enableComplexMapKeySerialization().setDateFormat("yyyy-MM-dd HH:mm:ss").create(); String requestUrl = request.getServletPath(); String requestJson = new RequestWrapper(request).getBodyString(); Map parameterMap = gson.fromJson(requestJson, Map.class); log.info(" 请求地址为: " + requestUrl + " 请求参数为: " + requestJson); try { if (parameterMap.get("appId") == null || parameterMap.get("appId").toString() == "") { responseJson(response, gson.toJson(WrapMapper.wrap(Wrapper.ERROR_CODE, "appId 参数错误或不存在"))); return false; } return true; } catch (Exception e) { log.error(e.toString()); return false; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } private void responseJson(HttpServletResponse response, String json) throws Exception { PrintWriter writer = null; response.setCharacterEncoding("UTF-8"); response.setContentType("text/json; charset=utf-8"); try { log.info(json); writer = response.getWriter(); writer.print(json); } catch (IOException e) { log.error(e.toString()); } finally { if (writer != null) writer.close(); } } }
WebMvcConfig增加拦截器配置
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Bean public ApiInterceptor getApiInterceptor() { System.out.println("注入了 ApiInterceptor"); return new ApiInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { // 多个拦截器组成一个拦截器链 // addPathPatterns 用于添加拦截规则 // excludePathPatterns 排除拦截 String[] excludePaths = { "/login" }; registry.addInterceptor(getApiInterceptor()).addPathPatterns("/**").excludePathPatterns(Arrays.asList(excludePaths)); } }
以上是关于SpringBoot之在拦截器获取http请求的json数据公共参数的验证的主要内容,如果未能解决你的问题,请参考以下文章
springboot通过HttpServletRequestWrapper获取所有请求参数
SpringBoot 三种拦截http请求方式Filter,interceptor和aop