SpringBoot修改请求参数和返回结果

注:本文基本上照抄自:https://www.codenong.com/cs107098749/,记录一下方便自己之后再找而已。

1.修改请求参数

1.1.自定义HttpServletRequest的包装类

Spring 中的 request.getInputStream()和 request.getReader()只能被读取一次,而@RequestBody注解底层也是通过流来请求数据,所以需要把拦截器中的数据流保存下来,让 controller 层可以读取的数据

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

/**
 * @author tianxc
 * @title: RequestWrapper
 * @projectName mycim-module
 * @description:
 * @date 2022/4/14 11:25
 */
public class RequestWrapper extends HttpServletRequestWrapper {
    private String body;

    public RequestWrapper(HttpServletRequest request) {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {

        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        body = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;

    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    public String getBody() {
        return this.body;
    }

    // 赋值给body字段
    public void setBody(String body) {
        this.body = body;
    }

1.2.自定义过滤器,将HttpServletRequest替换成自定义的包装类

image-20220414132035897

1.3.自定义拦截器

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mycim.framework.logging.Logger;
import com.mycim.framework.logging.LoggerFactory;
import com.mycim.webapp.wrapper.RequestWrapper;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author tianxc
 * @title: LoginInterceptor
 * @projectName mycim-module
 * @description:
 * @date 2022/4/14 10:47
 */
@Component
public class RequestParamInterceptor implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(handler);
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        pushRequest2Body(request, handlerMethod);

        return true;
    }

    private void pushRequest2Body(HttpServletRequest request, HandlerMethod handlerMethod) {
        try{
            MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
            if(ArrayUtils.isEmpty(methodParameters)) {
                return;
            }
            if(request instanceof RequestWrapper){
                RequestWrapper requestWrapper = (RequestWrapper)request;
                String body = requestWrapper.getBody();
                JSONObject param = JSONObject.parseObject(body).getJSONObject("body");
                requestWrapper.setBody(JSON.toJSONString(param));
            }
        }catch (Exception e){
            logger.warn("fill userInfo to request body Error ", e);
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

2.修改返回参数

2.1.自定义返回值拦截器

因为SpringBoot默认的ResponseBody的处理程序就是HandlerMethodReturnValueHandler,所以我们自己写的HandlerMethodReturnValueHandler通常无法生效,

非要使用HandlerMethodReturnValueHandler,那么只能替换掉默认的,

如果只是想对Controller的所有返回值进行封装,产生上面的效果,使用ResponseBodyAdvice会更加简单一些

import com.mycim.webapp.Response;
import com.mycim.webapp.ResponseMsgBuilder;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author tianxc
 * @title: InterceptResponse
 * @projectName mycim-module
 * @description:
 * @date 2022/4/14 11:14
 */
@ControllerAdvice
public class InterceptResponse implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof Response) {
            return body;
        }
        return ResponseMsgBuilder.buildSuccessResponse(body);
    }
}

原文:https://www.codenong.com/cs107098749/

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