1. 构建错误码
在 common 层中,设置错误码
2. 构建自定义异常
注意事项:
- 继承自 RuntimeException
- @EqualsAndHashCode(callSuper = true)// 使用父类的equals和hashcode方法,不使用lombok生成的
3. 构建统一结果返回
在 common 层
中,设置统一结果返回(CommonResult)
注意事项:
- 使用泛型的格式:
public static <T> CommonResult<T> error(Integer code, String msg) {
- Jackson 在进行序列化时,一般需要类有无参构造函数,并且属性要有对应的 getter 方法。
记得加上 @Data
默认的 lombok 依赖会出现错误:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>// 加上版本号
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>// 加上版本号
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
在 Java 中,方法返回类型前的<T>
不能省略,因为它是泛型方法的类型参数声明,用于告诉编译器:“这个方法使用一个名为T
的泛型类型”。如果省略<T>
,编译器会将T
视为一个实际的类(如java.lang.Object
的子类),而不是泛型类型参数,从而导致编译错误。
3.1. 返回类型前的<T> 为什么不能省略?
3.1.1. (1)语法规则
泛型方法的类型参数声明必须紧跟在方法修饰符(如public
、static
)之后,返回类型之前。省略<T>
会导致语法错误:java
// 错误:缺少类型参数声明,编译器无法识别T
public void printArray(T[] array) { ... } // 报错:Cannot resolve symbol 'T'
// 正确:声明泛型参数T
public <T> void printArray(T[] array) { ... }
3.1.2. (2)类型推断机制
- 若省略
<T>
,编译器会认为T
是一个已存在的具体类型(如类或接口),而非泛型类型参数。 - 例如,若代码中没有定义名为
T
的类,编译器会报错 “无法解析符号 'T'”。
3.2. 泛型类型擦除机制
在 Java 中,泛型类型参数T
在运行时必须被具体类型替换或擦除,否则会导致编译错误或运行时异常。
也就是说,运行时,不能存在还不知道替换成什么具体类型的T。
示例:
public static <T> T readValue(String content, T valueType) {
return JacksonUtil.tryParse(()->{
return JacksonUtil.getObjectMapper().readValue(content, valueType);
});
}
这段代码种的声明部分,存在运行时还未知的 T
,所以错误!
更正:
public static <T> T readValue(String content, Class<T> valueType) {
return JacksonUtil.tryParse(()->{
return JacksonUtil.getObjectMapper().readValue(content, valueType);
});
}
3.2.1. 为什么是Class<T>,而不是class<T>?
在 Java 中,Class 和 class 的区别源于大小写的不同,这实际上代表了两种完全不同的语法概念:
Class
:Java 中的类型字面量
Class 是 Java 中的一个内置类,用于表示类的运行时类型信息(RTTI)。
泛型形式:Class 中的 T 表示该 Class 对象所代表的实际类型。
class<T>
:Java 中的语法错误
class
是 Java 的关键字,用于定义类(如public class MyClass {}
)。- 泛型类定义:应使用
class MyClass<T> {}
,但不能单独作为类型使用。
Class 就像是 class 的类。
4. 构建序列化工具
工具有:
- fastjson
- jackson(选中)
- protobuf
可视化差、但是速度快。
演示 List 的:
/**
* List序列化
*/
List<CommonResult<String>> list = Arrays.asList(
CommonResult.success("success1"),
CommonResult.success("success2")
);
String s1;
try {
s1 = objectMapper.writeValueAsString(list);
System.out.println("List序列化:" + s1);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
/**
* List反序列化
*/
JavaType javaType = objectMapper.getTypeFactory()
.constructParametricType(List.class, CommonResult.class);
try {
List<CommonResult<String>> o = objectMapper.readValue(s1, javaType);
System.out.println(Arrays.toString(new List[]{o}));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
创建一个表示List<T>
的JavaType
对象,其中T
由parameterClasses
指定。
一直 try-catch,冗余,学习 spring 框架中是怎么处理的:
check.isAssignableFrom(ex.getClass())
作用:
判断 ex 是否是 check 的实例/子类