Lottery lec3-cnblog

发布时间 2024-01-04 00:21:58作者: xyfyy

Lottery lec3

今天主要学习一下lottery抽象项目中,第三节中如何使用Dubbo跑通Rpc过程调用以及在这个过程中遇到的知识盲点(实在是刚开始学习Java,不懂的地方太多了)
Serializable接口
首先在创建Rpc的Request和Response对象时,必须将对象继承Serializable,这个可以理解(毕竟之前使用过brpc),因为在Rpc调用过程中,需要将Req和Response对象序列化为二进制发送给对端,那么需要实现特定的方法是很自然的..不过我尝试去implement Serializable接口,发现没有我需要去实现的方法,这就有点奇怪了~需要去了解一下这个序列化接口是怎么工作的?

看一下这个接口的代码

image-20231228224938359

fuck~为什么是空的,那这个接口还有什么意义呢?

经过一些查阅,这种没有内容的接口是一种标识接口,就是去通知JVM,当JVM检查到这个接口实现,意思就是用户不负责对类的序列化,由jvm负责该类的序列化。

和这个序列化相关,有一个知识点就是serialVersionUID。

在Serializable接口上,有这样的一段注释。

image-20231228225810247

简单翻译一下就是:如果一个序列化类没有显示声明一个serialVersionUID,这个类在运行时会自动创建一个。但是官方强烈建议我们将所有除了enum类型的序列化类声明一个serialVersionUID。因为默认生成的serialversionUID对class极其敏感,在反序列化的时候很容易抛出InvalidClassException异常。

我理解的就是,如果我们不自己创建一个,那么序列化后的对象,在反序列化时,只要类有一点点变动(比如多了个方法、多了个字段),都会导致InvalidClassException。这样就导致与编译器的实现细节耦合,可能会导致在反序列化的过程中发生意外的InvalidClassException异常。

此外serialVersionUID字段地声明要尽可能使用private关键字修饰,这是因为该字段的声明只适用于声明的类,该字段作为成员变量被子类继承是没有用处的!

解决了这个问题,继续搭建环境~

当在定义Result(统一返回对象)的枚举信息时,遇到了知识盲区,java中枚举是如何表示的?

// 学习一下枚举类型

// enum类型继承java.lang.Enum
public enum Color {
    RED(1,"我是红色"),   // 这些变量默认被final、public、static修饰
    BLUE(2,"我是蓝色"),
    GREEN(3,"我是绿色");
    private int value;
    private String description;
    // 枚举类型中可以定义构造函数和其它变量
    private ColorEnum(int value, String description)
    {
         this.value = value;
         this.description = description;
    }
}

// 枚举类型优势:
//(1)类型安全。
//(2)紧凑有效的数据定义。
//(3)可以和程序其他部分完美交互。
//(4)运行效率高。

通过对上面枚举类型的学习,这个枚举类的代码可以很清晰的理解, 通过枚举变量的构造函数,可以创建4个不同的常量,有不同的错误码和说明信息,这样确实比C++中方便了很多,在C++项目中,往往会定义变量后,在创建专门的错误信息类,将不同的错误码和错误信息进行匹配,从而通过类似CodeToString()的方法,进行转换后打印...

public enum ResponseCode {
        SUCCESS("0000", "成功"),
        UN_ERROR("0001","未知失败"),
        ILLEGAL_PARAMETER("0002","非法参数"),
        INDEX_DUP("0003","主键冲突");

        private String code;
        private String info;

        ResponseCode(String code, String info) {
            this.code = code;
            this.info = info;
        }

        public String getCode() {
            return code;
        }

        public String getInfo() {
            return info;
        }

    }

然后..又遇到了另一个问题,当我创建好了common公共对象类Result, 在rpc模块下,直接import是找不到的,肯定是rpc模块没有引入common的jar包,那么如何解决这个问题呢?

很明显这个问题是由于我对maven的认识不足导致的(之前没有去了解maven的lifecycle)

image-20231228234038409

下面就看一下这几个生命周期方法的作用

clean:清除之前构建生成的所有文件
validate:用于验证项目是否正确,并且其中有必要信息是否都可用
compile:编译项目中的源代码,主要是java文件
test:用合适的测试框架来进行测试,测试compile中编译出来的代码
package:生成target目录,编译、测试代码,生成测试报告,生成jar/war文件 
vertify:这步是用来验证testm检查test的结果是否满足标准
install:将软件包安装到本地存储库中
deploy:复制最终的包至远程仓库,共享给其它开发人员和项目

这样一看很明显,我得先把common的模块compile 然后 package,在install到本地的maven仓库当中。

执行一套流程后,发现还是不能引入。不清楚具体原因hhh,继续查找问题。先来看看本地的maven仓库的情况

image-20231228235739701

明明有对应的jar包,为什么不能引入呢?

又看了project setting中的module的依赖

image-20231229000405597

明明也可以找到对应的位置..为什么还要爆红?

仔细看之后,发现是因为包名不一样,一个是com.xyf.lottery,另一个是com.xyf,晕死~

改变dependencies后,恢复正常

<dependencies>
        <dependency>
            <groupId>com.xyf</groupId>
            <artifactId>lottery-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
</dependencies>

在配置业务层的一个类时,看到了一种注解方法@Resource,虽然明白其应该和@Autowired作用类似,实现Bean的注入,下面简单了解下区别

@Resource和@Autowired注解都是用来实现依赖注入的。只是@AutoWried按by type自动注入,而@Resource默认按byName自动注入。

其它配置遇到的问题:

  1. mysql 8.0以上配置连接,需要将mysql配置属性改为如下,需要url添加serverTimezone, 同时driver-class-name改为com.mysql.cj.jdbc.Driver:

image-202401040016060612. 要注意Dubbo接口实现类上的Service注解,需要是Dubbo包下面的,而不是Spring的Service注解。如下:

image-20240104001720472