转载:SpringBoot ResponseBodyAdvice 接口实现自定义返回数据类型(响应头)

3,681 阅读2分钟

原文链接:blog.csdn.net/jiangzeyin_…

有业务需要,我们需要动态确定接口返回的数据类型。如果json 、text、xml 等…

如果是固定类型可以采用 @RequestMapping 注解中的 produces 来实现

@Controller  
@RequestMapping(value = "/pets/{petId}", produces="MediaType.APPLICATION_JSON_VALUE"+";charset=utf-8")  
@ResponseBody  
public Pet getPet(@PathVariable String petId, Model model) {      
    // implementation omitted  
}  

那如果需要不确定类型,那么就不添加这个属性。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

原文链接:blog.csdn.net/jiangzeyin_…