场景描述
结合案例说明场景体会会更深,现有一周课表信息查询场景,前端要求,一周中有课程时时返回指定的课程数据信息,当天没有课程时时需要返回空对象,对于空对象的接口协议如下截图:
有没有感觉这需求有点问题,懂得自懂.本着助人为乐的态度,决定要实现这个需求!
问题说明
这个过程中有两个问题需要处理,第一个问题就是接口返回课程信息数据需要支持两种数据类型;第二个问题接口返回空对象,注意不是对象中各属性为空或是null!
问题处理过程:
第一个问题实际上就是集合支持多种数据类型问题.说到这就不得不提一下泛型,常见的使用场景有以下几种:
1.不使用泛型,默认支持object类型.万物接口插入;
2.指定泛型,反射绕过泛型校验进行插入;
3.自定义公共抽象对象,子类根据业务进行具体实现.
首先说第1种,不指定泛型,即默认泛型为object类型,理论上支持任何数据类型.
private static void method1() {
// List<Object> list = new ArrayList<>();
List list = new ArrayList<>();
list.add("123");
list.add(234);
list.add(new Personal());
list.add(new Object());
System.out.println(list);// [123, 234, Personal{name='null', age='null'}, java.lang.Object@548c4f57]
}
第2种指定泛型,插入泛型之外的数据类型.泛型是用来保持数据类型统一.对于指定泛型类型中插入其他数据类型,编译器就会报错,此种处理方案就是使用反射跳过泛型校验.
private static void method2() {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
// list.add("3"); // integer类型不允许添加string类型,编译器报错
Class<? extends ArrayList> listClass = list.getClass();
try {
Method addMethod = listClass.getMethod("add", Object.class);
try {
addMethod.invoke(list,"中国红");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println(list); // [1, 2, 中国红]
}
第3种就是使用自定义抽象父类.也是本文使用的方式;具体做法是先定义抽象公共父类(空实现),作为集合泛型.然后定义两个子类.自定义课程表业务对象,自定义空课程表对象(仅用作空对象传参处理)
实际处理过程中延伸出一个问题.接口返回的是抽象父类,但在业务处理中需要从父类中获取具体的课程详情对象部分参数数据处理,需要调用子类方法.
这里直接说实际处理方法,首先定义一接口,接口中指定父类需要调用子类的哪些方法,抽象父类需要实现自定义接口.这样就保证父类间接访问到子类方法
,具体代码如下:
接口
public interface CourseTableVoInterface {
// 父类需要调用子类中用到的业务方法
String getStartTime();
String getCreateTime();
String getDataTime();
}
公共父类对象(接口返回最终参数对象)
@JsonInclude(JsonInclude.Include.ALWAYS)
public abstract class CourseTableContentVo implements CourseTableVoInterface {
}
课程表业务对象
public class CourseTableDetailContentVo extends CourseTableContentVo {
// 省略get/set以及部分属性
private String startTime;
private String createTime;
private String dataTime;
}
自定义空对象
public class CourseTableEmptyContentVo extends CourseTableContentVo {
@JsonInclude(JsonInclude.Include.NON_NULL)
@Override
public String getCourseName() {
return null;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@Override
public String getDataTime() {
return null;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@Override
public String getCreateTime() {
return null;
}
}
最后一个问题,将返回空对象的处理,这里需要使用jackson中JsonInclude相关注解,由于自定义空对象也需要实现接口方法,如果不做处理,返回的空对象为:
{
startTime: null
createTime: null
dataTime: null
}
所以为了拼装符合前端要求的空对象,所以需要将自定义空对象实现的方法上添加注解:@JsonInclude(JsonInclude.Include.NON_NULL)!