動態修改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屬性,讓參數類集成這個公共對象,以后不用再刪除就好了。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM