通过HttpServletResponseWrapper修改response输出流

在项目中遇到一个问题,需要对接口返回的数据进行加密给前端。项目中的controller一般都是返回一个实体form,重写的一个视图解析器继承ModelAndViewResolver,对返回的form转成json格式返回给前端。

视图解析器:

public class JsonModelAndViewResolver implements ModelAndViewResolver,
		InitializingBean, ApplicationContextAware {
	private String defaultContentType = "text/html";
	private Log log = LogFactory.getLog(super.getClass());
	private JsonSerialization jsonSerialization;
	private ApplicationContext applicationContext;

	public void afterPropertiesSet() throws Exception {
		if (this.jsonSerialization != null)
			return;
		this.jsonSerialization = JsonSerializationFactory.getInstance(this.applicationContext);
	}

	public void setApplicationContext(ApplicationContext paramApplicationContext)
			throws BeansException {
		this.applicationContext = paramApplicationContext;
	}

	//执行这个方法
	public ModelAndView resolveModelAndView(Method paramMethod,
			Class paramClass, Object paramObject,
			ExtendedModelMap paramExtendedModelMap,
			NativeWebRequest paramNativeWebRequest) {
		if (Rest.class.isAssignableFrom(paramClass)) {
			try {
				HttpServletResponse localHttpServletResponse = (HttpServletResponse) paramNativeWebRequest.getNativeResponse(HttpServletResponse.class);
				responseJson(paramObject, localHttpServletResponse);
			} catch (IOException localIOException) {
				throw new WebException(localIOException.getMessage(),
						localIOException);
			}
			return null;
		}
		return UNRESOLVED;
	}

	public void responseJson(Object paramObject,
			HttpServletResponse paramHttpServletResponse) throws IOException {
		if (!(StringUtils.hasText(paramHttpServletResponse.getContentType())))
			paramHttpServletResponse.setContentType(this.defaultContentType);
		String str = writeResult(paramObject);
		PrintWriter localPrintWriter = paramHttpServletResponse.getWriter();
		if (this.log.isInfoEnabled())
			this.log.info("Rest result=" + str);
		if ("{}".equals(str)) {
			this.log.info("image stream is not write ");
			return;
		}
		localPrintWriter.write(str);
		localPrintWriter.flush();
	}

	protected String writeResult(Object paramObject) {
		String str = null;
		if (paramObject == null) {
			str = "{}";
		} else if ((paramObject instanceof Number)
				|| (paramObject instanceof Boolean)) {
			str = "{\"resultCode\":\"" + paramObject.toString() + "\"}";
		} else if ((paramObject instanceof String)) {
			String result = (String) paramObject;
			str = result;
		} else {
			if (paramObject instanceof ModelAndView)
				paramObject = ((ModelAndView) paramObject).getModel();
			str = getJsonSerialization().toJSONString(paramObject);
		}
		return str;
	}

	public String getDefaultContentType() {
		return this.defaultContentType;
	}

	public void setDefaultContentType(String paramString) {
		this.defaultContentType = paramString;
	}

	public JsonSerialization getJsonSerialization() {
		return this.jsonSerialization;
	}

	public void setJsonSerialization(JsonSerialization paramJsonSerialization) {
		this.jsonSerialization = paramJsonSerialization;
	}
}

  本来考虑直接修改视图解析器,对返回json串加密,但发现项目中有些接口直接在controller中直接通过PrintWriter返回了参数,显然有这种方法是拦截不到的。

最后通过HttpServletResponseWrapper截取返回数据流加密重新输出给前端的方式。

代码参照如下:

ResponseWrapper:

package com.paic.egis.smts.toa.web.interceptor;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import com.paic.egis.smts.common.util.LoggerUtil;

public class ResponseWrapper extends HttpServletResponseWrapper {
	private PrintWriter cachedWriter;
	private CharArrayWriter bufferedWriter;

	public ResponseWrapper(HttpServletResponse response) throws IOException {
		super(response);
		bufferedWriter = new CharArrayWriter();
		cachedWriter = new PrintWriter(bufferedWriter);
	}

	public PrintWriter getWriter() throws IOException {
		return cachedWriter;
	}

	public String getResult() {
		byte[] bytes = bufferedWriter.toString().getBytes();
		try {
			return new String(bytes, "UTF-8");
		} catch (Exception e) {
			LoggerUtil.logError(this.getClass().getName(), "getResult", e);
			return "";
		}
	}

}

  过滤器如下:

package com.paic.egis.smts.toa.web.filter;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.paic.egis.smts.common.util.LoggerUtil;
import com.paic.egis.smts.common.util.PropertiesUtil;
import com.paic.egis.smts.pama.security.Base64Utils;
import com.paic.egis.smts.toa.web.interceptor.ResponseWrapper;
import com.paic.egis.smts.trusteesship.util.RSACoder;

public class ResponseWrapperFilter implements Filter {

