物流项目的分类
技术架构图(面试时面试官会要求你画出技术架构图)
功能结构图
业务功能流程
流程说明:
-
用户在【用户端】下单后,生成订单
-
系统会根据订单生成【取件任务】,快递员上门取件后成功后生成【运单】
-
用户对订单进行支付,会产生【交易单】
-
快件开始运输,会经历起始营业部、分拣中心、转运中心、分拣中心、终点营业部之间的转运运输,在此期间会有多个【运输任务】
-
到达终点网点后,系统会生成【派件任务】,快递员进行派件作业
-
最后,用户将进行签收或拒收操作
微服务调度关系
物流项目使用的工具的账号和密码
名称 | 地址 | 用户名/密码 | 端口 |
---|---|---|---|
git | sl-express.com - The domain is available for purchase | sl/sl123 | 10880 |
maven | http://maven.sl-express.com/nexus/ | admin/admin123 | 8081 |
jenkins | sl-express.com - The domain is available for purchase | root/123 | 8090 |
权限管家 | http://auth.sl-express.com/api/authority/static/index.html | admin/123456 | 8764 |
RabbitMQ | sl-express.com - The domain is available for purchase | sl/sl321 | 15672 |
MySQL | - | root/123 | 3306 |
nacos | http://nacos.sl-express.com/nacos/ | nacos/nacos | 8848 |
neo4j | http://neo4j.sl-express.com/browser/ | neo4j/neo4j123 | 7474 |
xxl-job | http://xxl-job.sl-express.com/xxl-job-admin | admin/123456 | 28080 |
EagleMap | sl-express.com - The domain is available for purchase | eagle/eagle | 8484 |
seata | sl-express.com - The domain is available for purchase | seata/seata | 7091 |
Gateway | sl-express.com - The domain is available for purchase | - | 9527 |
admin | sl-express.com - The domain is available for purchase | - | 80 |
skywalking | sl-express.com - The domain is available for purchase | - | 48080 |
Redis | - | 123321 | 6379 |
MongoDB | - | sl/123321 | 27017 |
项目搭建提问
在公司中使用几台服务器?
服务器这块我不是很清楚,因为我们是个大公司,在公司中我们的运维已经搭好了cicd的环境,我们后端人员主要使用jenkins发布写好的微服务模块。
权限认证步骤
流程图:
数据校验
数据校验使用@Validated。(可以使用在方法,方法参数,类 上)
DTO类的数据校验
Controller层中的方法
为了使得DTO类中的校验注解生效,我们需要在controller中添加@Validated。
但是即使在contrller中设置了对应的注解,校验还是不会生效,为了使得注解生效,这里在方法参数位置添加@Validated注解。
在该项目中为了方便开发,直接使用aop进行环绕通知,自动设置@Validated。
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.sl.transport.common.exception.SLException;
import com.sl.transport.common.util.AspectUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 请求参数校验切面,统一对Controller中@RequestBody映射的对象进行校验,在Controller方法中无需单独处理
* 通过aop保证对应参数的中的校验注解可以生效
* 该切面的作用就是自动在方法参数上添加@validated
*/
@Aspect //思想aop
@Slf4j
@EnableAspectJAutoProxy
@Component
public class ValidatedAspect {
@Resource
private Validator validator;
@Around("execution(* com.sl..controller.*Controller.*(..))") //设置前面切面为:每个Controller层中对应的每个方法,这里使用环绕通知
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 获取@RequestBody映射的对象
Object body = AspectUtil.getBody(proceedingJoinPoint); //这里就是获取Controller方法中对应的参数
// 不为空的body进行拦截校验
//方法中的参数不为空就说明我们需要进行数据校验
if (!ObjectUtil.isEmpty(body)) {
// 进行校验
Set<ConstraintViolation<Object>> validateResult = validator.validate(body); //就等于在对应的方法参数上添加@Validated注解
if (CollUtil.isNotEmpty(validateResult)) {
//没有通过校验,抛出异常,由统一异常处理机制进行处理,响应400
String info = JSONUtil.toJsonStr(validateResult.stream()
.map(ConstraintViolation::getMessage).collect(Collectors.toList()));
throw new SLException(info, HttpStatus.BAD_REQUEST.value());
}
}
//校验通过,执行原方法
return proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
}
}
全局异常处理
问:你们是怎么处理异常的呢?
答: 在我们日常开发中,我,我们会创建一个全局的异常拦截器,通过使用@RestControllerAdvice , 创建一个全局异常处理类
通过@ExceptionHandler(对应的异常类)创建一个个处理对应异常类型的方法,最终返回友好的信息给前端。
微服务实现共享配置
对应的配置为下:
#设置共享配置所在的名字空间
#shared-config的值是一个数组
每个共享配配置需要设置:dataId, 分组
spring:
cloud:
nacos:
config:
namespace: ecae68ba-7b43-4473-a980-4ddeb6157bdc
shared-configs: #共享配置
- data-id: shared-spring-seata.yml
group: SHARED_GROUP
refresh: false
- data-id: shared-spring-mysql.yml
group: SHARED_GROUP
refresh: false
- data-id: shared-spring-mybatis-plus.yml
group: SHARED_GROUP
refresh: false
双token身份认证
问:单token会存在什么安全问题?有什么方法可以提高安全性?其实现步骤是什么?
单token存在的问题:
1.设置token有效时间:设置有效时长短了会导致用户需要频繁的登录,设置有效时长过长,会被非法人员获取token,通过该token干坏事。
2.没有设置token的有效时间:如果没有设置token的有效时间,token永远是有效的,在token有异常时,也无法使其失效。(token的无状态性)
解决方案: 使用双token实现三检验。
双token实现三检验的步骤:
1.解决token有效时间的方案为:设置access_token(短token),refresh_token(长token),access_token做用户认证,而refresh_token会在access_token失效的时候,用于获取新的access_token和refresh_token。(当然在通过这个过程也会判断refresh_tolen的有效性)
2.解决token的无状态性: 设置refreish的有效性和只能使用一次。(这些操作在redis中可以完成)
三次验证的流程图:
具体流程为下:
1.在用户第一次登录时会生成access_token和refresh_token,并将refresh_token存入redis中,设置refresh_token的有效时长,这里可以使用access_refresh当key,剩余的使用次数当value。(value默认是1)
如果次数用户有access_token或refresh_token
2.判断是否存在access_token, 存在时判断token的有效性,如果是无效的则返回错误信息。如果不存在则进入第二次验证(第一次验证)
3.判断是否存在refresh_token,通过redis判断token的有效性,如果有效进入第三次验证,如果无效则直接返回登录界面。(第二次验证)
4.判断refresh_token的使用次数通过redis,如果是第一次使用则通过该token获取新的access_token和refresh_token删除旧的refresh_token,如果旧的refresh_token不是第一次使用则此时refresh_tolen在redis中是查不到的,则返回登录界面。(第三次验证)
微信小程序登录流程
登录会取code,通过调用微信接口传入code,appid,appsecret,会获取openId和session_key。
自定义登录态,该登录态要关联openId和session_id,获取通过该自定义态获取openId和session_key。
最终项目的实现流程为下: