一:框架开发知识总结:
1.在用户登录接口里,接受请求参数搭配(@RequestBody @Valid):
![]()
当中去圈起来的两个注解, @RequestBody 作用是把前端传过来的HTTP 请求 Body 里面的 JSON 字符串,自动转成 Java 实体对象,而@Valid用来扫描SendVerificationCodeRequest这个类里面加的校验注(@NotBlank、@Email等)
也就是说,@Valid经常搭配这些来进行校验参数,如果前端用户输入不合法,就会返回这些异常信息。
2.在一些实体类里,加了@Builder注解。
加入这个之后,在外面创建这个类的时候,不用手写一堆 set 方法,直接通过 类.builder(). . .build()可以直接创建一个并初始化类。
上面这段代码等效于:
SendVerificationCodeResponse resp = new SendVerificationCodeResponse(); resp.setSendTo("***"); resp.setExpireTime(300); return resp;3.接口和实现类(impl)关系。
其中的UserService是一个接口:
有一个实现类UserServiceImpl实现(implement)了UserService这个接口:
UserServiceImpl 实现(implement)这个接口之后,接口的所有方法UserServiceImpl 都要进行实现,图中UserService接口有两个方法(发送验证码,认证注册/登录),所以,UserServiceImpl都是要进行实现的,这也是java基础知识讲过的(上图UserServiceImpl类里的方法截图不完整,方法代码是有的)。
4.注入Bean,和拿取Bean。
先看代码:
我们知道,接口是不能实例化的,UserService userService 为什么合法?并且userService还可以调用方法?看下图:
可以看到,UserServiceImpl这个类有个@Service注解,这个注解会将这个UserServiceImpl转化成一个Bean(对象实例,即new UserServiceImpl())放到spring容器,并且Spring容器会记录这个Bean的类型信息,这个Bean, 既是 UserserviceImpl类型,同时也属于UserService接口类型(因为implements实现了它)。
之后,当执行到代码1后,@Autowired去找容器中,找可以赋值给UserService类型变量的Bean,因为UserserviceImpl 的实例满足: Userservice ref = new UserserviceImpl() (Java 多态成立,相当于向上转型),容器里只有这一个实现类Bean,直接选中它注入给到userService。
代码2就可以直接调用对应Bean的 sendVerificationCode 方法了。
@Autowired默认是按类型匹配,假设如果这个Userservice接口有两个实现类:
@Service public class UserServiceImpl implements UserService {} @Service public class UserServiceMockImpl implements UserService {}此时,spring容器中就有两个 Bean 都实现 UserService,即UserServiceImpl和UserServiceMockImpl,这样的话, @Autowired不知道应该注入哪个Bean,就会报错,有个方法就是通过@Qualifier注解指定Bean的名字:
@Autowired @Qualifier("userServiceImpl") private UserService userService;这样之后,就选定了userServiceImpl这个Bean来注入。
在实际开发中,一般一个impl类实现一个接口,也就是一一对应,这样的好处是,不用指定Bean来注入,还拥有就是代码功能分类更清楚可读。
补充:除了@Service,还有以下的注解也是将类实例成Bean注入到spring容器:
1. @Component: 2. @Controller: 3. @RestController = @Controller + @ResponseBody5.MyBatis第三方依赖。
这里有个用户实体类的表:
@TableName("Users")写在User实体类上,意思是告诉MyBatis,这个User类,映射数据库里面名叫Users的表。
@TableField("password_hash")告诉MyBatis,Java实体属性passwordhash,对应数据库表里面的字段名password_hash,(这里就是对应数据库Users表中的password_hash)。
我们还创建了一个UserMapper接口:
@Mapper注解,MyBatis会为此接口(UserMapper)动态生成代理实现类,成为Bean注入到spring容器(意思是,MyBatis帮我们实现了一个类,这个类 implement UserMapper,但是我们看不到这个类)。
BaseMapper<>是一个MyBatis第三方提供的接口,这个接口源码预定(已经实现)了很多抽象方法,可以理解为里面有很多预定的sql语句。内置 CRUD 方法(insert、selectOne 等)。
extends BaseMapper<User> ,表示继承BaseMapper接口(接口1实现接口2,就可以将接口2的方法拿到接口1来使用了,相当于扩大了接口1的方法)。
BaseMapper<User>中的<User>代表这个Mapper操作的实体是User,也就是Users表。
在impl代码里,spring容器将MyBatis 生成的代理对象,注入到 userMapper:
在impl业务代码处,有一个注解:
其中的@Transactional注解,是Spring 事务注解: 被标记的方法里,数据库操作要么全部成功;只要抛出指定异常,所有数据库操作全部回滚撤销,不会出现一半成功一半失败。
对于数据库的操作,具体在这段代码:
// 1. 创建条件构造器,绑定User实体 LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); // 2. 添加条件:username = account queryWrapper.eq(User::getUsername,account); // 3. 使用mapper执行查询,拿到User对象 User user = userMapper.selectOne(queryWrapper);6.在用户登出(退出登录模块),@RequestHeader注解的作用。
@RequestHeader 用来从HTTP请求头里,提取名字叫 Authorization 的值,
赋值给变量 authorization,