当前位置: 首页 > news >正文

个人学习系列 - 解决拦截器操作请求参数后台无法获取

由于项目需要使用拦截器对请求参数进行操作,可是请求流只能操作一次,导致后面方法不能再获取流了。

新建SpringBoot项目

1. 新建拦截器WebConfig.java

/*** @date: 2023/2/6 11:21* @author: zhouzhaodong* @description:*/
@Configuration
public class WebConfig implements WebMvcConfigurer {/*** 添加Web项目的拦截器*/@Overridepublic 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());}@Overridepublic BufferedReader getReader() {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic int read() {return bais.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic 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: 访问控制器方法前执行*/@Overridepublic 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: 访问控制器方法后执行*/@Overridepublic 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方法执行完成后执行,一般用于释放资源*/@Overridepublic 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: 测试*/
@RestController
public 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);@Overridepublic void init(FilterConfig filterConfig) {}@Overridepublic 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);}@Overridepublic void destroy() {}
}

9. 流处理后再进行测试

请求结果:
在这里插入图片描述
控制台输出:
在这里插入图片描述

解决啦!!!

源代码路径

https://github.com/zhouzhaodong/springboot/tree/master/springboot-interceptor

http://www.lryc.cn/news/1391.html

相关文章:

  • 【编程基础之Python】2、安装Python环境
  • Java开发 - 问君能有几多愁,Spring Boot瞅一瞅。
  • Office Server Document Converter Lib SDK Crack
  • Cubox是什么应用?如何将Cubox同步至Notion、语雀、在线文档中
  • 计算机网络-传输层
  • HTML-CSS-js教程
  • 【Nacos】Nacos配置中心客户端启动源码分析
  • 中国特色地流程管理系统,天翎让流程审批更简单
  • Python算法:DFS排列与组合算法(手写模板)
  • 拿来就用的Java海报生成器ImageCombiner(一)
  • 【C++】类和对象(二)
  • UDP协议
  • IT人的晋升之路——关于人际交往能力的培养
  • Docker进阶 - 8. docker network 网络模式之 container
  • 2年功能测试月薪9.5K,100多天自学自动化,跳槽涨薪4k后我的路还很长...
  • “数字孪生”:为什么要仿真嵌入式系统?
  • Java基础知识总结(上)
  • MySQL 2:MySQL约束
  • C4--Vivado添加列表中不存在的FLash器件2023-02-10
  • php代码审计
  • 接口测试入门,如何划分接口文档
  • 数据库学习第二天
  • NODE => CORS跨域资源共享学习
  • golang rabbitMQ 生产者复用channel以及生产者组分发策略
  • 掌握了这项技能的性能测试师,90%都升职加薪了
  • linux中crontab定时任务导致磁盘满和云监控未报警的的坑
  • vscode中安装python运行调试环境
  • 【微服务】微服务架构超强讲解,通俗易懂
  • 内核中的竞态产生的原因和解决方法
  • 【微服务】Elasticsearch文档索引库操作(二)