SpringBoot使用RequestBodyAdvice進行統一參數處理

在實際項目中 , 往往需要對請求參數做一些統一的操作 , 例如參數的過濾 , 字符的編碼 , 第三方的解密等等 , Spring提供了RequestBodyAdvice一個全局的解決方案 , 免去了我們在Controller處理的繁瑣 . 

RequestBodyAdvice僅對使用了@RqestBody註解的生效 , 因爲它原理上還是AOP , 所以GET方法是不會操作的.

package com.xbz.common.web;

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
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;

/**
 * @title 全局請求參數處理類
 * @author Xingbz
 * @createDate 2019-8-2
 */
@ControllerAdvice(basePackages = "com.xbz.controller")//此處設置需要當前Advice執行的域 , 省略默認全局生效
public class GlobalRequestBodyAdvice implements RequestBodyAdvice {


    /** 此處如果返回false , 則不執行當前Advice的業務 */
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
//        return methodParameter.getMethod().isAnnotationPresent(XXApiReq.class);
        return false;
    }

    /**
     * @title 讀取參數前執行
     * @description 在此做些編碼 / 解密 / 封裝參數爲對象的操作
     *
     *  */
    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        return new XHttpInputMessage(inputMessage, "UTF-8");
    }

    /**
     * @title 讀取參數後執行
     * @author Xingbz
     */
    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return inputMessage;
    }

    /**
     * @title 無請求時的處理
     */
    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }
}

//這裏實現了HttpInputMessage 封裝一個自己的HttpInputMessage
class XHttpInputMessage implements HttpInputMessage {
    private HttpHeaders headers;
    private InputStream body;

    public XHttpInputMessage(HttpInputMessage httpInputMessage, String encode) throws IOException {
        this.headers = httpInputMessage.getHeaders();
        this.body = encode(httpInputMessage.getBody(), encode);
    }

    private InputStream encode(InputStream body, String encode) {
        //省略對流進行編碼的操作
        return body;
    }

    @Override
    public InputStream getBody() {
        return body;
    }

    @Override
    public HttpHeaders getHeaders() {
        return null;
    }
}

Spring默認提供了接口的抽象實現類RequestBodyAdviceAdapter , 我們可以繼承這個類按需實現 , 讓代碼更簡潔一點

package org.springframework.web.servlet.mvc.method.annotation;

import java.io.IOException;
import java.lang.reflect.Type;

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;

public abstract class RequestBodyAdviceAdapter implements RequestBodyAdvice {

	@Override
	public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class<? extends HttpMessageConverter<?>> converterType)
			throws IOException {

		return inputMessage;
	}


	@Override
	public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {

		return body;
	}


	@Override
	@Nullable
	public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage,
			MethodParameter parameter, Type targetType,
			Class<? extends HttpMessageConverter<?>> converterType) {

		return body;
	}
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章