有业务需要,我们需要动态确定接口返回的数据类型。如果json 、text、xml 等…
如果是固定类型可以采用 @RequestMapping 注解中的 produces 来实现
那如果需要不确定类型,那么就不添加这个属性。controller 的方法如下:
@RequestMapping(value = "version", method = RequestMethod.POST)
public String encVersion() {
}
这样我们方法的返回值是string 我们可以返回任意类型,但是响应头中的ContextType 是无法控制的。
好了前言先说到这里,接下来说说一个需求案例。
如果需要根据传入指定参数去判断该返回什么类型的数据。那么我们可以在controller 中默认返回json 然后去添加一个ResponseBodyAdvice的实现类
@ControllerAdvice
public class ApiResponseBody implements ResponseBodyAdvice<String> {
/**
* 判断哪些需要拦截
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public String beforeBodyWrite(String body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 然后使用SpringBoot RequestContextHolder 提供的方法来获取Request 对象,来获取请求参数判断需要返回的对应类型
String enc = StringUtil.convertNULL(CallbackController.getRequestAttributes().getAttribute(ApiResponseBody.ENC, SCOPE_REQUEST));
boolean encBool = "1".equals(enc);
if (encBool) {
// 修改响应头
response.getHeaders().setContentType(MediaType.parseMediaType(MediaType.APPLICATION_JSON_UTF8_VALUE));
} else {
response.getHeaders().setContentType(MediaType.parseMediaType(MediaType.TEXT_XML_VALUE));
// 修改需要返回的字符串
body = AESUtil.encode(body);
}
return body;
}
}
这样就可以实现拦截并指定响应头了,注意上面方法是提供大致思路。具体的还请根据业务调整
这里说几点:
1.可以直接在Controller 中返回对应类型 然后在beforeBodyWrite 方法中只需要修改响应头就好
2.为什么Controller 返回的是一个String 而不是一个对象再去转换。因为这里很容易受到HttpMessageConverter 接口的影响所以就采用String
当然关于这种需要有多种方法。我这里采用的这种