在微服务项目中,Spring Security 比 Shiro 强在哪?

虽然目前 Spring Security 一片火热,但是 Shiro 的市场依然存在,今天我就来稍微的说一说这两个框架的,方便大家在实际项目中选择适合自己的安全管理框架。

首先我要声明一点,框架无所谓好坏,关键是适合当前项目场景,作为一个年轻的程序员更不应该厚此薄彼,或者拒绝学习某一个框架。

小孩子才做选择题,成年人两个都要学!

所以接下来主要结合我自己的经验来说一说这两个框架的优缺点,没有提到的地方也欢迎大家留言补充。

1. Spring Security

1.1 因为 SpringBoot 而火

Spring Security 并非一个新生的事物,它最早不叫 Spring Security ,叫 Acegi Security,叫 Acegi Security 并不是说它和 Spring 就没有关系了,它依然是为 Spring 框架提供安全支持的。事实上,Java 领域的框架,很少有框架能够脱离 Spring 框架独立存在。

当 Spring Security 还叫 Acegi Security 的时候,虽然功能也还可以,但是实际上这个东西并没有广泛流行开来。最重要的原因就是它的配置太过于繁琐,当时网上流传一句话:“每当有人要使用 Acegi Security,就会有一个精灵死去。” 足见 Acegi Security 的配置是多么可怕。直到今天,当人们谈起 Spring Security 的时候,依然在吐槽它的配置繁琐。

后来 Acegi Security 投入 Spring 的怀抱,改名叫 Spring Security,事情才慢慢开始发生变化。新的开发团队一直在尽力简化 Spring Security 的配置,Spring Security 的配置相比 Acegi Security 确实简化了很多。但是在最初的几年里,Spring Security 依然无法得到广泛的使用。

直到有一天 Spring Boot 像谜一般出现在江湖边缘,彻底颠覆了 JavaEE 的世界。一人得道鸡犬升天,自从 Spring Boot 火了之后,Spring 家族的产品都被带了一把,Spring Security 就是受益者之一,从此飞上枝头变凤凰。

Spring Boot/Spring Cloud 现在作为 Java 开发领域最最主流的技术栈,这一点大家应该都没有什么异议,而在 Spring Boot/Spring Cloud 中做安全管理,Spring Security 无疑是最方便的。

你想保护 Spring Boot 中的接口,添加一个 Spring Security 的依赖即可,事情就搞定了,所有接口就保护起来了,甚至不需要一行配置。

有小伙伴可能觉得这个太笼统了,我再举一个实际点的例子。

在微服务架构的项目中,我们可能使用 Eureka 做服务注册中心,默认情况下,Eureka 没有做安全管理,如果你想给 Eureka 添加安全管理,只需要添加 Spring Security 依赖,然后在 application.properties 中配置一下用户名密码即可,Eureka 就自动被保护起来了,别人无法轻易访问;然后各个微服务在注册的时候,只需要把注册地址改为 http://username:password@localhost:8080/eureka 即可。类似的例子还有 Spring Cloud Config 中的安全管理。

在微服务这种场景下,如果你想用 Shiro 代替 Spring Security,那 Shiro 代码量绝对非常可观,Spring Security 则可以非常容易的集成到现在流行的 Spring Boot/Spring Cloud 技术栈中,可以和 Spring Boot、Spring Cloud、Spring Social、WebSocket 等非常方便的整合。

所以我说,因为 Spring Boot/Spring Cloud 火爆,让 Spring Security 跟着沾了一把光。

1.2 配置臃肿吗?

「有的人觉得 Spring Security 配置臃肿。」

如果是 SSM + Spring Security 的话,我觉得这话有一定道理。

但是如果是 Spring Boot 项目的话,其实并不见得臃肿。Spring Boot 中,通过自动化配置 starter 已经极大的简化了 Spring Security 的配置,我们只需要做少量的定制的就可以实现认证和授权了,这一点,大家可以参考我之前连载的 Spring Security 系列文章基本就能感受到这种便利(公众号后台回复 2020 有文章索引)。

「有人觉得 Spring Security 中概念复杂。」

这个是这样的,没错。

Spring Security 由于功能比较多,支持 OAuth2 等原因,就显得比较重量级,不像 Shiro 那样轻便。

但是如果换一个角度,你可能会有不一样的感受。

在 Spring Security 中你会学习到许多安全管理相关的概念,以及常见的安全攻击。这些安全攻击,如果你不是 web 安全方面的专家,很多可能存在的 web 攻击和漏洞你可能很难想到,而 Spring Security 则把这些安全问题都给我们罗列出来并且给出了相应的解决方案。

