约定大于配置!!!
约定大于配置!!!
约定大于配置!!!
1、 针对本机多网卡/虚拟机IP/代理IP/docker 容器启动等情况,需指定注册段IP
- pom 加入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency>
- application.yml加入配置
spring.cloud.inetutils.preferred-networks: '172.16.'
2、日志调用
- 落库 -> 日志独立库(nacos->balde-dev.yaml->blade.datasource.dev.log.url、blade.datasource.dev.log.username、blade.datasource.dev.log.password,【blade-log】->application.yml对应配置) private BladeLogger dblog; dblog.info("title", "data");
dblog.info -> spring event异步订阅事件 -> 最终调ILogClient -> saveUsualLog("Info") -> blade_log_usual表
dblog.warn-> spring event异步订阅事件 -> 最终调ILogClient -> saveUsualLog("Warn") -> blade_log_usual表
dblog.error -> spring event异步订阅事件 -> 最终调ILogClient -> saveUsualLog("Error") -> blade_log_usual表
@ApiLog("Blog详情") @GetMapping("/detail") @ApiOperation(value = "查看详情", notes = "传入主键") public R<Blog> detail(@ApiParam(value = "主键值") @RequestParam Integer id) { Blog detail = service.getById(id); return R.data(detail); }
@ApiLog -> spring event异步订阅事件 -> 最终调ILogClient -> saveApiLog() -> blade_log_api表
public class BladeRestExceptionTranslator { @ExceptionHandler({Throwable.class}) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public R handleError(Throwable e) { log.error("服务器异常", e); ErrorLogPublisher.publishEvent(e, UrlUtil.getPath(WebUtil.getRequest().getRequestURI())); return R.fail(ResultCode.INTERNAL_SERVER_ERROR, Func.isEmpty(e.getMessage()) ? ResultCode.INTERNAL_SERVER_ERROR.getMessage() : e.getMessage()); }
服务器未知异常 -> 异步订阅事件 -> 最终调ILogClient -> saveErrorLog() -> blade_log_api表
- ELFK -> 日志系统 @Slf4j public class ...{ public void ....{ log.info("收到消息: {}", message); } }
3、分布式事务
- 基于seata at模式
- serviceImpl 类 stage 1 方法上标注全局事务
<dependency> <groupId>org.springblade</groupId> <artifactId>blade-starter-transaction</artifactId> </dependency>
@GlobalTransactional @Transactional(rollbackFor = Exception.class) public void xxx(...){ }
4、代码结构/命名规范
- 代码结构
├── controller
│ ├── api #api接口
│ └── manage #后台管理接口
├── entity
│ ├── dto #数据传输模型
│ └── vo #返回前端视图模型
├── feign #内部接口
├── mapper #xml
└── service
└── impl #service实现
api目录命名规则,XxxApiController,路径("/api/xxx")
manage目录命名规则,XxxApiController,路径("/manage/xxx")
feign目录命名规则,IXxxClient
dto目录命名规则,XxxDto
vo目录命名规则,XxxVo
nacos配置网关可以动态修改路径,pbkdf2('blade-auth',128,1024,3) = f0c8d543bfd2d5b9a90e6a68fe7a310e
http://172.16.0.200/f0c8d543bfd2d5b9a90e6a68fe7a310e/api/order/detail
- 数据库规则
每张表都必须建字段,

需要实现租户时继承:TenantEntity,其他继承:BaseEntity,
主键配置如下
// IdType.ASSIGN_ID 为mybatis plus 3.x 的雪花算法 @TableId(value = "id", type = IdType.ASSIGN_ID) private Long id;
application.yml
# 关闭日志配置 blade: mybatis-plus: sql-log: false
5、框架相关
- 接口放行,网关不做鉴权(nacos->blade.yml)
blade: secure: skip-url: - /test/** - /weixin_return_url/**
- 接口验签,(nacos->blade.yml)
blade: secure: sign: - method: ALL pattern: /api/order/** crypto: "sha1" - method: ALL pattern: /manage/** crypto: "md5"
- Client客户端认证机制,(nacos->blade.yml)
blade: #多终端认证配置,AntPatternMatch规则,ClientInterceptor.class/SecureConfiguration.class client: - client-id: sword path-patterns: - /sword/** - client-id: saber path-patterns: - /saber/** - client-id: sword/saber path-patterns: - /**/manage/** - client-id: android/ios/h5 path-patterns: - /**/api/**
这里做了重构,
目的是为了 让 /**/api/** 的路径请求 只允许 android/ios/h5 的client token 才能访问,
已经提了MR和Issue,主要是Spring Security 的路径监听规则导致Blade的ClientInterceptor.java逻辑冲突,目前先构建本地依赖
eg: curl --location --request GET 'http://172.16.0.200/blade-demo/manage/test' \
--header 'blade-auth: bearer {{token}}' \
--header 'Authorization: Basic aW9zOjI2OTE2MDNjMWE1MGE5OTlhZjE4N2I0ZWM5M2I3YTI1'
- 配置单人登录(nacos->blade.yaml)
blade: #token配置 token: #单人登录 single: true
- 踢出已登录用户
JwtUtil.removeAccessToken(String tenantId, String userId)
- 获取用户信息
SecureUtil.xxx()
- Redis分布式锁(nacos->blade-dev.yaml)
#项目模块集中配置 blade: #分布式锁配置 lock: enabled: true address: redis://172.16.0.201:6379
<dependency> <groupId>org.springblade</groupId> <artifactId>blade-starter-redis</artifactId> </dependency>
@RequestMapping("/test") @RedisLock(value = "lock:api:test") public String test() { }
- Redis缓存(nacos->blade.yaml)
blade: #redis序列化方式,参见BladeRedisProperties.SerializerType redis: serializer-type: json
@Autowired private BladeRedis bladeRedis; @RequestMapping("/test") public String test() { bladeRedis.set("a:b", bean); }
6、权限模块
- 功能权限 -> 即菜单按钮权限,参见RBAC
- 接口权限 -> 注解@PreAuth,个别敏感接口,只允许管理员或特定角色访问,具体参见Spring security
#引入 secure <dependency> <groupId>org.springblade</groupId> <artifactId>blade-core-auto</artifactId> </dependency> @PreAuth("hasAnyRole('opsPrivileger','admin')") //修改系统参数值(手续费/商户号/...) public boolean updateOpsParam(...){ }
- 数据权限 -> 注解@DataAuth,具体参见dsf,租户模式实现数据权限 -> tenant_id字段,@DataAuth数据权限 -> create_dept字段,eg:租户A下面的销售角色只能看到本部及下属机构的销售统计数据
动态数据权限部分只扫描了包含Page、List的mapper方法,其他方法需要在blade.yml配置
#引入 secure <dependency> <groupId>org.springblade</groupId> <artifactId>blade-starter-datascope</artifactId> </dependency> <dependency> <groupId>org.springblade</groupId> <artifactId>blade-scope-api</artifactId> </dependency> @DataAuth(column = "user_id", type = DataScopeEnum.OWN_DEPT_CHILD,value = "where scope.create_dept !='a' and scope.create_dept in (${deptId})") //${deptId} -> BladeUser类属性 //column -> 可自定数据权限字段 public R saleMetricsReport(...){ }
Comments | NOTHING