	public void destroy() {

	}

	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {

		String version = req.getParameter("version");
		if(StringUtils.isEmpty(version)){

			chain.doFilter(req, resp);

		} else {

			HttpServletResponse response = (HttpServletResponse) resp;
			ResponseWrapper mr = new ResponseWrapper(response);

			chain.doFilter(req, mr);

			PrintWriter out = resp.getWriter();
			try {
				//取返回的json串
				String result = mr.getResult();
				System.out.println(result);
				//加密
				String encryptStr = encryptRSA(result);
				out.write(encryptStr);
			} catch (Exception e) {
				LoggerUtil.logError(this.getClass().getName(), "doFilter", e);
			} finally {
				out.flush();
				out.close();
			}
		}
	}

	@Override
	public void init(FilterConfig filterconfig) throws ServletException {

	}

	//rsa公钥加密
	public String encryptRSA(String content) throws Exception{
		String publicKeyStr = PropertiesUtil.getProperty("response.publicKey");
		byte[] encryptBytes = RSACoder.encrypt(content.getBytes("utf-8"), publicKeyStr,"public");
		return  Base64Utils.encode(encryptBytes);
	}
}

  

时间: 2025-01-02 20:01:14

通过HttpServletResponseWrapper修改response输出流的相关文章

测试调试-利用fiddler修改response返回结果

测试前端过程中,经常需要验证各种功能状态.不同数据层级等返回后的展示效果.一般会通过以下三种方式进行测试: 1.构造满足条件的测试数据:(耗时费力) 2.修改数据库:(前提需要了解数据库数据存储.沟通成本高) 3.通过网络代理截获返回的数据进行修改.(成本低.即时修改即时测试.不需要打扰后端修改数据库) 综合,第三种方式较方便且灵活.最近在用抓包工具fiddler,以下通过fiddler介绍如何修改response返回结果. 第一步:下载fiddler的最新版本: 运行fiddler之后测试要调

Fiddler脚本修改Response数据

Instroduction: Fiddler抓包工具,修改CustomRules.js脚本达到修改Http请求的Response中Body信息(如JSON串). 常用于在Server开发未完全Ready而前端或客户端开发需要Server数据时,修改请求的返回数据,达到Debug和测试的目的,较添加BreakPoint的方法更加便捷. Implementation:  目的: 本例Demo中会为JSON添加一个字段和修改一个字段,如下所示: 1 // 原JSON串 V1.0 2 { 3 "musi

直接通过Response输出流写文件,浏览器表现为下载文件

response.setContentType("application/x-download"); response.addHeader("Content-Disposition", "attachment;filename="+new String( "中文".getBytes("utf-8"), "ISO8859-1" )+"文件类型"); OutputStre

配置filter,修改response

在java中增加了过滤器filter,一般我们定义的filter都要继承filter接口从而实现dofilter方法,filter的配置,我们可以在web.xml中进行配置,配置如下: <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-na

Fiddler设置断点修改Request和Response

一.Fiddler中修改Request有两种方法: 点击Rules-> Automatic Breakpoint ->Before Requset (这种方法会中断所有的会话) 消除命令:  点击Rules-> AutomaticBreakpoint  ->Disabled 在命令行中输入命令: bpu www.baidu.com (这种方法只会中断www.baidu.com) 消除命令:  在命令行中输入命令 bpu 二.Fiddler中修改Response也有两种方法: 点击R

Response的使用入门

一.Servlet访问过程 response:是Servlet里一块区域,可以通过人为修改之后由tomcatMS引擎重新写入Http request :经过tomcatMS引擎封装的http请求体信息 名词说明: service(ServletRequest,ServletReponse)由来:在Servlet接口中的方法,目的是接收传递response和request 的参数 doGet(HttpServletRequest,HttpServletReponse)由来:doGet方法在Http

response和request详解

JavaEE:response响应和request请求 Web服务器接收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象. request和response对象既然代表请求和响应,那么我们要获取客户机提交过来的数据,只需要找request对象,就行了.要向客户机输出数据,只需要找response对象就行了. HttpServletRequest封装客户端相关信息,服务器Servlet程序可以通过request对象操作客户端信

SpringBoot中利用过滤器修改请求url地址

要求: 代码中配置的url路径为http://127.0.0.1/api/associates/queryAssociatesInfo 现在要求http://127.0.0.1/associates/queryAssociatesInfo也可以同样访问同一个conroller下面的method,并且要求参数全部跟随 代码: package com.shitou.huishi.framework.filter; import java.io.IOException; import javax.se

Request和Response详解

转自:http://zhidao.baidu.com/link?url=8BI0cjlcFdBSJKHTZlpo874eqtbTJoZfrh3miQgM_05RvSER8skPiBc1wSPZtXT8OGGCHfVXFAzAosa6E5HBl_ 内置对象request:请求对象request.getParameter("名字") 获得客户端输入的信息***************request.getParameterValues("名字") 获得客户端输入的一组信