栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot分析使用RequestBodyAdvice&ResponseBodyAdvice接口

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot分析使用RequestBodyAdvice&ResponseBodyAdvice接口

RequestBodyAdvice

作用:controller入参使用了@RequestBody注解获取json数据,RequestBodyAdvice才能生效。很明显,原理是aop,在读取请求body数据前后进行额外的操作。

看看RequestBodyAdvice接口源码:

public interface RequestBodyAdvice {

	
	boolean supports(MethodParameter methodParameter, Type targetType,
			Class> converterType);

	
	HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class> converterType) throws IOException;

	
	Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class> converterType);

	
	@Nullable
	Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class> converterType);

}

Spring默认提供了接口的抽象实现类RequestBodyAdviceAdapter , 我们可以继承这个类按需实现 , 让代码更简洁一点:

public abstract class RequestBodyAdviceAdapter implements RequestBodyAdvice {

	
	@Override
	public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class> converterType)
			throws IOException {
		return inputMessage;
	}

	
	@Override
	public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class> converterType) {
		return body;
	}

	
	@Override
	@Nullable
	public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage,
			MethodParameter parameter, Type targetType,
			Class> converterType) {
		return body;
	}

}

例子:

@RestControllerAdvice(annotations = {RestController.class, Controller.class})
public class baseRequestValidationAdvice extends RequestBodyAdviceAdapter {
    
    @Resource
    private SysUseronlineMapper sysUserOnlineMapper;
    
    @Resource
    private TokenService tokenService;
    
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType,
                            Class> converterType) {
        return true;
    }
    
    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
                                Class> converterType) {
        // 基础请求入参对象,可以对token等基础参数进行校验
        baseRequest request = (baseRequest) body;
        if (body instanceof baseRequest && !(body instanceof Login/confirm/iDto) && !(body instanceof LoginIdentifyDto)) {
            if (StringUtils.isEmpty(request.getUserCode())) {
                throw new ServiceException(CommonConstant.ERROR, CommonConstant.ERROR_USERCODE_EMPTY);
            }
            if (StringUtils.isEmpty(request.getToken())) {
                throw new ServiceException(CommonConstant.ERROR, CommonConstant.ERROR_TOKEN_EMPTY);
            }
            SysUseronline sysUseronline = sysUserOnlineMapper.selectByPrimaryKey(request.getUserCode());
            if (null == sysUseronline || !request.getToken().equals(sysUserOnline.getToken())) {
                throw new ServiceException(CommonConstant.ERROR_TOKEN_INVALID,CommonConstant.ERROR_LOGOUT_ONLINE);
            }
            if (!(body instanceof LogOutDto) && StringUtils.isEmpty(request.getWarehouseCode())) {
                throw new ServiceException(CommonConstant.ERROR, CommonConstant.ERROR_WAREHOUSECODE_EMPTY);
            }
        }
        // 幂等性校验
        checkIdempotent(inputMessage, parameter);
        return body;
    }
    
    
    private void checkIdempotent(HttpInputMessage inputMessage, MethodParameter parameter){
        // 幂等性校验, 校验通过则放行, 校验失败则抛出异常, 并通过统一异常处理返回友好提示
        ApiIdempotent apiIdempotent = parameter.getMethod().getAnnotation(ApiIdempotent.class);
        if (apiIdempotent != null) {
            // 请求头中获得幂等性Id
            if(inputMessage.getHeaders().containsKey(CommonConstant.TRACTIONID)){
                // 校验等幂性,存到redis进行检验也行
                String tractionId = inputMessage.getHeaders().get(CommonConstant.TRACTIONID).get(0);
                tokenService.checkToken(tractionId);
            }else{
                throw new ServiceException(ResponseCode.ILLEGAL_ARGUMENT.getMsg());
            }
        }
    }
}
ResponseBodyAdvice

作用:controller出参返回json数据,ResponseBodyAdvice才能生效。很明显,原理都是aop,在请求返回body数据前进行额外的操作。

看看ResponseBodyAdvice接口源码:

public interface ResponseBodyAdvice {

	
	boolean supports(MethodParameter returnType, Class> converterType);

	
	@Nullable
	T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType,
			Class> selectedConverterType,
			ServerHttpRequest request, ServerHttpResponse response);

}

例子:

@RestControllerAdvice(annotations = {RestController.class, Controller.class})
public class WebControllerAdvice implements ResponseBodyAdvice {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private TokenService tokenService;

    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Result exceptionHandler(Exception e) {
        return Result.DefaultFailure(e.getMessage());
    }

    @Override
    public boolean supports(MethodParameter methodParameter, Class> aClass) {
        // controller方法上有幂等性注解ApiIdempotent才触发
        Method method = methodParameter.getMethod();
        return method.isAnnotationPresent(ApiIdempotent.class);
    }

    @Override
    public Result beforeBodyWrite(Result restResult, MethodParameter methodParameter, MediaType mediaType, Class> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        String token = "";
        if(serverHttpRequest.getHeaders().containsKey(CommonConstant.TRACTIONID)) {
            token = serverHttpRequest.getHeaders().get(CommonConstant.TRACTIONID).get(0);
        }
        if(CommonConstant.SUCCESS.equals(restResult.getCode()) || CommonConstant.PAR_SUCCESS.equals(restResult.getCode()) ){
            // 刷新token
            int result = tokenService.updateToken(token);
            logger.info("request success update token, result:{}", result);
        } else if(CommonConstant.PICKCODE01.equals(restResult.getCode())){
            int result = tokenService.updateTokenAndMsg(token, restResult.getMessage());
            logger.info("request success update token, result:{}", result);
        } else {
            int result = tokenService.deleteToken(token);
            logger.info("request error delete token, result:{}", result);
        }
        return restResult;
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/666352.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号