所以我说,我们学习 Spring Security 的过程,也是在学习 web 安全,各种各样的安全攻击、各种各样的登录方式、各种各样你能想到或者想不到的安全问题,Spring Security 都给我们罗列出来了,并且给出了解决方案,从这个角度来看,你会发现 Spring Security 好像也不是那么让人讨厌。

1.3 结合微服务的优势

除了前面和大家介绍的 Spring Security 优势,在微服务中,Spring 官方推出了 Spring Cloud Security 和 Spring Cloud OAuth2,结合微服务这种分布式特性,可以让我们更加方便的在微服务中使用 Spring Security 和 OAuth2,松哥前面的 OAuth2 系列实际上都是基于 Spring Cloud Security 来做的。

可以看到,Spring 官方一直在积极进取,让 Spring Security 能够更好的集成进微服务中。

2. Shiro

接下来我们再说说 Apache Shiro。

Apache Shiro 是一个开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro 框架具有直观、易用等特性,同时也能提供健壮的安全性,虽然它的功能不如 Spring Security 那么强大,但是在常规的企业级应用中,其实也够用了。

2.1 由来

Shiro 的前身是 JSecurity,2004 年,Les Hazlewood 和 Jeremy Haile 创办了 Jsecurity。当时他们找不到适用于应用程序级别的合适 Java 安全框架,同时又对 JAAS 非常失望,于是就搞了这个东西。

2004 年到 2008 年期间,JSecurity 托管在 SourceForge 上,贡献者包括 Peter Ledbrook、Alan Ditzel 和 Tim Veil。

2008 年,JSecurity 项目贡献给了 Apache 软件基金会(ASF),并被接纳成为 Apache Incubator 项目,由导师管理,目标是成为一个顶级 Apache 项目。期间,Jsecurity 曾短暂更名为 Ki,随后因商标问题被社区更名为“Shiro”。随后项目持续在 Apache Incubator 中孵化,并增加了贡献者 Kalle Korhonen。

2010 年 7 月,Shiro 社区发布了 1.0 版,随后社区创建了其项目管理委员会,并选举 Les Hazlewood 为主席。2010 年 9 月 22 日,Shrio 成为 Apache 软件基金会的顶级项目(TLP)。

2.2 有哪些功能

Apache Shiro 是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。Apache Shiro 的首要目标是易于使用和理解。安全有时候是很复杂的,甚至是痛苦的,但它没有必要这样。框架应该尽可能掩盖复杂的地方,露出一个干净而直观的 API,来简化开发人员在应用程序安全上所花费的时间。

以下是你可以用 Apache Shiro 所做的事情:

  1. 验证用户来核实他们的身份

  2. 对用户执行访问控制,如:判断用户是否被分配了一个确定的安全角色;判断用户是否被允许做某事

  3. 在任何环境下使用Session API,即使没有Web容器

  4. 在身份验证,访问控制期间或在会话的生命周期,对事件作出反应

  5. 聚集一个或多个用户安全数据的数据源,并作为一个单一的复合用户“视图”

  6. 单点登录(SSO)功能

  7. 为没有关联到登录的用户启用"Remember Me"服务

  8. ...

Apache Shiro 是一个拥有许多功能的综合性的程序安全框架。下面的图表展示了 Shiro 的重点:

Shiro 中有四大基石——身份验证,授权,会话管理和加密。

  1. Authentication:有时也简称为“登录”,这是一个证明用户是谁的行为。

  2. Authorization:访问控制的过程,也就是决定“谁”去访问“什么”。

  3. Session Management:管理用户特定的会话,即使在非 Web 或 EJB 应用程序。

  4. Cryptography:通过使用加密算法保持数据安全同时易于使用。

除此之外,Shiro 也提供了额外的功能来解决在不同环境下所面临的安全问题,尤其是以下这些:

  1. Web Support:Shiro 的 web 支持的 API 能够轻松地帮助保护 Web 应用程序。

  2. Caching:缓存是 Apache Shiro 中的第一层公民,来确保安全操作快速而又高效。

  3. Concurrency:Apache Shiro 利用它的并发特性来支持多线程应用程序。

  4. Testing:测试支持的存在来帮助你编写单元测试和集成测试。

  5. "Run As":一个允许用户假设为另一个用户身份(如果允许)的功能,有时候在管理脚本很有用。

  6. "Remember Me":在会话中记住用户的身份,这样用户只需要在强制登录时候登录。

