JWT验证流程总结
- 调用
UserService.login
登录功能,后端从数据库根据用户名和邮箱进行验证,验证成功调用jwtConfig.createJWT
生成JWT,并把这个JWT返回给前端,以后前端每次请求都需要带上这个JWT - controller层对前端来的路由添加
@Authorized
注解进行鉴权 AuthAspect
类对Authorized
注解进行增强,@Order
注解用于有多个增强类对同一个方法进行增强的时候表明其优先级,越小优先级越高- 添加
Before
方法,用于拦截controller包中所有public并且有@Authorized
注解的方法 - 拦截http请求并获得
Authorized
标头,调用jwtConfig.parseJwt
解析出UserVO
信息,判断该UserVO
的角色是否在Authorized
注解的roles集合中,如果不在就抛出访问未授权的异常
项目的并发性怎么样?
通过在Service层使用Transaction注解和synchronized关键字保证了一定的并发性。一开始想的是直接将@Transcational
注解和synchronized
一起使用,但是后来验证发现还是线程不安全的,最后找到原因是加锁的范围没有包括到整个事务导致的,会出现synchronized
代码块执行完但是事务还没有提交,新的线程又进入到synchronized
代码块,读取到的数据是还没有提交的旧数据这样的情况。最后是通过对service层的方法添加一个代理方法,对这个代理方法加synchronized
关键字,方法内部直接调用service
的方法,这样就把锁加到了整个事务上。由此保证了单机下的多线程,但如果是分布式的话后面还的考虑加一些分布式锁
用到了哪些设计模式?
策略模式
总经理角色可以制定促销策略,针对不同级别的客户制定促销策略,包括赠品、价格折让或者赠送代金券,这部分我把这三种促销策略抽象成促销这个类,它具体的实现类有赠品、打折和代金券三种,不同级别的客户在一次购买金额达到触发条件后会自动进行判断,PromitionService层根据客户对应的级别和购买金额发放对应的促销策略,客户并不需要关心具体是哪种促销策略,只需要选择他能使用的促销策略就行
工厂模式
因为每个单据的创建都要设置大量的单据信息,如果把这些创建单据的代码放在业务代码主体中,会降低代码的可读性,所以我把单据的创建都交给工厂来做了,但是由于不同的单据它需要设置的信息基本不相同,所以我没有用抽象工厂,只是用了简单工厂模式,比如对于工资单这个单据,业务代码中只需要给工厂穿进一个staffDao,然后就不需要关心单据的具体创建过程,大大简化了SalarySheetService.makeSalarySheet方法,他只需要获取对应的员工信息,传给工厂,获得单据,存起来,如果有异常,就处理异常,并向前端返回,业务逻辑很清晰
测试部分怎么写的?
测试部分主要分为单元测试和集成测试
单元测试
单元测试部分主要对工资单、员工打卡和用户模块进行测试,比如员工打卡模块,这个Service主要有ClockIn、GetAllInformation和GetMyInformation这三个方法,分别是当日打卡、人力部门查看打卡情况、员工查看今日打卡情况,所以主要测试这三个方法,比如打卡方法,测试打卡前后的员工打卡状态是否更改了,当月打卡次数是不是增加了,因为会用到员工的Dao层,所以先创建一个桩程序,来模拟Dao层返回的信息
集成测试
集成测试主要对财务人员部分的付款单和客户这两个模块的整体进行测试,财务人员制定付款单,包括单据编号,操作员,金额,银行账户以及所付款的客户ID,付款单审批成功后会把客户的应收金额减去单据的金额,表明公司向客户付过这些款了,主要测试单据金额大于公司应付的情况、银行账户错误等,这些情况都应该抛出异常。这部分需要实现的桩程序主要有银行账户Dao、客户Dao和付款单Dao
有哪些可以优化的地方
事务优化
在创建出库单中,主要是基于Mysql的事务进行的,而基于MySQL事务的创建出库单操作的主要瓶颈是网络延迟和GC(Java垃圾回收机制)。执行一条update语句更新库存情况首先要拿到MySQL的行级锁rowLock,所以要尽量降低update对rowLock的持有时间。
一个简单的优化方式是在创建出库单时,从原来的先update库存再创建单据,优化成先创建单据再update库存,这样一来持有Mysql行级锁的时间会比原来少很多
Redis缓存优化
由于员工打卡信息不需要经常变动,但前端接口需要保证员工打卡信息及时显示到前端页面上的,所以对数据库中这个字段的查询会比较频繁,可以采用Redis缓存的方式来减轻DB的压力,选取Bitmap数据接口存储员工打卡信息。内部的key是员工id+年月的形式,执行打卡时去相应的key中把天数对应的bit为置为1就行了