因为我的项目须要应用拦截器对申请参数进行操作,可是申请流只能操作一次,导致前面办法不能再获取流了。
新建SpringBoot我的项目
1. 新建拦截器WebConfig.java
/** * @date: 2023/2/6 11:21 * @author: zhouzhaodong * @description: */@Configurationpublic class WebConfig implements WebMvcConfigurer { /** * 增加Web我的项目的拦截器 */ @Override public void addInterceptors(InterceptorRegistry registry) { // 对所有拜访门路,都通过MyInterceptor类型的拦截器进行拦挡 // 放行登录页,登陆操作,动态资源 registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**") .excludePathPatterns("/", "/login", "/index.html", "/user/login", "/css/**", "/images/**", "/js/**", "/fonts/**"); }}
2. 获取申请参数并解决逻辑
/** * @date: 2023/2/6 12:46 * @author: zhouzhaodong * @description: 获取申请参数并解决 */public class RequestWrapper extends HttpServletRequestWrapper { private final Logger logger = LoggerFactory.getLogger(RequestWrapper.class); private final byte[] body; public RequestWrapper(HttpServletRequest request) { super(request); String sessionStream = getBodyString(request); body = sessionStream.getBytes(StandardCharsets.UTF_8); } public String getBodyString() { return new String(body, StandardCharsets.UTF_8); } /** * @date: 2023/2/6 12:46 * @author: zhouzhaodong * @description: 获取申请Body */ public String getBodyString(final ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = cloneInputStream(request.getInputStream()); reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } logger.info("获取body申请参数:" + sb); return sb.toString(); } /** * @date: 2023/2/6 12:46 * @author: zhouzhaodong * @description: 复制输出流 */ public InputStream cloneInputStream(ServletInputStream inputStream) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; try { while ((len = inputStream.read(buffer)) > -1) { byteArrayOutputStream.write(buffer, 0, len); } byteArrayOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } return new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); } @Override public BufferedReader getReader() { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() { return bais.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; }}
3. 实现HandlerInterceptor接口
/** * @date: 2023/2/6 11:19 * @author: zhouzhaodong * @description: 实现HandlerInterceptor接口 */public class MyInterceptor implements HandlerInterceptor { private final Logger logger = LoggerFactory.getLogger(MyInterceptor.class); /** * @date: 2023/2/6 11:19 * @author: zhouzhaodong * @description: 拜访控制器办法前执行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { logger.info("================进入拦截器======================"); logger.info(new Date() + "--preHandle:" + request.getRequestURL()); logger.info("***************************【RequestBeginning】***************************"); logger.info("----------------StartProcessingRequest----------------"); try { long currentTime = System.currentTimeMillis(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Date date = new Date(currentTime); logger.info("CurrentTime: {}", formatter.format(date)); logger.info("ResponseTime: {}", (System.currentTimeMillis() - currentTime) + "ms"); String requestUrl = request.getRequestURI(); logger.info("RequestURL: {} ", requestUrl); logger.info("GetMethod: {}", handler); String method = request.getMethod(); logger.info("Method: {}", method); //获取申请参数 RequestWrapper requestWrapper = new RequestWrapper(request); //这里getBodyString()办法无参数 logger.info("RequestBody: {}", requestWrapper.getBodyString()); } catch (Exception e) { logger.error("MVC业务解决-拦截器异样:", e); } logger.info("-------------------------End-------------------------"); return true; } /** * @date: 2023/2/6 12:46 * @author: zhouzhaodong * @description: 拜访控制器办法后执行 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { logger.info(new Date() + "--postHandle:" + request.getRequestURL()); } /** * @date: 2023/2/6 12:46 * @author: zhouzhaodong * @description: postHandle办法执行实现后执行,个别用于开释资源 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { logger.info(new Date() + "--afterCompletion:" + request.getRequestURL()); }}
4. application.yml
spring: main: # 当呈现雷同名字的类进行注册时,准许笼罩注册 allow-bean-definition-overriding: true
5. 启动类增加@ServletComponentScan注解
6. 新建TestController.java
/** * @date: 2023/2/6 12:24 * @author: zhouzhaodong * @description: 测试 */@RestControllerpublic class TestController { @PostMapping("/one/abc") public String abc(@RequestBody User user){ return user.getName(); }}
7. 不进行解决先测试看后果
申请后果:
控制台输入:
能够看出,流被读取了一次而后后盾就获取不到了。
8. 通过过滤器获取参数而后传到前面程序中
/** * @date: 2023/2/6 12:47 * @author: zhouzhaodong * @description: */@Component@WebFilter(urlPatterns = "/*", filterName = "channelFilter")public class ChannelFilter implements Filter { private final Logger logger = LoggerFactory.getLogger(ChannelFilter.class); @Override public void init(FilterConfig filterConfig) { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { logger.info("================进入过滤器======================"); // 避免流读取一次后就没有了, 所以须要将流持续写出去 HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest); filterChain.doFilter(requestWrapper, servletResponse); } @Override public void destroy() { }}
9. 流解决后再进行测试
申请后果:
控制台输入:
解决啦!!!
源代码门路
https://github.com/zhouzhaodo...