浅入java架构-Filter-篡改RequestBody
没干过几年的朋友,一定会问:为啥要篡改RequestBody?
这里笔者不想过多解释了,列举个场景:
eg:一个大型项目,分为N个模块去开发,分别在东北、华北、华东都有研发中心,其中系统登录、注册、认证等基础功能在东北地区研发,转账、汇款、理财等业务功能有我在华北地区研发,聊天、论坛等边缘辅助功能安排在华东地区研发。
为了达到模块低耦合的最佳效果,每个地区分别立项各自的服务器、应用、设计各自的UI页面,此时用户发起转账交易的时候,只能从cookie中拿到用户登录的唯一标识(userId),而转账服务会用到userId。
此时有三种方式处理userId传到服务中:
一、在每一个需要用到userId的控制器中get到userId,再塞到请求对象(RequestBody)中,(代码重复性太强)
二、定义一个baseControler类,由需要用到userId的控制器继承,其中实现一,(如果是做代码重构,工作量太大)
三、定义Filter,从cookie中获取userId后,在塞到请求对象(RequestBody)
毋庸置疑,选择第三种,这种系统级别的优化功能,跟业务层面没有关系,应该保持透明化
步骤一:web.xml中声明过滤器:NormFilter
RequestFilter
com.front.web.filter.RequestFilter
encoding
utf-8
RequestFilter
/web/*
步骤二:创建过滤器:RequestFilter
/**
* @ClassName RequestFilter
* @Description 篡改requestbody过滤器
* @author lisheng
* @Date 2016年6月14日 下午4:51:56
* @version 1.0.0
*/
public class RequestFilter implements Filter {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@SuppressWarnings("unchecked")
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 获取request
HttpServletRequest request = (HttpServletRequest) servletRequest;
if (request.getMethod().toUpperCase().equals("GET")) {
filterChain.doFilter(servletRequest, servletResponse);
} else if (request.getMethod().toUpperCase().equals("POST")) {
// 错误对象
ClientResponse
三、创建request转换类:HttpServletRequestWapper
/**
* @ClassName HttpServletRequestWapper
* @Description 重置requestbody
* @author lisheng
* @Date 2016年6月14日 下午4:50:30
* @version 1.0.0
*/
public class HttpServletRequestWapper extends HttpServletRequestWrapper {
private byte[] body;
private String bodyStr;
private HttpServletRequest request;
public HttpServletRequestWapper(HttpServletRequest request) throws UnsupportedEncodingException {
super(request);
String bodyString = HttpHelper.getBodyString(request);
body = StringUtils.isEmpty(bodyString) ? null : bodyString.getBytes("UTF-8");
this.request = request;
}
public void setBody(String body, BaseReq baseReq) throws UnsupportedEncodingException {
this.request.setAttribute("bodyStr", body);
this.request.setAttribute("baseReq", baseReq);
bodyStr = body;
this.body = body.getBytes("UTF-8");
}
public String getBodyStr() {
return bodyStr;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream(),getCharacterEncoding()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
public boolean isFinished() {
return false;
}
public boolean isReady() {
return false;
}
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
}
以上操作可以将request中的参数塞进Body中。