springboot 如何在请求进入controller之前改变body中的值
- 拦截器HandlerInterceptorAdapter
通过继承HandlerInterceptorAdapter
拦截器,可以重写preHandle
方法,但是在这个方法里直接对HttpServletRequest
中的body进行更改是无效的。HttpServletRequest
请求实际上并没有改变。
- HttpServletRequestWrapper 请求包装类
通过继承HttpServletRequestWrapper
可以重写自己的包装类。如:
public class MultiReadHttpServletRequestWrapper extends HttpServletRequestWrapper { private String tempBody; public MultiReadHttpServletRequestWrapper(HttpServletRequest request) { super(request); tempBody = AbstractRequestUtils.getRequestBody(request); } @Override public ServletInputStream getInputStream() { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(tempBody.getBytes()); return new ServletInputStream() { @Override public boolean isReady() { return false; } @Override public int readLine(byte[] b, int off, int len) throws IOException { return super.readLine(b, off, len); } @Override public boolean isFinished() { return false; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() { return byteArrayInputStream.read(); } }; } @Override public BufferedReader getReader() { return new BufferedReader(new InputStreamReader(this.getInputStream())); } public String getBody() { return this.tempBody; } public void setBody(String body) { this.tempBody = body; } }
在这里面定义了一个tempbody,可以防止出现流只能被读取一次而出现的流重读错误。
- 定义一个过滤器,以过滤相应请求,让它们使用包装过的HttpServletRequest。
@Slf4j public class RequestWrapperFilter implements Filter { @Override public void init(FilterConfig config) { log.info("==>RequestWrapperFilter启动"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException { MultiReadHttpServletRequestWrapper requestWrapper = new MultiReadHttpServletRequestWrapper((HttpServletRequest) request); chain.doFilter(requestWrapper, response); } @Override public void destroy() { } }
- 在WebMvcConfigurer中注册过滤器(这里也注册了最开始的拦截器)
@Configuration public class WebConfig implements WebMvcConfigurer { @Bean public WebInterceptor webInterceptor() { return new WebInterceptor(); } @Bean public FilterRegistrationBean addRequestWrapperFilter() { FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>(); registration.setFilter(new RequestWrapperFilter()); registration.setName("RequestWrapperFilter"); registration.addUrlPatterns("/interest/*"); registration.setOrder(1); return registration; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(webInterceptor()).addPathPatterns("/interest/**"); } }
- 在拦截器中对body中的值进行修改
@Slf4j public class WebInterceptor extends HandlerInterceptorAdapter { @Resource private IpVisitService ipVisitService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String ip = HttpUtils.getRemoteIP(request); log.info("!!!!!!!!!!!!!!!!currentIp:{}", ip); MultiReadHttpServletRequestWrapper requestWrapper = (MultiReadHttpServletRequestWrapper) request; String body = requestWrapper.getBody(); Preconditions.checkArgument(!StringUtils.isEmpty(body), "请求参数有误!"); BaseReq baseReq = JSON.parseObject(body, BaseReq.class); baseReq.setIp(ip); requestWrapper.setBody(JSON.toJSONString(baseReq)); return true; } }
经过实验,证明修改成功!
来源:https://www.cnblogs.com/fruitknife/p/12598480.html