zoukankan      html  css  js  c++  java
  • 动态修改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属性,让参数类集成这个公共对象,以后不用再删除就好了。

  • 相关阅读:
    BFS visit tree
    Kth Largest Element in an Array 解答
    Merge k Sorted Lists 解答
    Median of Two Sorted Arrays 解答
    Maximal Square 解答
    Best Time to Buy and Sell Stock III 解答
    Best Time to Buy and Sell Stock II 解答
    Best Time to Buy and Sell Stock 解答
    Triangle 解答
    Unique Binary Search Trees II 解答
  • 原文地址:https://www.cnblogs.com/huanshilang/p/11892087.html
Copyright © 2011-2022 走看看