RequestBodyAdvice和ResponseBodyAdvice

RequestBodyAdvice和ResponseBodyAdvice

这是spring 4.2新加的两个接口,这两个接口有些什么作用呢?先看看这两个接口

RequestBodyAdvice

public interface RequestBodyAdvice {

    boolean supports(MethodParameter methodParameter, Type targetType,
            Class<? extends HttpMessageConverter<?>> converterType);

    Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
            Type targetType, Class<? extends HttpMessageConverter<?>> converterType);

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

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

}

查看一下谁调用了这个接口的这些方法,可以看到AbstractMessageConverterMethodArgumentResolver的readWithMessageConverters()方法调用了这个接口的方法。

//代码片段
for (HttpMessageConverter<?> converter : this.messageConverters) {
            Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
            if (converter instanceof GenericHttpMessageConverter) {
                GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
                if (genericConverter.canRead(targetType, contextClass, contentType)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
                    }
                    if (inputMessage.getBody() != null) {
                        inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType);
                        body = genericConverter.read(targetType, contextClass, inputMessage);
                        body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType);
                    }
                    else {
                        body = null;
                        body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType);
                    }
                    break;
                }
            }

可以看到这接口的方法,主要是在HttpMessageConverter处理request body的前后做一些处理,和body为空的时候做处理。
而AbstractMessageConverterMethodArgumentResolver的实现类有
HttpEntityMethodProcessor(处理controller的方法参数是HttpEntity或RequestEntity的)、
RequestResponseBodyMethodProcessor(处理方法参数有@RequestBoyd的)、
RequestPartMethodArgumentResolver(处理方法参数是@RequestPart或MultipartFile,javax.servlet.http.Part)。

从这个可以看出,我们可以在使用这些HandlerMethodArgumentResolver的时候,我们能对request body进行前处理,和解析后处理。

RequestBodyAdvice怎么用

首先一个实现类,实现RequestBodyAdvice,后在类上加上注解@ControllerAdvice,比如有些请求的参数需要做加密处理,可以在此将json串解密处理,在处理

ResponseBodyAdvice

public interface ResponseBodyAdvice<T> {


boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);


T beforeBodyWrite(T body, MethodParameter returnType, MediaType selectedContentType,
        Class<? extends HttpMessageConverter<?>> selectedConverterType,
        ServerHttpRequest request, ServerHttpResponse response);

}

此可以对@ResponseBody的返回结果在输出到响应之前做处理

@ResponseBody

    <!-- 使用spring组件扫描 -->
    <context:component-scan base-package="com.game.ws,com.game.advice" />

package com.game.advice;

import javax.annotation.PostConstruct;

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

import com.alibaba.fastjson.JSON;
import com.game.dto.Result;
import com.gameqp.common.Utils;
import com.gameqp.common.Utils.MD5;

/**
 * 
 * @ClassName: MyResponseBodyAdvice
 * @Description: 对于@ResponseBody的返回结果加密
 * @author duhai
 * @date 2017年6月13日 下午2:31:36
 */
@ControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice<Result> {

	/**
	 * 加密串一
	 */
	private static String md5_keyone;
	/**
	 * 加密串二
	 */
	private static String md5_keytwo;

	@PostConstruct
	public void init() throws Exception {
		md5_keyone = Utils.PT.getProps("md5_keyone");
		md5_keytwo = Utils.PT.getProps("md5_keytwo");
	}

	/**
	 * 判断支持的类型
	 * 
	 * @param returnType
	 * @param converterType
	 * @return
	 * @see org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#supports(org.springframework.core.MethodParameter,
	 *      java.lang.Class)
	 */
	@Override
	public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
		return returnType.getMethod().getReturnType().isAssignableFrom(Result.class);
	}

	/**
	 * 对于结果进行加密
	 * 
	 * @param body
	 * @param returnType
	 * @param selectedContentType
	 * @param selectedConverterType
	 * @param request
	 * @param response
	 * @return
	 * @see org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#beforeBodyWrite(java.lang.Object,
	 *      org.springframework.core.MethodParameter,
	 *      org.springframework.http.MediaType, java.lang.Class,
	 *      org.springframework.http.server.ServerHttpRequest,
	 *      org.springframework.http.server.ServerHttpResponse)
	 */
	@Override
	public Result beforeBodyWrite(Result body, MethodParameter returnType,
			org.springframework.http.MediaType selectedContentType,
			Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
			ServerHttpResponse response) {
		String jsonString = JSON.toJSONString(body.getData());
		System.out.println(jsonString);
		// 第一次加密
		String data_encode_one = MD5.md5(md5_keyone + jsonString);
		// 第二次加密
		String data_encode_two = MD5.md5(data_encode_one + md5_keytwo);
		body.setToken(data_encode_two);
		return body;
	}

}



阅读更多
换一批

没有更多推荐了,返回首页