• 动态修改HttpServletRequest的Post请求参数


    需求场景:

      公司对APP调用的后台接口有个公用格式如下,外层包含了一些设备、版本、签名信息,主要的业务参数是在body里,外层信息都是在网关解决,验证签名后,在转发body到后台服务。

    {
        "appVersion":"1.0.0",
        "equipmentNo":"***********",
        "equipmentType":"ios",
        "mobile":"134*******",
        "registrationId":"*******",
        "sign":"**********",
        "token":"*************",
        "body":"{*****}"
    }

      目前开发一个新的APP后台,要先提供接口与移动端联调,网关开发延后,这时的服务端接口是不能直接拿到body的,也不方便在@RequestBody参数都包装上外层的字段。

    解决方法1:使用拦截器从HttpServletRequest获取POST数据,取出body数据,再替换HttpServletRequest的参数。

        public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=UTF-8");
            StringBuffer jb = new StringBuffer();
            String line = null;
            BufferedReader reader = null;
            PrintWriter out = null;
            try {
                reader = request.getReader();
                while ((line = reader.readLine()) != null){
                    jb.append(line);
                }
                JSONObject object = JSON.parseObject(jb.toString());
                String body = object.getString("body");
                out = response.getWriter();
                out.append(body);
            } catch (Exception e) {
                e.printStackTrace();
                if(reader != null){
                    reader.close();
                }
                if(out != null){
                    out.close();
                }
            }
        }

      这种方式可以提取POST传入的对象,并替换,但会报以下错误,所以还不建议使用。

    getReader() has already been called for this request

    解决方案二:使用AOP,拦截所有Controller

        @Around(value = "allController()")
        private void doAround(ProceedingJoinPoint joinPoint) {
            try {
                //所有参数
                Object[] args = joinPoint.getArgs();
                if(args != null && args.length > 0 ){
                    Object obj = args[0];
                    //记录@RequestBody注解的对象类型
                    Class<?> aClass = obj.getClass(); 
                    JSONObject object = JSON.parseObject(JSONUtil.toJson(obj));
                    //提取body,
                    String body = object.getString("body");
                    if(StringUtils.isNotBlank(body)){
                        //替换参数,并回写
                        body = body.replaceAll("\\","");
                        JSONObject bodyStr = JSON.parseObject(body);
                        args[0] = JSONUtil.fromJson(bodyStr.toJSONString(), aClass);
                        joinPoint.proceed(args);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }

      这个方式顺利解决当前的问题,不过因为使用AOP,Spring框架已经对接收到的参数进行了转换,是拿不到body的值的。所以在所有Controller接口的请求参数类,都加一个String body 属性,才能接收到body的值。我是定义了一个公共对象,只有一个String body属性,让参数类集成这个公共对象,以后不用再删除就好了。

  • 相关阅读:
    thinkphp3.2.3版本在windows本地apache环境运行正常,上传到centos服务器apache环境中出现:thinkphp 上传根目录不存在!请尝试手动创建:uploads/
    [POI2013]LUK-Triumphal arch
    【背包问题】
    2016 acm香港网络赛 A题. A+B Problem (FFT)
    tomcat部署项目的三种方式
    仿照ArrayList自己生成的MyList对象
    使用回调函数实现回文判断
    关于angularjs的model的一些问题
    关于使用Tomcat服务器出现413错误的解决办法(Request Entity Too Large)
    关于angularjs+typeahead的整合
  • 原文地址:https://www.cnblogs.com/huanshilang/p/11892087.html
Copyright © 2020-2023  润新知