思路
1、自定义一个注解@ResponseResult用于在方法或者类上面标注,标识这个接口需要包装数据
2、拦截请求、判断此请求是否被@ResponseResult注解标注
3、实现接口ResponseBodyAdvice,然后需要用@ControllerAdvice注解激活,用于判断请求是否需要包装,如果需要,就把Controller中的返回值进行重写
具体实现
统一返回对象
自定义注解
三个注解作用请看下面
@Retention注解作用_m0_37840000的博客-优快云博客_retention
@Target:注解的作用目标_fengcai0123的专栏-优快云博客_@target注解作用
@Documented_诚的博客-优快云博客_documented
定义拦截器
主要就是利用反射API来获取此请求接口的全方法名,以及类名。然后判断如果此方法标注在类上,那么类中的所有接口都应该包装返回值。如果类上没有标注注解,再判断方法上是否标注了注解。如果标注了注解的话,就在请求中设置attribute,仅用作标记用,具体的还需要在ResponseBodyAdvice类中进行处理。
因为我们到时候注册拦截器的时候是拦截的所有的请求,然后再根据请求的类型来进行判断,handler instanceof HandlerMethod,如果是一个web接口方法,则走进if判断中。如果不是,直接放行请求。
包装返回值
此代码核心思想,就是获取此请求,是否需要返回值包装,设置一个属性标记。重写返回体
这是实现ResponseBodyAdvice
接口必须要重写的两个方法,supports方法用来判断是否需要包装返回值。如果需要就包装返回值,然后方法返回值true,就会执行包装的方法beforeBodyWrite()
,如果不需要包装就直接返回false,不用重写beforeBodyWrite()
beforeBodyWrite()包装返回值的核心代码,直接将原本的返回值封装进Result就可以。
这里的判断body instanceof Result的作用是,如果需要包装返回值的接口发生了异常,我们需要对异常进行处理。
这里我采用了全局异常处理@ControllerAdvice来处理发生的异常,然后将异常信息包装进Result对象。
注册拦截器
此处拦截所有请求,或者可以根据自己的业务需要来具体安排。
注意:当接口返回类型为string类型时,会报类型转换异常
此处我们需要在拦截器处再加一个转换器
@Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = converter.getObjectMapper(); // 时间格式化 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // 设置格式化内容 converter.setObjectMapper(objectMapper); converters.add(0, converter); }
本文参考如下