Springboot中的响应拦截器
1.标题
日常项目开发中,有时候会对响应结果进行处理,比如返回枚举字段时的名称,此文章用于记录响应拦截器在实战项目中的使用
2 工具类
2.1 自定义注解
/**
* 注解使用在返回Vo对象中的枚举字段
*/
@Target(ElementType.FIELD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumsMapper {
/**
* 目标字段
*/
public String targetField() default "";
}
2.2 响应拦截器
/**
* 枚举类型返回字段处理
*
*/
@Slf4j
@RestControllerAdvice
// 实现ResponseBodyAdvice接口,传入需要拦截的返回封装对象
public class EnumsMapperHandlerAdvice implements ResponseBodyAdvice<ResponseMessage> {
/**
* 判断拦截的方法返回对象是否包含 封装的返回对象
* @param returnType
* @param converterType
* @return
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
if (returnType.getMethod() == null) {
return false;
}
return ResponseMessage.class.isAssignableFrom(returnType.getMethod().getReturnType());
}
/**
* 判断返回的对象中的data数据 Vo对象是否实现Vo类,分页对象是否实现PageBean,列表数据是否实现List
* @param body
* @param returnType
* @param selectedContentType
* @param selectedConverterType
* @param request
* @param response
* @return
*/
@Override
public ResponseMessage beforeBodyWrite(ResponseMessage body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
Object data = body.getData();
if (data instanceof Vo) {
mapEnum(data);
} else if (data instanceof PageBean) {
mapEnums(((PageBean) data).getDatas());
} else if (data instanceof List) {
mapEnums((List) data);
}
return body;
}
private void mapEnums(List data) {
if (data != null) {
data.forEach(this::mapEnum);
}
}
private void mapEnum(Object data) {
if (data != null) {
processFields(data.getClass(), data);
}
}
private void processFields(Class clazz, Object data) {
// 递归处理父类
Class superClass = clazz.getSuperclass();
if (!superClass.equals(Object.class)) {
processFields(superClass, data);
}
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 判断对象中是否存在自定义的注解 EnumsMapper
EnumsMapper mapper = field.getAnnotation(EnumsMapper.class);
if (mapper == null) {
continue;
}
// 对象中必须存在枚举字段 对应的返回枚举名称为枚举字段名+Name
String targetFieldName = mapper.targetField();
if (StringUtils.isEmpty(targetFieldName)) {
targetFieldName = field.getName() + "Name";
}
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
Object fieldValue = field.get(data);
if (fieldValue instanceof EnumDictionarySupport) {
Field targetField = clazz.getDeclaredField(targetFieldName);
if (!targetField.isAccessible()) {
targetField.setAccessible(true);
}
targetField.set(data, ((EnumDictionarySupport) fieldValue).getName());
}
} catch (IllegalAccessException | NoSuchFieldException e) {
log.error("enum field map failed: {}", e.getMessage());
}
}
}
}