spring boot拦截器中获取request post请求中的参数
最近有一个需要从拦截器中获取post请求的参数的需求,这里记录一下处理过程中出现的问题。
首先想到的就是request.getParameter(String )方法,但是这个方法只能在get请求中取到参数,post是不行的,后来想到了使用流的方式,调用request.getInputStream()获取流,然后从流中读取参数,如下代码所示:
- String body = "";
- StringBuilder stringBuilder = new StringBuilder();
- BufferedReader bufferedReader = null;
- InputStream inputStream = null;
- try {
- 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) {
- e.printStackTrace();
- } finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (bufferedReader != null) {
- try {
- bufferedReader.close();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- body = stringBuilder.toString();
代码中的body就是request中的参数,我这里传的是JSON数据:{"page": 1, "pageSize": 10},那么body就是:body = "{"page": 1, "pageSize": 10}",一个JSON字符串。这样是可以成功获取到post请求的body,但是,经过拦截器后,参数经过@RequestBody注解赋值给controller中的方法的时候,却抛出了一个这样的异常:
org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing
在网上查找资料后发现,request的输入流只能读取一次,那么这是为什么呢?下面是答案:
那是因为流对应的是数据,数据放在内存中,有的是部分放在内存中。read 一次标记一次当前位置(mark position),第二次read就从标记位置继续读(从内存中copy)数据。 所以这就是为什么读了一次第二次是空了。 怎么让它不为空呢?只要inputstream 中的pos 变成0就可以重写读取当前内存中的数据。javaAPI中有一个方法public void reset() 这个方法就是可以重置pos为起始位置,但是不是所有的IO读取流都可以调用该方法!ServletInputStream是不能调用reset方法,这就导致了只能调用一次getInputStream()。
那么有什么办法可以用户解决呢?上面这篇博客中提到了解决方案,就是重写HttpServletRequestWrapper把request保存下来,然后通过过滤器把保存下来的request再填充进去,这样就可以多次读取request了。步骤如下所示:
①写一个类,继承HttpServletRequestWrapper
- import javax.servlet.ReadListener;
- import javax.servlet.ServletInputStream;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
- import java.io.*;
- public class RequestWrapper extends HttpServletRequestWrapper {
- private final String body;
- public RequestWrapper(HttpServletRequest request) {
- super(request);
- StringBuilder stringBuilder = new StringBuilder();
- BufferedReader bufferedReader = null;
- InputStream inputStream = null;
- try {
- 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) {
- } finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (bufferedReader != null) {
- try {
- bufferedReader.close();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- 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;
- }
- }
②拦截器层面
- import com.alibaba.fastjson.JSON;
- import com.miniprogram.api.douyin.user.req.DyuserReq;
- import com.miniprogram.common.auth.VisitLimitCount;
- import com.miniprogram.common.cache.RedisCache;
- import com.miniprogram.common.config.InterceptorConfigMap;
- import com.miniprogram.common.config.InterceptorUrlConfig;
- import com.miniprogram.common.douyin.SearchEngineMapConstants;
- import com.miniprogram.common.response.Response;
- import com.miniprogram.common.session.*;
- import com.miniprogram.common.utils.DateUtil;
- import com.miniprogram.dao.common.UserLoginEntity.Users;
- import com.miniprogram.service.douyin.users.UsersService;
- import com.miniprogram.web.douyin.config.RequestWrapper;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.BeanUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import org.springframework.web.servlet.ModelAndView;
- import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.BufferedReader;
- import java.io.InputStreamReader;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- @Component("authSecurityInterceptor")
- public class AuthSecurityInterceptor extends HandlerInterceptorAdapter {
- private Logger logger = LoggerFactory.getLogger(AuthSecurityInterceptor.class);
- @Autowired
- private RedisCache redisCache;
- @Autowired
- private VisitLimitCount visitLimitCount;
- @Override
- public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
- try {
- RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest);
- String body = requestWrapper.getBody();
- System.out.println(body);
- return true;
- }catch (Exception e){
- logger.error("权限判断出错",e);
- }
- return false;
- }
- @Override
- public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
- }
- @Override
- public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
- }
- }
③过滤器Filter,用来把request传递下去
- import javax.servlet.*;
- import javax.servlet.annotation.WebFilter;
- import javax.servlet.http.HttpServletRequest;
- import java.io.IOException;
- @WebFilter(urlPatterns = "/*",filterName = "channelFilter")
- public class ChannelFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- }
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- ServletRequest requestWrapper = null;
- if(servletRequest instanceof HttpServletRequest) {
- requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
- }
- if(requestWrapper == null) {
- filterChain.doFilter(servletRequest, servletResponse);
- } else {
- filterChain.doFilter(requestWrapper, servletResponse);
- }
- }
- @Override
- public void destroy() {
- }
- }
④在启动类中注册拦截器
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.web.servlet.MultipartConfigFactory;
- import org.springframework.boot.web.servlet.ServletComponentScan;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- @SpringBootApplication
- // @ServletComponentScan //注册过滤器注解
- @Configuration
- public class WebApplication {
- public static void main(String[] args) {
- SpringApplication.run(WebApplication.class, args);
- }
- }
经测试,问题解决
spring boot拦截器中获取request post请求中的参数的更多相关文章
- spring boot拦截器中获取request post请求中的参数(转)
文章转自 https://www.jianshu.com/p/69c6fba08c92
- Spring boot拦截器的实现
Spring boot拦截器的实现 Spring boot自带HandlerInterceptor,可通过继承它来实现拦截功能,其的功能跟过滤器类似,但是提供更精细的的控制能力. 1.注册拦截器 @C ...
- 【spring boot】spring boot 拦截器
今日份代码: 1.定义拦截器 import com.alibaba.fastjson.JSON; import org.apache.commons.collections.CollectionUti ...
- spring boot拦截器配置
1.在spring boot配置文件application.properties中添加要拦截的链接 com.url.interceptor=/user/test 2.编写拦截器代码 ,创建UrlInt ...
- Spring boot 拦截器和过滤器
1. 过滤器 Filter介绍 Filter可以认为是Servlet的一种“加强版”,是对Servlet的扩展(既可以对请求进行预处理,又可以对处理结果进行后续处理.使用Filter完整的一般流程是: ...
- (22)Spring Boot 拦截器HandlerInterceptor【从零开始学Spring Boot】
上一篇对过滤器的定义做了说明,也比较简单.过滤器属于Servlet范畴的API,与Spring 没什么关系. Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Sprin ...
- spring boot拦截器WebMvcConfigurerAdapter,以及高版本的替换方案
Springboot中静态资源和拦截器处理(踩了坑) 背景: 在项目中我使用了自定义的Filter 这时候过滤了很多路径,当然对静态资源我是直接放过去的,但是,还是出现了静态资源没办法访问到spr ...
- spring boot拦截器
实现自定义拦截器只需要3步: 1.创建我们自己的拦截器类并实现 HandlerInterceptor 接口. 2.创建一个Java类继承WebMvcConfigurerAdapter,并重写 addI ...
- 九、 Spring Boot 拦截器
过滤器属于Servlet范畴的API,与spring 没什么关系. Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截 ...
随机推荐
- 安卓开发常用icon/png图样
平时开发当中会用到很多png图样,但是自己又不太会做,因此做好的办法就是直接在网上下载下来用了,这里给大家推荐一个比较好用的网站,免费的,有很多好的png可以直接下载下来使用. http://www. ...
- 启动VMware虚拟机时总是出现许可证到期提示怎么办?
不知道大家有没有遇到过这个问题,每次当你打开VMware虚拟机时它总是会提示许可证到期,需要注册,还会出现许多报红的代码,下面就让小编带大家解决一下吧~ VMware教程 如果Fusion本身无法启动 ...
- 微服务架构 - CentOS7离线部署docker
1.环境准备 系统环境为: CentOS Linux release 7.5.1804 (Core) 安装docker版本为: 17.12.0-ce 2.准备部署文件 在http://mirrors. ...
- 用node探究http缓存
用node搞web服务和直接用tomcat.Apache做服务器不太一样, 很多工作都需要自己做.缓存策略也要自己选择,虽然有像koa-static,express.static这些东西可以用来管理静 ...
- KnockoutJS-与服务端交互
几乎所有Web应用程序都要和服务器端交换数据,交换数据时最方便的就是使用JSON格式.Knockout可以实现很复杂的客户端交互,对于前后端交互使用的技术最为基本且常用的是Ajax,本次利用Ajax和 ...
- java中如何从一行数据中读取数据
目录 @(如何从一行数据中切割数据) 例如我要从一行学生信息中分割出学号.姓名.年龄.学历等等 ==主要使用split方法,split方法在API中定义如下:== public String[] sp ...
- JDBC mysql 相关内容笔记
解决乱码: url字符串加上?useUnicode=true&characterEncoding=utf-8; mysql数据库无法插入中文数据问题:将mysql数据库的编码改为utf-8; ...
- HIVE扩展GIS函数
按项目日益增长的gis数据量要求,需要在大数据集群中部署HIVE的扩展函数. Apache Hive是一个建立在Hadoop架构之上的数据仓库.它能够提供数据的精炼,查询和分析.([引 ...
- Sql Server 本地(客户端)连接服务器端操作
网有很多相关内容,我在此做记录和总结 1.主要是sql server 配置管理工具的配置 在此参考 https://www.cnblogs.com/yougmi/p/4616273.html(再次感谢 ...
- CVE-2019-0686|Microsoft Exchange特权提升漏洞补丁已发布
Microsoft Exchange Server中存在一个特权提升漏洞.成功利用此漏洞的攻击者可以获得与Exchange服务器的任何其他用户相同的权限.这可能允许攻击者执行诸如访问其他用户的邮箱之类 ...