2.3 学习资料

Shiro 的学习资料并不多,没看到有相关的书籍。张开涛的《跟我学Shiro》是一个非常不错的资料,小伙伴可以搜索了解下。也可以在公众号后台回复 2TB,有相关的视频教程。

2.4 优势和劣势

就目前而言,Shiro 最大的问题在于和 Spring 家族的产品进行整合的时候非常不便,在 Spring Boot 推出的很长一段时间里,Shiro 都没有提供相应的 starter,后来虽然有一个 shiro-spring-boot-web-starter 出来,但是其实配置并没有简化多少。所以在 Spring Boot/Spring Cloud 技术栈的微服务项目中,Shiro 几乎不存在优势。

但是如果你是传统的 SSM 项目,不是微服务项目,那么无疑使用 Shiro 是最方便省事的,因为它足够简单,足够轻量级。

3. 如何取舍

在公司里做开发,这两个要如何取舍,还是要考虑蛮多东西的。

首先,如果是基于 Spring Boot/Spring Cloud 的微服务项目,Spring Security 无疑是最方便的。

如果是就是普通的 SSM 项目,那么 Shiro 基本上也够用。

另外,选择技术栈的时候,我们可能也要考虑团队内工程师的技术栈,如果工程师更擅长 Shiro,那么无疑 Shiro 是合适的,毕竟让工程师去学习一门新的技术,一来可能影响项目进度,而来也可能给项目埋下许多未知的雷。

对于我们个人来说,小孩子才做选择题,成年人两个都要学。

