首页 > 编程语言 >java在filter中修改一个http请求出入参内容

java在filter中修改一个http请求出入参内容

时间:2023-02-21 16:33:58浏览次数:45  
标签:http return new filter IOException import Override java public


response保存了请求的返回信息,里面有个outputstream,你要返回给页面的流,都在这个地方保存. 
之前遇到一个问题,想把outputstream修改一下.因为这是个输出流,想要改这个里面的东西不是这么简单的. 
sun为我们提供了这么一个工具HttpServletResponseWrapper抽象类,利用这个类的子类把servletresponse包装一下,在过滤器中使用,就可以去除response的文件流,对其作出修改.给出一个实现: 

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;

/**
* ResponseWrapper
*
* @author wuweifeng
* @version 1.0
* @date 2021-08-16
*/
public class ResponseWrapper extends HttpServletResponseWrapper {
/**
* ByteArrayOutputStream
*/
private ByteArrayOutputStream buffer;
/**
* ServletOutputStream
*/
private ServletOutputStream out;
/**
* writer
*/
private PrintWriter writer;

/**
* ResponseWrapper
*/
public ResponseWrapper(HttpServletResponse resp) throws IOException {
super(resp);
buffer = new ByteArrayOutputStream();//真正存储数据的流
out = new WrapperOutputStream(buffer);
writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
}

//重载父类获取outputstream的方法
@Override
public ServletOutputStream getOutputStream() throws IOException {
return out;
}

//重载父类获取writer的方法
@Override
public PrintWriter getWriter() throws UnsupportedEncodingException {
return writer;
}

//重载父类获取flushBuffer的方法
@Override
public void flushBuffer() throws IOException {
if (out != null) {
out.flush();
}
if (writer != null) {
writer.flush();
}
}

@Override
public void reset() {
buffer.reset();
}

/**
* 获取response的字符串
*/
public String getContent() throws IOException {
flushBuffer();//将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据
return new String(buffer.toByteArray());
}

//内部类,对ServletOutputStream进行包装
private class WrapperOutputStream extends ServletOutputStream {
/**
* ByteArrayOutputStream
*/
private ByteArrayOutputStream bos;

/**
* WrapperOutputStream
*/
WrapperOutputStream(ByteArrayOutputStream stream) {
bos = stream;
}

@Override
public void write(int b) {
bos.write(b);
}

@Override
public boolean isReady() {
return false;
}

@Override
public void setWriteListener(WriteListener writeListener) {

}
}
}

然后在你的过滤器中这么使用: 

public class UserFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) servletResponse;

ResponseWrapper mResp = new ResponseWrapper(resp);// 包装响应对象 resp 并缓存响应数据
filterChain.doFilter(servletRequest, mResp);

String content = mResp.getContent();//response流的内容
System.out.println(content);


//此处可以对content做处理,然后再把content写回到输出流中
servletResponse.setContentLength(-1);

PrintWriter out = servletResponse.getWriter();

out.write(content);

out.flush();

out.close();
}
}

关于入参request的,如果只是key-value型的,对应客户端是form那种传过来的,在filter里直接获取没事。但如果是application/json型的,如果这个输入流被提前读取了,则后续真正的controller就取不到了,也需要做个包装类。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import static com.alibaba.fastjson.util.IOUtils.UTF8;

public class RequestWrapper extends HttpServletRequestWrapper {
/**
* log
*/
private static final Logger log = LoggerFactory.getLogger(RequestWrapper.class);
/**
* application/json型的入参
*/
private final String body;
/**
* key-value型所有的入参
*/
private Map<String, String[]> params = new HashMap<>();


public RequestWrapper(HttpServletRequest request) {
super(request);
this.params.putAll(request.getParameterMap());
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF8));
char[] charBuffer = new char[512];
int bytesRead;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
}
} catch (IOException ex) {
log.error("requestBody read error ignore,message:" + ex.getMessage());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error("requestBody inputStream close error,ignore");
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
log.error("requestBody bufferedReader close error,ignore");
}
}
}
body = stringBuilder.toString();
}

@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes(UTF8));
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(), UTF8));
}

public String getBody() {
return this.body;
}

@Override
public String getParameter(String name) {
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}

@Override
public String[] getParameterValues(String name) {
return params.get(name);
}


@Override
public Enumeration<String> getParameterNames() {
return Collections.enumeration(params.keySet());
}

}

标签:http,return,new,filter,IOException,import,Override,java,public
From: https://blog.51cto.com/u_13706148/6076714

相关文章

  • JAVA日志发展史,你知道多少?
    第一阶段2001年以前,Java是没有日志库的,打印日志全凭System.out和System.err缺点:   产生大量的IO操作同时在生产环境中无法合理的控制是否需要输出   输出的内......
  • Java零基础自学容易吗?看我们的学习技巧
    Java零基础自学容易吗?难度是不是很大呢?其实市面上还是有不少自学者的,在最开始的时候确实很难,毕竟大家是刚刚接触这个领域,入门时会看到听到很多奇奇怪怪的名词,当时大家的......
  • Java特性和优势
    简单性面向对象可移植性高性能分布式动态性多线程安全性健壮性......
  • Java三大版本
    WriteOnce、RunAnywhereJavaSE:标准版(桌面程序,控制台开发......JavaME:嵌入式开发(手机,小家电.......JavaEE:E企业级开发(web端,服务器开发...)......
  • 来一波骚操作,Java内存模型
    文章整理自博学谷狂野架构师什么是JMM并发编程领域的关键问题线程之间的通信线程的通信是指线程之间以何种机制来交换信息。在编程中,线程之间的通信机制有两种,共享......
  • tomcat java进程占用CPU资源过高
    top-Hppid-->根据jps得到的进程号(pid),查看java进程的所有线程,并且可以看到所有线程占用CPU的情况,-H用于显示某个进程的所有线程。printf"%x\n"9733-->将第2步查......
  • JavaScript 中字符串和数组的截取办法总结
    字符串substring形式:substring(index1,index2)不会改变原始字符串将小的参数作为开始位置start,大的作为结束位置stop包含start,但不包含stop如果只给一个参数表......
  • 关于Java锁机制的理解
    首先Java中为什么会使用锁:是为了解决Java共享内存模型带来的线程安全问题。思考:两个线程都有初始值为0的静态变量做自增,一个做自减,各做5000次,counter的值会为0嘛?public......
  • 使用java.util.Timer实现定时任务,详解Thread.sleep() in a loop, probably busy-waiti
    很多时候,我们需要定时任务实现一些诸如刷新,心跳,保活等功能。这些定时任务往往逻辑很简单,使用定时任务的框架(例如springboot@Scheduled)往往大材小用。下面是一个定时任......
  • java只有值传递
    Java中将实参传递给方法(或函数)的方式是值传递:如果参数是基本类型的话,很简单,传递的就是基本类型的字面量值的拷贝,会创建副本。如果参数是引用类型,传递的就是实参所引......