Request Body Advice and Response Body Advice handle input and output globally

Keywords: Java JSON Apache Spring

Usage scenarios

  1. All inputs in the project need to be filtered in front and back spaces
  2. Replace some special character input
  3. Decrypt some key fields
  4. Inject some parameters when requesting a method
  5. Return parameter unified processing, if the background returns empty, unified return success information
  6. Unified processing of special characters such as ID cards

code

The main purpose is to use the two interfaces of RequestBodyAdvice and ResponseBodyAdvice and a comment.
@ControllerAdvice

  • Request parameters to de-blank
package com.sanri.test.testmvc.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.Map;

/**
 * Remove the front and back spaces and special characters
 */
@Slf4j
@ControllerAdvice
public class CustomRequestBodyAdvice implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return body;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        return new CustomHttpInputMessage(httpInputMessage);
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return body;
    }

    class CustomHttpInputMessage implements HttpInputMessage{
        private HttpInputMessage origin;

        public CustomHttpInputMessage(HttpInputMessage httpInputMessage) {
            this.origin = httpInputMessage;
        }

        @Override
        public InputStream getBody() throws IOException {
            HttpHeaders headers = origin.getHeaders();
            InputStream body = origin.getBody();

            // Empty parameters, get requests, empty streams, non-application/json requests, no processing parameters
            MediaType contentType = headers.getContentType();
            if(contentType == null){return body;}
            if(!contentType.isCompatibleWith(MediaType.APPLICATION_JSON)){return body;}
            if(body == null){return body;}
            String params = IOUtils.toString(body, "utf-8");
            if(StringUtils.isBlank(params)){return body;}

            // Formal filtering of json parameters
            Object parse = JSON.parse(params);
            if (parse instanceof JSONArray) {
                JSONArray jsonArray = (JSONArray) parse;
                trimJsonArray(jsonArray);
            } else if (parse instanceof JSONObject) {
                trimJsonObject((JSONObject) parse);
            } else {
                log.error("Parameters do not support de-spaces:" + parse+ " contentType:"+contentType);
            }
            return IOUtils.toInputStream(JSON.toJSONString(parse, SerializerFeature.WriteMapNullValue), "UTF-8");
        }

        private void trimJsonObject(JSONObject jsonObject) {
            Iterator<Map.Entry<String, Object>> iterator = jsonObject.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Object> next = iterator.next();
                String key = next.getKey();
                Object value = next.getValue();
                if (value instanceof JSONArray) {
                    trimJsonArray((JSONArray) value);
                }else if(value instanceof JSONObject){
                    trimJsonObject((JSONObject) value);
                }else if(value instanceof  String){
                    String trimValue = StringUtils.trim(ObjectUtils.toString(value));
                    next.setValue(filterDangerString(trimValue));
                }
            }
        }

        private void trimJsonArray(JSONArray jsonArray) {
            for (int i = 0; i < jsonArray.size(); i++) {
                Object object = jsonArray.get(i);
                if(object instanceof JSONObject){
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    trimJsonObject(jsonObject);
                }else if(object instanceof  String){
                    String trimValue = StringUtils.trim(ObjectUtils.toString(object));
                    jsonArray.set(i,trimValue);
                }

            }
        }

        @Override
        public HttpHeaders getHeaders() {
            return origin.getHeaders();
        }

        private String filterDangerString(String value) {
            if(StringUtils.isBlank(value))return value;

            value = value.replaceAll(";", ";");
            value = value.replaceAll("'", "'");
            value = value.replaceAll("<", "<");
            value = value.replaceAll(">", ">");
            value = value.replaceAll("\\(", "(");
            value = value.replaceAll("\\)", ")");
            value = value.replaceAll("\\?", "?");
            return value;
        }

    }
}
  • Use ResponseBodyAdvice to handle return empty returns
package com.sanri.test.testmvc.config;

import com.alibaba.fastjson.JSONObject;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Executable;
import java.lang.reflect.Type;

/**
 * You can define an empty return to return the correct information, such as success information.
 */
@RestControllerAdvice
public class CustomResponseBodyAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        Executable executable = returnType.getExecutable();
        AnnotatedType annotatedReturnType = executable.getAnnotatedReturnType();
        Type type = annotatedReturnType.getType();
        return JSONObject.parseObject("{\"result\":0}");
    }
}

Project code

I've got an example code about the use of every tool in java, such as rabbitmq, mysql, mybatis, spring boot, spring mvc. It's convenient for beginners, and I can use it anytime, github address.
https://gitee.com/sanri/example

sanri-tools tool

Promotion of my gadget, very practical solution to some of the troubles in the project, welcome to github dot star, fork
https://gitee.com/sanri/sanri-tools-maven

Posted by RHolm on Mon, 07 Oct 2019 07:22:37 -0700