评论 2 您还未登录,请先 登录 后发表或查看评论
<p class="md-end-block md-p" style="font-family: Roboto, sans-serif; margin: 0.5rem 0rem 1.5rem; padding: 0px; font-size: 16px; background-color: #ffffff; box-sizing: border-box; line-height: inherit; orphans: 4; white-space: pre-wrap; position: relative; color: #3b454e;"><span class="md-plain" style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; box-sizing: border-box;">天猫商城是一个基于SSM框架的综合性B2C电商平台,需求设计主要参考天猫商城的购物流程:用户从注册开始,到完成登录,浏览商品,加入购物车,进行下单,确认收货,评价等一系列操作。 作为模拟天猫商城系统的核心组成部分之一,采用SSM框架的天猫数据管理后台包含商品管理,订单管理,类别管理,用户管理和交易额统计等模块,实现了对整个商城的一站式管理和维护。</span></p> <p class="md-end-block md-p" style="font-family: Roboto, sans-serif; margin: 0.5rem 0rem 1.5rem; padding: 0px; font-size: 16px; background-color: #ffffff; box-sizing: border-box; line-height: inherit; orphans: 4; white-space: pre-wrap; position: relative; color: #3b454e;"><span class="md-plain" style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; box-sizing: border-box;">本课程是一门专业的Java服架构开发实战课程,主要讲解了当下流行的SpringBoot框架、SpringCloud架构以及与第三方技术整合开发实战内容。</span></p> <p class="md-end-block md-p md-focus" style="font-family: Roboto, sans-serif; margin: 0.5rem 0rem 1.5rem; padding: 0px; font-size: 16px; background-color: #ffffff; box-sizing: border-box; line-height: inherit; orphans: 4; white-space: pre-wrap; position: relative; color: #3b454e;"><span class="md-plain" style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; box-sizing: border-box;">通过本课程的学习,能够理解并掌握SpringBoot的基础知识,同时能够掌握SpringBoot与常用的第三方技术整合实现实际开发的业务需求,包括实现Web开发、数据访问、缓存管理、安全管理、消息服务、任务管理等;了解并掌握SpringCloud微服务架构的基础知识及相关组件的应用,掌握微服务架构企业级开发的实践,建立起服架构思想。</span></p> <p class="md-end-block md-p md-focus" style="font-family: Roboto, sans-serif; margin: 0.5rem 0rem 1.5rem; padding: 0px; font-size: 16px; background-color: #ffffff; box-sizing: border-box; line-height: inherit; orphans: 4; white-space: pre-wrap; position: relative; color: #3b454e;"><span class="md-plain" style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; box-sizing: border-box;"><span style="font-family: Roboto, sans-serif; font-weight: bold;">项目技术栈:</span></span></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">采用SpringBoot简化商城系统的初始搭建以及开发过程</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">采用SpringMVC+Spring+IBatis完成项目的整合</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">采用Mysql作为数据库存储,Druid配置数据库连接池</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">采用SpringCloud+Netflix 微服务技术栈的实战开发</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用Redis完成缓存的数据存储,搭建Redis搭建主从、哨兵、集群应用,保证Redis的高可用</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用ElasticSearch全文检索系统进行商品数据搜索,使用ElasticSearch搭建搜索服务的高可用</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用Ngnix实现页面动静分离与负载均衡的配置</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">采用FastDFS文件储存系统文件存储,完成广告图片、商品图片的上传和存储</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">系统使用采用CAS+shiro单点登录系统实现用户认证</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用ECharts根据后台查询数据生成图表</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用POI实现了商城盈利状况的Excel表格导出。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">商品的详情页使用Thymeleaf完成页面静态化,减少页面数据展示延迟</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">项目使用SpringBoot下的Aop + 自定义注解完成用户行为记录,日志采集</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">后台管理系统使用Shiro实现登录验证和权限管理(超级管理员、管理员、产品编辑员)</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">项目整合信完成订单的支付</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用Redission完成分布式锁,生成订单的编号</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用SpringCloud Alibaba Seat完成下订单模块的分布式事务(新增订单表,库存减少,库存超卖设计)</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用RabbitMQ 做消息队列,完成订单未支付自动取消和模块直接的解耦合</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用Quartz任务调度,完成缓存的定时刷新,保证缓存的一致性</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用本地消息表机制完成消息然队列RabbitMQ消息可靠性传输</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">订单支付模块使用信扫码支付,并设置订单超时自动取消</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">通过Jquery实现前端校验,通过基于Hibernate的Valida注解实现后端的校验功能</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用Base64编码对Json数据传输进行编码和解码</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">项目使用RESTful设计风格实现资源的访问,实现前后端分离</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">项目使用聚合数据第三方短信平台完成用户的登陆功能</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">项目使用SpringBoot整合JavaMail完成邮件的发送</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">项目使用SpringBoot整合Swagger2生成接口文档</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用PostMan完成接口的测试</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">项目的测试:SpringTest、dbunit、EasyMock</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用Docker 进行应用的自动化打包和发布、自动化测试和持续集成、部署和调整其他应用</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">使用 PowerDesigner,完成数据库的建模</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">项目使用禅道进行BUG管理</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">环境采用Maven实施多模块项目构建,采用Git进行项目版本管理</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><span style="font-family: Roboto, sans-serif; margin: 0px; padding: 0px; color: #3b454e; font-weight: bold; orphans: 4; white-space: pre-wrap;">架构解读</span><span style="color: #3b454e; font-family: Roboto, sans-serif; font-weight: bold; orphans: 4; white-space: pre-wrap;">:</span></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><span style="color: #3b454e; font-family: Roboto, sans-serif; font-weight: bold; orphans: 4; white-space: pre-wrap;"><img src="https://img-bss.csdnimg.cn/202012250344382142.jpg" alt="" /></span></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><span style="color: #3b454e; font-family: Roboto, sans-serif; font-weight: bold; orphans: 4; white-space: pre-wrap;">项目部分截图:</span></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><span style="color: #3b454e; font-family: Roboto, sans-serif; font-weight: bold; orphans: 4; white-space: pre-wrap;"><img src="https://img-bss.csdnimg.cn/202012250345169828.png" alt="" /></span></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250354551230.jpg" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250453144736.gif" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250453299471.png" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250454041225.png" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250455192130.png" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250500437508.jpg" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><span style="color: #3b454e; font-family: Roboto, sans-serif; font-weight: bold; orphans: 4; white-space: pre-wrap;">讲义部分截图:</span></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><span style="color: #3b454e; font-family: Roboto, sans-serif; font-weight: bold; orphans: 4; white-space: pre-wrap;"><img src="https://img-bss.csdnimg.cn/202012250501336714.png" alt="" /></span></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><span style="color: #3b454e; font-family: Roboto, sans-serif; font-weight: bold; orphans: 4; white-space: pre-wrap;"><img src="https://img-bss.csdnimg.cn/202012250501527959.png" alt="" /></span></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250503138350.jpg" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250503561515.png" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250504062851.png" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250504171269.png" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250504278541.png" alt="" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202012250504363479.png" alt="" /></p> <p class="md-end-block md-p md-focus" style="font-family: Roboto, sans-serif; margin: 0.5rem 0rem 1.5rem; padding: 0px; font-size: 16px; background-color: #ffffff; box-sizing: border-box; line-height: inherit; orphans: 4; white-space: pre-wrap; position: relative; color: #3b454e;"> </p>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页

打赏作者

Java架构师云流

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值