浅入java架构-Filter-篡改RequestBody

浅入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> baseResponseDto = ClientResponse.respFail();
            HttpServletRequestWapper requestWapper = new HttpServletRequestWapper(request);
            try {
                String jsonRequest = getJsonRequest(request, requestWapper);
                if (StringUtils.isNotEmpty(jsonRequest)) {
                    try {
                        Map requestMap = JsonUtil.json2Map(jsonRequest);
                        BaseReq baseReq = JsonUtil.json2Object(jsonRequest, BaseReq.class);
                        String userId = CookieUtils.getCookieValue(request, "userId", "");
                        requestMap.put("userId", userId);
                        baseReq.setUserId(userId);
                        requestWapper.setBody(JsonUtil.toJson(requestMap), baseReq);
                        filterChain.doFilter(requestWapper, servletResponse);
                        return;
                    } catch (Exception e) {
                        logger.error("doFilter 异常:", e);
                    }
                }
            } catch (Exception e) {
                logger.error("过滤器异常:", e);
            }
            servletResponse.setContentType("application/json; charset=utf-8");
            servletResponse.setCharacterEncoding("UTF-8");
            OutputStream out = servletResponse.getOutputStream();
            out.write(JsonUtil.toJson(baseResponseDto).getBytes("UTF-8"));
            out.flush();
        }
    }

    @Override
    public void destroy() {

    }
}

三、创建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中。

你可能感兴趣的:(java架构设计)