Spring Boot(十三):Spring Boot 集成 Activiti - 快速实现工作流
ccwgpt 2024-11-01 11:32 20 浏览 0 评论
大家好,我是杰哥
上一篇文章,我们介绍了一个常用工作流框架:Activiti,并通过实际例子,了解了它的工作原理与使用步骤。实际上,Spring Boot 也集成了这个框架,从而能够让我们轻松实现项目中的工作流
需要说明的是,Spring Boot 集成的 Activiti 依赖 activiti-spring-boot-starter中 ,同时也集成了 Security 框架,所以说它可谓是自带权限控制功能,这一点从设计上出发,的确是比较人性化的了,毕竟实际需求中的工作流,往往涉及到特定用户的操作,比如有些工作流只能由某些人发起或者查看,而有些流程,只能由某些人进行审批等
当然你也可以考虑将 Security 换成其他权限控制的框架,或者在初学时,直接将 Security 去掉即可(具体方式网上都有的,可以参考)
据我了解,很多 Spring Boot 框架的 WEB 项目中,往往就是直接采用这两个方式一起进行权限管理的工作流控制的,所以,为了完整起见,我们今天就直接来学习 Activiti 与 Spring Security 结合来实现工作流控制的方法与步骤
本次演示信息如下(均为当前最新版本):
- spring-boot-starter-parent 依赖版本:2.7.0
- activiti-spring-boot-starter 依赖版本:7.1.0.M6
- spring-boot-starter-security 依赖版本:2.7.0
一 security 相关
对于 Spring Boot 集成 Security 的步骤,我们在文章 Spring Boot(十一):Spring Security 实现权限控制 中已经很详细地介绍过,可以跳过去大概阅读一番,以便更好地入门此次的知识
1 引入 spring-boot-starter-security 依赖
虽然 activiti-spring-boot-starter 也包含了 Security 的依赖,但是在 7.1.0.M6 版本里,却不能够直接使用最新版本的权限配置方式(自定义 SecurityFilterChain Bean 来实现权限配置),所以我这里便额外引入了 spring-boot-starter-security 的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2 表结构
遵从 Security 所采取的权限访问控制方案:RABC -基于角色的权限访问控制(Role-Based Access Control),我们建立如下 5 张表
建表语句如下:
/*
Navicat Premium Data Transfer
Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50733
Source Host : localhost:3306
Source Schema : activiti_spring
Target Server Type : MySQL
Target Server Version : 50733
File Encoding : 65001
Date: 18/07/2022 15:55:30
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) DEFAULT NULL,
`pid` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of permission
-- ----------------------------
BEGIN;
INSERT INTO `permission` VALUES (1, '/user/common', 'common', NULL, 0);
INSERT INTO `permission` VALUES (2, '/user/admin', 'admin', NULL, 0);
INSERT INTO `permission` VALUES (3, '/process/*', 'activiti', NULL, 0);
COMMIT;
-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of role
-- ----------------------------
BEGIN;
INSERT INTO `role` VALUES (1, 'USER');
INSERT INTO `role` VALUES (2, 'ADMIN');
INSERT INTO `role` VALUES (3, 'ACTIVITI_USER');
COMMIT;
-- ----------------------------
-- Table structure for role_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_id` bigint(11) NOT NULL,
`permission_id` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of role_permission
-- ----------------------------
BEGIN;
INSERT INTO `role_permission` VALUES (1, 1, 1);
INSERT INTO `role_permission` VALUES (2, 2, 1);
INSERT INTO `role_permission` VALUES (3, 2, 2);
INSERT INTO `role_permission` VALUES (4, 3, 3);
COMMIT;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
BEGIN;
INSERT INTO `user` VALUES (1, 'user', '$2a$10$4zd/aj2BNJhuM5PIs5BupO8tiN2yikzP7JMzNaq1fXhcXUefWCOF2');
INSERT INTO `user` VALUES (2, 'admin', '$2a$10$4zd/aj2BNJhuM5PIs5BupO8tiN2yikzP7JMzNaq1fXhcXUefWCOF2');
INSERT INTO `user` VALUES (3, 'Jack', '$2a$10$4zd/aj2BNJhuM5PIs5BupO8tiN2yikzP7JMzNaq1fXhcXUefWCOF2');
INSERT INTO `user` VALUES (4, 'Marry', '$2a$10$4zd/aj2BNJhuM5PIs5BupO8tiN2yikzP7JMzNaq1fXhcXUefWCOF2');
COMMIT;
-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` bigint(11) NOT NULL,
`role_id` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user_role
-- ----------------------------
BEGIN;
INSERT INTO `user_role` VALUES (1, 1, 1);
INSERT INTO `user_role` VALUES (3, 2, 2);
INSERT INTO `user_role` VALUES (4, 2, 3);
INSERT INTO `user_role` VALUES (5, 3, 3);
INSERT INTO `user_role` VALUES (6, 4, 3);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
其实就是直接拿来文章 Spring Boot(十一):Spring Security 实现权限控制 中的表结构,并根据我们本次对于 Activiti 项目的演示需要,在之前的基础上,分别增加了两个用户:Jack 和 Marry,以及他们对应的新角色:ACTIVITI_USER 以及新 url :/process/* 的访问权限。当然,根据 RABC 的方式,也配置了其对应的用户角色、角色权限的关系
3 配置类
采用 Spring Boot Security 的最新方式实现,即:
- 如果想要配置过滤器链,可以通过自定义 SecurityFilterChain Bean 来实现
- 如果想要配置 WebSecurity,可以通过 WebSecurityCustomizer Bean 来实现
@Configuration
@Slf4j
public class SecurityConfig {
@Resource
private PermissionMapper permissionMapper;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
authorizeRequests = http.csrf().disable().authorizeRequests();
// 方式二:配置来源于数据库
// 1.查询到所有的权限
List<Permission> allPermission = permissionMapper.findAllPermission();
// 2.分别添加权限规则
allPermission.forEach((p -> {
authorizeRequests.antMatchers(p.getUrl()).hasAnyAuthority(p.getName()) ;
}));
authorizeRequests.antMatchers("/**").fullyAuthenticated()
.anyRequest().authenticated().and().formLogin();
return http.build();
}
@Bean
WebSecurityCustomizer webSecurityCustomizer() {
return web -> {
web.ignoring().antMatchers("/css/**");
web.ignoring().antMatchers("/js/**");
web.ignoring().antMatchers("/img/**");
web.ignoring().antMatchers("/plugins/**");
web.ignoring().antMatchers("/login.html");
};
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
当前用户所拥有的的权限等信息,则通过实现 UserDetailsService 接口,并重写其方法 loadUserByUsername() 来获取:
@Slf4j
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1.根据用户名称查询到user用户
User userDetails = userMapper.findByUsername(username);
if (userDetails == null) {
return null;
}
// 2.查询该用户对应的权限
List<Permission> permissionList = userMapper.findPermissionByUsername(username);
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
permissionList.forEach((a) -> grantedAuthorities.add(new SimpleGrantedAuthority(a.getName())));
log.info(">>permissionList:{}<<", permissionList);
// 设置权限
userDetails.setAuthorities(grantedAuthorities);
return userDetails;
}
}
到此,就完成了 Security 的相关配置,接下来,让我们正式进入 Spring Boot 集成 Activiti 的实战环节
二 进入 Spring Boot 集成 Activiti 的实战
需要预先说明的是,
Activiti 提供了几个 Service 类,用来管理工作流,常用的有以下四项:
- 1)RepositoryService:提供流程定义和部署等功能。比如说,实现流程的的部署、删除,暂停和激活以及流程的查询等功能
- 2)RuntimeService:提供了处理流程实例不同步骤的结构和行为。包括启动流程实例、暂停和激活流程实例等功能
- 3)TaskService:提供有关任务相关功能的服务。包括任务的查询、删除以及完成等功能
- 4)HistoryService:提供 Activiti 引擎收集的历史记录信息服务。主要用于历史信息的查询功能
- 还有以下两项:
- 1)ManagementService:job 任务查询和数据库操作
- 2)DynamicBpmnService:无需重新部署就能修改流程定义内容
而 Spring Boot 集成 Activiti 实现工作流功能,也主要是采用这些 Service 所提供的 相应的 API 来实现的
1 配置文件
application.yml 文件的配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/activiti_spring?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
activiti:
# flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。(生产环境常用)
# true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。(开发时常用)
# create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。(单元测试常用)
# drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。
database-schema-update: true
#默认不生成历史表,这里开启
db-history-used: true
#历史登记
# none: 不记录历史流程,性能高,流程结束后不可读取
# activity: 归档流程实例和活动实例,流程变量不同步
# audit: 默认值,在activiti基础上同步变量值,保存表单属性
# full: 性能较差,记录所有实例和变量细节变化,最完整的历史记录,如果需要日后跟踪详细可以开启full(一般不建议开启)
history-level: full
deployment-mode: never-fail # 关闭 SpringAutoDeployment
除了数据库的配置信息以外,在我们的 demo 演示环境,Activiti 的配置如下:
- database-schema-update 配置为 true,即每次项目启动,都会对数据库进行更新操作,如果表不存在,则自动创建
- db-history-used 配置为 true 由于默认是不生成历史表的,配置为 true,表示需要生成
- history-level 配置 为 full,表示记录最完整的历史记录
- deployment-mode 配置为 never-fail ,即关闭掉 SpringAutoDeployment。如果不关闭,每次重新启动项目的时候,总是会在 ACT_RE_DEPLOYMENT 自动创建一个名为 SpringAutoDeployment 工作流记录。但是在开发阶段,需要经常重启项目,久而久之就会导致 ACT_RE_DEPLOYMENT 的记录越来越大了
2 表结构创建
首次启动时,根据以上的配置,Activiti 会进行表结构的自动创建,以下是项目初次启动时的日志
由于上述我们配置了开启历史表的使用开关:db-history-used: true
所以,这里除了创建 Activiti 的非历史表结构以外,还创建了其历史表结构
项目启动之后,会发现,我们所配置的 activiti_spring 数据库中,便增加了 25 张 ACT 开头的表
备注:这些表的说明,也可以参考上一篇文章:Activiti工作流(一):OA 上的那些请假流程如何快速实现呢?
3 流程部署
总得来说,可以分为两种方式:自动部署和手动部署
自动部署,实际上是 Spring Boot 会在启动项目时,会自动部署项目目录下的 processes 文件夹中的所有流程,而没有在这个目录下的所有流程定义文件,则需要手动方式进行部署了
我们先来看一下自动部署的方式
1)自动部署
a) 创建流程定义
备注:具体创建方式本文不再赘述,大家可以参考上一篇文章:Activiti工作流(一):OA 上的那些请假流程如何快速实现呢?
在 resources 目录下,创建一个 processes 文件夹,在该文件夹下分别创建两个简单的流程:
- 请假申请(leaveApplication)
- 出差申请(myEvection)
其中,请假流程定义了两个步骤:
创建申请和审批申请,其负责人分别定义为 ${assignee0} 和 ${assignee1}
b)启动项目
项目启动时,完成 process 目录下的流程文件的自动部署
观察日志,可以看到我们预先创建好的两个流程定义,均被自动部署了
我们知道,Activiti 的逻辑,实际上是通过对一系列表的操作,来实现工作流的控制。而流程的部署,则是把我们所创建的流程定义文件,真正与数据库的表关联起来
那么,我们来看看看流程定义表:ACT_RE_PROCDEF
发现表中已有相应的两条记录,验证了这两个流程的确完成了自动部署
当然,如果定义好的流程文件没有在 processes 文件夹下,就需要我们手动部署了
2)手动部署
可以通过如下方式指定 bpmn 文件的目录:filePath 进行部署
repositoryService.createDeployment()
.addClasspathResource(filePath)
.deploy();
由于是对流程定义的操作,所以我们采用 RepositoryService 这个服务进行部署
4 查询流程定义
查询流程定义,依旧是对流程定义的操作,所以采用 RepositoryService 服务进行查询,具体代码与上篇文章中的查询方式类似
/**
* 查询流程
* @param key
* @return
*/
@GetMapping(value = {"/list/{key}","/list"})
public ResponseResult getProcessList(@PathVariable(name = "key",required = false) String key) {
ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
List<ProcessDefinition> definitionList;
if (key!=null){
definitionList = definitionQuery
.processDefinitionKey(key)
.list();
}
definitionList = definitionQuery.list();
//提取所有的流程名称
List<String> processList = new ArrayList<>();
for (ProcessDefinition processDefinition : definitionList) {
processList.add(processDefinition.getName());
}
return ResponseResult.getSuccessResult(processList);
}
采用 Jack 用户登录之后,带上其 Cookie 头参数,进行如下访问
成功访问
5 启动流程
本次实战,我们来启动请假申请(leaveApplication)流程,由于是运行时状态,所以采用 RuntimeService 的 startProcessInstanceByKey(key,map) 方法进行启动,具体代码如下:
/**
* 启动流程定义(由流程定义-》流程实例)
* @param key
* @return
*/
@PostMapping("start/{key}")
public ResponseResult startProcess(@PathVariable(name = "key") String key){
Map<String,Object> map = new HashMap<>();
map.put("assignee0","Jack");
map.put("assignee1","Marry");
//启动 key 标识的流程定义,并指定 流程定义中的两个参数:assignee0和assignee1
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key,map);
ResponseResult result = ResponseResult.getSuccessResult(processInstance.getProcessDefinitionName());
log.info("流程实例的内容:{}",processInstance);
return result;
}
测试启动:
指定参数 key 为 leaveApplication ,进行启动操作
访问成功后,看看表中的数据有没有变化呢,查看 ACT_RU_TASK 表,该表中新增了一条记录,为创建申请,负责人为 Jack,表示我们的这个流程已经成功启动,目前进行到了创建申请这一任务了,其负责人为 Jack
当前登录的用户就是 Jack,此时我们通过接口 /process/task/list 接口来查看 Jack 的任务列表
发现目前在 Jack 名下的确存在一个待办任务:创建申请
6 Jack -创建申请
对任务的完成,依旧是采用 TaskService 进行,具体代码如下:
/**
* 完成任务
* @param key
* @param assigne
* @return
*/
@PostMapping("complete")
public ResponseResult doTask(@RequestParam(name = "key") String key,@RequestParam(name = "assignee")String assigne){
List<Task> tasks = taskService.createTaskQuery().processDefinitionKey(key)
.taskAssignee(assigne)
.list();
if (tasks!=null && tasks.size()>0){
for (Task task : tasks) {
log.info("任务名称:{}",task.getName());
taskService.complete(task.getId());
log.info("{},任务已完成",task.getName());
}
}
return ResponseResult.getSuccessResult(null);
}
由 Jack 来完成“创建申请”的待办任务,分别指定 key 为 leaveApplication ,assignee 为 Jack ,进行任务的完成操作:
访问成功之后,我们再来查看 ACT_RU_TASK(当前任务表)
按照预期,此时正要处理的任务为审批申请,并且负责人为 Marry
当前我们采用 Jack 登录的这个 Cookie 来进行查询,发现 task 列表已经变成了空的
7 Marry -审批申请
1)登录
访问 localhost:8080/logout 登出,会跳转到登录页面
此时,采用 Marry 进行登录
2)查看其名下的任务列表
发现的确存在一个任务:审批申请
3)完成任务
指定 key 为 leaveApplication,assignee 为 Marry,访问接口 /process/complete
接口返回成功 此时,再次查询我们的 ACT_RU_TASK 表,会发现我们已经没有了正在处理的任务,说明我们已完成了所有的任务
再次查看历史表 ACT_HI_TASKINST,会看到我们所处理过的两个任务
好了,走到这一步,我们便成功完成了 Spring Boot 集成 Activiti 进行流程定义、流程部署、流程启动、任务完成等工作流管理的一系列操作
总结
今天带领大家完成了 Spring Boot 集成 Activiti 的功能,网上目前可能很难找到类似的案例,因为我们这里采用的 Spring Boot 和 Activiti 以及 Security 均是当前最新的版本
Spring Boot 与 Activiti 集成,使得我们不仅可以继续使用 Activiti 本身所提供的简易的 API, 而且 Spring Boot 还提供了很多自动化的东西,包括启动时自动创建表结构,自动完成 processes 目录下的流程部署操作等等
真心觉得 Spring Boot 的衍生的确是程序员的福音呢,它使得技术越来越简单化,让我们的学习与使用成本大大降低了呢
文章演示代码地址:https://github.com/helemile/Spring-Boot-Notes/tree/master/activiti/activiti
嗯,就这样。每天学习一点,时间会见证你的强大~
欢迎大家关注我们的公众号,一起持续性学习吧~
往期精彩回顾
总结复盘
架构设计读书笔记与感悟总结
带领新人团队的沉淀总结
复盘篇:问题解决经验总结复盘
网络篇
网络篇(四):《图解 TCP/IP》读书笔记
网络篇(一):《趣谈网络协议》读书笔记(一)
事务篇章
事务篇(四):Spring事务并发问题解决
事务篇(三):分享一个隐性事务失效场景
事务篇(一):毕业三年,你真的学会事务了吗?
Docker篇章
Docker篇(六):Docker Compose如何管理多个容器?
Docker篇(二):Docker实战,命令解析
Docker篇(一):为什么要用Docker?
..........
SpringCloud篇章
Spring Cloud(十三):Feign居然这么强大?
Spring Cloud(十):消息中心篇-Kafka经典面试题,你都会吗?
Spring Cloud(九):注册中心选型篇-四种注册中心特点超全总结
Spring Cloud(四):公司内部,关于Eureka和zookeeper的一场辩论赛
..........
Spring Boot篇章
Spring Boot(十二):陌生又熟悉的 OAuth2.0 协议,实际上每个人都在用
Spring Boot(七):你不能不知道的Mybatis缓存机制!
Spring Boot(六):那些好用的数据库连接池们
Spring Boot(四):让人又爱又恨的JPA
SpringBoot(一):特性概览
..........
翻译
[译]用 Mint 这门强大的语言来创建一个 Web 应用
【译】基于 50 万个浏览器指纹的新发现
使用 CSS 提升页面渲染速度
WebTransport 会在不久的将来取代 WebRTC 吗?
.........
职业、生活感悟
你有没有想过,旅行的意义是什么?
程序员的职业规划
灵魂拷问:人生最重要的是什么?
如何高效学习一个新技术?
如何让自己更坦然地度过一天?
..........
相关推荐
- 团队管理“布阵术”:3招让你的团队战斗力爆表!
-
为何古代军队能够以一当十?为何现代企业有的团队高效似“特种部队”,有的却松散若“游击队”?**答案正隐匿于“布阵术”之中!**今时今日,让我们从古代兵法里萃取3个核心要义,助您塑造一支战斗力爆棚的...
- 知情人士回应字节大模型团队架构调整
-
【知情人士回应字节大模型团队架构调整】财联社2月21日电,针对原谷歌DeepMind副总裁吴永辉加入字节跳动后引发的团队调整问题,知情人士回应称:吴永辉博士主要负责AI基础研究探索工作,偏基础研究;A...
- 豆包大模型团队开源RLHF框架,训练吞吐量最高提升20倍
-
强化学习(RL)对大模型复杂推理能力提升有关键作用,但其复杂的计算流程对训练和部署也带来了巨大挑战。近日,字节跳动豆包大模型团队与香港大学联合提出HybridFlow。这是一个灵活高效的RL/RL...
- 创业团队如何设计股权架构及分配(创业团队如何设计股权架构及分配方案)
-
创业团队的股权架构设计,决定了公司在随后发展中呈现出的股权布局。如果最初的股权架构就存在先天不足,公司就很难顺利、稳定地成长起来。因此,创业之初,对股权设计应慎之又慎,避免留下巨大隐患和风险。两个人如...
- 消息称吴永辉入职后引发字节大模型团队架构大调整
-
2月21日,有消息称前谷歌大佬吴永辉加入字节跳动,并担任大模型团队Seed基础研究负责人后,引发了字节跳动大模型团队架构大调整。多名原本向朱文佳汇报的算法和技术负责人开始转向吴永辉汇报。简单来说,就是...
- 31页组织效能提升模型,经营管理团队搭建框架与权责定位
-
分享职场干货,提升能力!为职场精英打造个人知识体系,升职加薪!31页组织效能提升模型如何拿到分享的源文件:请您关注本头条号,然后私信本头条号“文米”2个字,按照操作流程,专人负责发送源文件给您。...
- 异形柱结构(异形柱结构技术规程)
-
下列关于混凝土异形柱结构设计的说法,其中何项正确?(A)混凝土异形柱框架结构可用于所有非抗震和抗震设防地区的一般居住建筑。(B)抗震设防烈度为6度时,对标准设防类(丙类)采用异形柱结构的建筑可不进行地...
- 职场干货:金字塔原理(金字塔原理实战篇)
-
金字塔原理的适用范围:金字塔原理适用于所有需要构建清晰逻辑框架的文章。第一篇:表达的逻辑。如何利用金字塔原理构建基本的金字塔结构受众(包括读者、听众、观众或学员)最容易理解的顺序:先了解主要的、抽象的...
- 底部剪力法(底部剪力法的基本原理)
-
某四层钢筋混凝土框架结构,计算简图如图1所示。抗震设防类别为丙类,抗震设防烈度为8度(0.2g),Ⅱ类场地,设计地震分组为第一组,第一自振周期T1=0.55s。一至四层的楼层侧向刚度依次为:K1=1...
- 结构等效重力荷载代表值(等效重力荷载系数)
-
某五层钢筋混凝土框架结构办公楼,房屋高度25.45m。抗震设防烈度8度,设防类别丙类,设计基本地震加速度0.2g,设计地震分组第二组,场地类别为Ⅱ类,混凝土强度等级C30。该结构平面和竖向均规则。假定...
- 体系结构已成昭告后世善莫大焉(体系构架是什么意思)
-
实践先行也理论已初步完成框架结构留余后人后世子孙俗话说前人栽树后人乘凉在夏商周大明大清民国共和前人栽树下吾之辈已完成结构体系又俗话说青出于蓝而胜于蓝各个时期任务不同吾辈探索框架结构体系经历有限肯定发展...
- 框架柱抗震构造要求(框架柱抗震设计)
-
某现浇钢筋混凝土框架-剪力墙结构高层办公楼,抗震设防烈度为8度(0.2g),场地类别为Ⅱ类,抗震等级:框架二级,剪力墙一级,混凝土强度等级:框架柱及剪力墙C50,框架梁及楼板C35,纵向钢筋及箍筋均采...
- 梁的刚度、挠度控制(钢梁挠度过大会引起什么原因)
-
某办公楼为现浇钢筋混凝土框架结构,r0=1.0,混凝土强度等级C35,纵向钢筋采用HRB400,箍筋采用HPB300。其二层(中间楼层)的局部平面图和次梁L-1的计算简图如图1~3(Z)所示,其中,K...
- 死要面子!有钱做大玻璃窗,却没有钱做“柱和梁”,不怕房塌吗?
-
活久见,有钱做2层落地大玻璃窗,却没有钱做“柱子和圈梁”,这样的农村自建房,安全吗?最近刷到个魔幻施工现场,如下图,这栋5开间的农村自建房,居然做了2个全景落地窗仔细观察,这2个落地窗还是飘窗,为了追...
- 不是承重墙,物业也不让拆?话说装修就一定要拆墙才行么
-
最近发现好多朋友装修时总想拆墙“爆改”空间,别以为只要避开承重墙就能随便砸!我家楼上邻居去年装修,拆了阳台矮墙想扩客厅,结果物业直接上门叫停。后来才知道,这种配重墙拆了会让阳台承重失衡,整栋楼都可能变...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- bootstrap框架 (43)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- express框架 (43)
- scrapy框架 (52)
- beego框架 (42)
- java框架spring (43)
- grpc框架 (55)
- 前端框架bootstrap (42)
- orm框架有哪些 (43)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)