简介

在 Web 开发中,安全一直是非常重要的一个方面。

安全虽然属于应用的非功能性需求,但是应该在应用开发的初期就考虑进来。

市面上存在比较有名的:Shiro,Spring Security

首先我们看下它的官网介绍:Spring Security官网地址

  1. Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
  2. Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements
  3. Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它实际上是保护基于spring的应用程序的标准。
  4. Spring Security是一个框架,侧重于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring安全性的真正强大之处在于它可以轻松地扩展以满足定制需求

从官网的介绍中可以知道这是一个权限框架

Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。

一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分,Spring Security 框架都有很好的支持。

  1. 在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID LDAP 等。在用户授权方面,
  2. Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control ListACL),可以对应用中的领域对象进行细粒度的控制。

实战环境搭建

项目代码地址:https://gitee.com/zwtgit/spring-security-or-shiro

1、新建一个初始的springboot项目web模块,thymeleaf模块

2、导入静态资源,资源上面有

3、controller跳转!

  1. @Controller
  2. public class RouterController {
  3. @RequestMapping({"/","/index"})
  4. public String index(){
  5. return "index";
  6. }
  7. }

4、测试实验环境是否OK!

SpringSecurity

Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,

他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!

记住几个类:

  • WebSecurityConfigurerAdapter:自定义Security策略
  • AuthenticationManagerBuilder:自定义认证策略
  • @EnableWebSecurity:开启WebSecurity模式

Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制)。

“认证”(Authentication)

身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。

身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。

“授权” (Authorization)

授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。

这个概念是通用的,而不是只在Spring Security 中存在。

认证和授权

1、引入 Spring Security 模块

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-security</artifactId>
  4. </dependency>

2、编写 Spring Security 配置类

参考官网:https://spring.io/projects/spring-security

查看我们自己项目中的版本,找到对应的帮助文档:

https://docs.spring.io/spring-security/site/docs/5.3.0.RELEASE/reference/html5 #servlet-applications 8.16.4

3、编写基础配置类

  1. @EnableWebSecurity // 开启WebSecurity模式
  2. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  3. @Override
  4. protected void configure(HttpSecurity http) throws Exception {
  5. }
  6. }

4、定制请求的授权规则

  1. @Override
  2. protected void configure(HttpSecurity http) throws Exception {
  3. // 定制请求的授权规则
  4. // 首页所有人可以访问
  5. http.authorizeRequests().antMatchers("/").permitAll()
  6. .antMatchers("/level1/**").hasRole("vip1")
  7. .antMatchers("/level2/**").hasRole("vip2")
  8. .antMatchers("/level3/**").hasRole("vip3");
  9. }

5、测试一下:发现除了首页都进不去了!因为我们目前没有登录的角色,因为请求需要登录的角色拥有对应的权限才可以!

6、在configure()方法中加入以下配置,开启自动配置的登录功能!

  1. // 开启自动配置的登录功能
  2. // /login 请求来到登录页
  3. // /login?error 重定向到这里表示登录失败
  4. http.formLogin();

7、测试一下:发现,没有权限的时候,会跳转到登录的页面!

8、查看刚才登录页的注释信息;

我们可以定义认证规则,重写configure(AuthenticationManagerBuilder auth)方法

  1. //定义认证规则
  2. @Override
  3. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  4. //在内存中定义,也可以在jdbc中去拿....
  5. auth.inMemoryAuthentication()
  6. .withUser("kuangshen").password("123456").roles("vip2","vip3")
  7. .and()
  8. .withUser("root").password("123456").roles("vip1","vip2","vip3")
  9. .and()
  10. .withUser("guest").password("123456").roles("vip1","vip2");
  11. }

9、测试,我们可以使用这些账号登录进行测试!发现会报错!

There is no PasswordEncoder mapped for the id “null”

10、原因,我们要将前端传过来的密码进行某种方式加密,否则就无法登录,修改代码

  1. //定义认证规则
  2. @Override
  3. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  4. //在内存中定义,也可以在jdbc中去拿....
  5. //Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
  6. //要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
  7. //spring security 官方推荐的是使用bcrypt加密方式。
  8. auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
  9. .withUser("zwt").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
  10. .and()
  11. .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
  12. .and()
  13. .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2");
  14. }

11、测试,发现,登录成功,并且每个角色只能访问自己认证下的规则!

权限控制和注销

1、开启自动配置的注销的功能

  1. //定制请求的授权规则
  2. @Override
  3. protected void configure(HttpSecurity http) throws Exception {
  4. //....
  5. //开启自动配置的注销的功能
  6. // /logout 注销请求
  7. http.logout();
  8. }

2、我们在前端,增加一个注销的按钮,index.html 导航栏中

3、我们可以去测试一下,登录成功后点击注销,发现注销完毕会跳转到登录页面!

4、但是,我们想让他注销成功后,依旧可以跳转到首页,该怎么处理呢?

  1. // .logoutSuccessUrl("/"); 注销成功来到首页
  2. http.logout().logoutSuccessUrl("/");

5、测试,注销完毕后,发现跳转到首页OK

6、我们现在又来一个需求:根据权限访问页面

我们需要结合thymeleaf中的一些功能

sec:authorize="isAuthenticated()":是否认证登录!来显示不同的页面

Maven依赖:

  1. <!-- https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity4 -->
  2. <dependency>
  3. <groupId>org.thymeleaf.extras</groupId>
  4. <artifactId>thymeleaf-extras-springsecurity5</artifactId>
  5. <version>3.0.4.RELEASE</version>
  6. </dependency>

7、修改我们的 前端页面

  1. 导入命名空间

8、重启测试,我们可以登录试试看,登录成功后确实,显示了我们想要的页面;

9、如果注销404了,就是因为它默认防止csrf跨站请求伪造,因为会产生安全问题,我们可以将请求改为post表单提交,或者在spring security中关闭csrf功能;

  1. http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
  2. http.logout().logoutSuccessUrl("/");

权限控制和注销搞定!

记住我

1、开启记住我功能

  1. //定制请求的授权规则
  2. @Override
  3. protected void configure(HttpSecurity http) throws Exception {
  4. //。。。。。。。。。。。
  5. //记住我
  6. http.rememberMe();
  7. }

原理: spring security 登录成功后,将cookie发送给浏览器保存,

以后登录带上这个cookie,只要通过检查就可以免登录了。

如果点击注销,则会删除这个cookie,具体的原理在JavaWeb阶段都讲过了,这里就不在多说了!

Shiro

Apache Shiro是一个Java的安全(权限)框架。

Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等。

三大核心组件

Shiro有三大核心组件,即Subject、SecurityManager和Realm

组件
Subject 用户,认证主体 应用代码直接交互的对象是Subject,Subject。包含Principals和Credentials两个信息
SecurityManager 管理所有用户,为安全管理员。 是Shiro架构的核心。与Subject的所有交互都会委托给SecurityManager, Subject相当于是一个门面,而SecurityManager才是真正的执行者。它负责与Shiro 的其他组件进行交互。
Realm 连接数据,是一个域。 可以把Realm看成DataSource,即安全数据源。

Pricipals:代表身份。可以是用户名、邮件、手机号码等等,用来标识一个登陆主题的身份。

Credentials:代表凭证。常见的有密码、数字证书等等。

在官网的例子中了解Shiro

  1. public class Quickstart {
  2. private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
  3. public static void main(String[] args) {
  4. Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
  5. SecurityManager securityManager = factory.getInstance();
  6. SecurityUtils.setSecurityManager(securityManager);
  7. // 获取当前用户
  8. Subject currentUser = SecurityUtils.getSubject();
  9. // 通过当前用户拿到session
  10. Session session = currentUser.getSession();
  11. //在session中存值
  12. session.setAttribute("someKey", "aValue");
  13. String value = (String) session.getAttribute("someKey");
  14. if (value.equals("aValue")) {
  15. log.info("Retrieved the correct value! [" + value + "]");
  16. }
  17. // 判断当前的用户是否被认证
  18. if (!currentUser.isAuthenticated()) {
  19. //token 令牌 随意设置
  20. UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
  21. //设置记住我
  22. token.setRememberMe(true);
  23. try {
  24. currentUser.login(token); //执行了登录操作
  25. } catch (UnknownAccountException uae) { //用户名不存在
  26. log.info("There is no user with username of " + token.getPrincipal());
  27. } catch (IncorrectCredentialsException ice) { //密码错误
  28. log.info("Password for account " + token.getPrincipal() + " was incorrect!");
  29. } catch (LockedAccountException lae) { //用户被锁定
  30. log.info("The account for username " + token.getPrincipal() + " is locked. " +
  31. "Please contact your administrator to unlock it.");
  32. }
  33. // ... catch more exceptions here (maybe custom ones specific to your application?
  34. catch (AuthenticationException ae) { //认证异常
  35. //unexpected condition? error?
  36. }
  37. }
  38. //获取当前用户的认证
  39. log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
  40. //获得当前用户的角色
  41. if (currentUser.hasRole("schwartz")) {
  42. log.info("May the Schwartz be with you!");
  43. } else {
  44. log.info("Hello, mere mortal.");
  45. }
  46. //是否拥有粗粒度(简单)权限
  47. if (currentUser.isPermitted("lightsaber:wield")) {
  48. log.info("You may use a lightsaber ring. Use it wisely.");
  49. } else {
  50. log.info("Sorry, lightsaber rings are for schwartz masters only.");
  51. }
  52. //是否拥有更高权限
  53. if (currentUser.isPermitted("winnebago:drive:eagle5")) {
  54. log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +
  55. "Here are the keys - have fun!");
  56. } else {
  57. log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
  58. }
  59. //注销
  60. currentUser.logout();
  61. //结束
  62. System.exit(0);
  63. }
  64. }

快速上手

导入依赖

  1. <!--shiro-->
  2. <dependency>
  3. <groupId>org.apache.shiro</groupId>
  4. <artifactId>shiro-spring</artifactId>
  5. <version>1.4.1</version>
  6. </dependency>

编写shiro配置类

  1. @Configuration
  2. public class ShiroConfig {
  3. //shiroFilterBean 第三步
  4. //DefaultWebSecurityManager 第二步
  5. //创建Realm对象 需要自定义类 第一步
  6. }

自定义Realm

  1. //自定义Realm 需要继承AuthorizingRealm
  2. public class UserRealm extends AuthorizingRealm {
  3. //授权
  4. @Override
  5. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  6. System.out.println("执行了授权=>");
  7. return null;
  8. }
  9. //认证
  10. @Override
  11. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  12. System.out.println("执行了认证");
  13. return null;
  14. }
  15. }

继续编写shiro配置类

  1. @Configuration
  2. public class ShiroConfig {
  3. //ShiroFilterFactoryBean 第三步
  4. @Bean
  5. public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager manager){
  6. ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
  7. //设置安全管理器
  8. filter.setSecurityManager(manager);
  9. return filter;
  10. }
  11. //DefaultWebSecurityManager 第二步
  12. @Bean(name="manager")
  13. public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
  14. DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
  15. //关联UserRealm
  16. manager.setRealm(userRealm);
  17. return manager;
  18. }
  19. //创建Realm对象 需要自定义类 第一步
  20. @Bean
  21. public UserRealm userRealm(){
  22. return new UserRealm();
  23. }
  24. }

实现登录拦截

  1. //ShiroFilterFactoryBean 第三步
  2. @Bean
  3. public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager manager){
  4. ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
  5. //设置安全管理器
  6. filter.setSecurityManager(manager);
  7. //增加shiro内置过滤器
  8. /**
  9. * anon: 无需认证就可以访问
  10. * authc: 必须认证才能访问
  11. * user: 必须拥有记住我功能才能访问
  12. * perms: 拥有对某个资源的权限才能访问
  13. * role:拥有某个角色权限才能访问
  14. */
  15. Map<String, String> map = new LinkedHashMap<>();
  16. map.put("/user/add","authc");
  17. map.put("/user/update","authc");
  18. filter.setFilterChainDefinitionMap(map);
  19. //设置登录页面
  20. filter.setLoginUrl("/login");
  21. return filter;
  22. }

用户认证

  1. //用户登录功能
  2. @PostMapping("/tologin")
  3. public String tologin(String username, String password, Model model){
  4. //获取用户
  5. Subject subject = SecurityUtils.getSubject();
  6. //封装用户登录数据并且生成一个token令牌
  7. UsernamePasswordToken token = new UsernamePasswordToken(username, password);
  8. try{
  9. subject.login(token);//登录 如果没有异常就说明OK了
  10. return "index";//返回首页
  11. }catch (UnknownAccountException e){
  12. model.addAttribute("msg","用户名错误");
  13. return "login";
  14. }catch (IncorrectCredentialsException e){
  15. model.addAttribute("msg","密码错误");
  16. return "login";
  17. }
  18. //认证
  19. @Override
  20. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  21. System.out.println("执行了认证");
  22. //用户名密码 数据库中取
  23. String name="admin";
  24. String password="123";
  25. UsernamePasswordToken userName=(UsernamePasswordToken)token;
  26. if (!userName.getUsername().equals(name)){
  27. return null;//抛出异常
  28. }
  29. //密码认证 shiro做
  30. return new SimpleAuthenticationInfo("",password,"");
  31. }

shiro整合mybais

导入依赖

  1. <!--spring boot整合mybatis-->
  2. <dependency>
  3. <groupId>org.mybatis.spring.boot</groupId>
  4. <artifactId>mybatis-spring-boot-starter</artifactId>
  5. <version>2.1.1</version>
  6. </dependency>
  7. <!--Mysql驱动-->
  8. <dependency>
  9. <groupId>mysql</groupId>
  10. <artifactId>mysql-connector-java</artifactId>
  11. <scope>runtime</scope>
  12. </dependency>
  13. <!--SpringbootJDBC-->
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-jdbc</artifactId>
  17. </dependency>

编写配置

  1. spring:
  2. thymeleaf:
  3. cache: false #关闭模板引擎的缓存
  4. # 配置数据源 serverTimezone=UTC 设置时区
  5. datasource:
  6. url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useSSL=true&useUnicode=true&characterEncoding=utf8
  7. username: root
  8. password: 123456
  9. driver-class-name: com.mysql.cj.jdbc.Driver
  10. mybatis:
  11. type-aliases-package: com.zwt.pojo
  12. mapper-locations: classpath:mapper/*.xml
  13. configuration:
  14. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

编写实体类,编写接口,编写映射文件

修改自定义Realm代码

  1. @Autowired
  2. private UserMapper userMapper;
  3. //认证
  4. @Override
  5. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  6. System.out.println("执行了认证");
  7. UsernamePasswordToken userName=(UsernamePasswordToken)token;
  8. //连接真实数据库
  9. User user = userMapper.queryUserbyName(userName.getUsername());
  10. if(user==null){ //没查出用户
  11. return null;
  12. }
  13. //密码认证 shiro做 密码加密
  14. return new SimpleAuthenticationInfo("",user.getPwd(),"");
  15. }

请求授权

编写Shiro过滤器

1.设置访问/user/add路径时,需要[user:add权限

2.没有此权限访问时,会跳转指定路径

  1. //ShiroFilterFactoryBean 第三步
  2. @Bean
  3. public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager manager){
  4. ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
  5. //设置安全管理器
  6. filter.setSecurityManager(manager);
  7. //增加shiro内置过滤器
  8. /**
  9. * anon: 无需认证就可以访问
  10. * authc: 必须认证才能访问
  11. * user: 必须拥有记住我功能才能访问
  12. * perms: 拥有对某个资源的权限才能访问
  13. * role:拥有某个角色权限才能访问
  14. */
  15. Map<String, String> map = new LinkedHashMap<>();
  16. // map.put("/user/add","authc");
  17. map.put("/user/update","authc");
  18. map.put("/user/add","perms[user:add]"); //访问此路径需要user:add权限
  19. filter.setFilterChainDefinitionMap(map);
  20. //设置登录页面
  21. filter.setLoginUrl("/login");
  22. filter.setUnauthorizedUrl("/noperms");//无权限时执行这个请求
  23. return filter;
  24. }

授权:

  1. //授权
  2. @Override
  3. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  4. System.out.println("执行了授权=>");
  5. SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
  6. info.addStringPermission("user:add");//对每个用户进行授权
  7. //取出用户信息
  8. Subject subject = SecurityUtils.getSubject();
  9. User principal = (User)subject.getPrincipal();
  10. //将用户信息的权限信息 设置进去
  11. //动态设置权限 需要新增一些数据库表 如:权限表
  12. //info.addStringPermission(principal.getParms());
  13. return info;
  14. }

SpringSecurity-Shiro-初见的更多相关文章

  1. Shiro 核心功能案例讲解 基于SpringBoot 有源码

    Shiro 核心功能案例讲解 基于SpringBoot 有源码 从实战中学习Shiro的用法.本章使用SpringBoot快速搭建项目.整合SiteMesh框架布局页面.整合Shiro框架实现用身份认 ...

  2. java 知识结构

    JAVA基础阶段 阶段 技术名称 技术内容 T线 JavaSE JAVA 开发基础知识 | Eclipse 开发环境 | JavaSE 7.0 API | JavaSE 8.0新特性 | 多线程技术 ...

  3. SpringBoot微服务框架

    springboot 是什么? 配置如何编写 yaml 自动装配原理 集成Web开发 集成数据库Druid 分布式开发:Dubbo(RPC)+zookeeper swagger:接口文档 任务调度 S ...

  4. 安全框架 SpringSecurity 和 Shiro 对比

    突然再次很想理一下权限的事,但是实在不知道实际情况选哪个框架好,现在整理下网上的资料,做一下对比. 1.Spring-security 对spring 结合较好,如果项目用的springmvc ,使用 ...

  5. 安全框架Shiro和SpringSecurity的比较

    来自:https://www.cnblogs.com/zoli/p/11236799.html 两个基本的概念 安全实体:系统需要保护的具体对象数据 权限:系统相关的功能操作,例如基本的CRUD Sh ...

  6. springmvc+spring+mybatis+maven项目集成shiro进行用户权限控制【转】

    项目结构:   1.maven项目的pom中引入shiro所需的jar包依赖关系 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...

  7. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(四)

    SpringSecurity(1) 其实啊,这部分我是最不想写的,因为最麻烦的也是这部分,真的是非常非常的麻烦.关于SpringSecurity的配置,让我折腾了好半天,网上的配置方式一大把,但总有一 ...

  8. Shiro简单配置

    注:这里只介绍Spring配置模式. 因为官方例子虽然中有更加简洁的ini配置形式,但是使用ini配置无法与spring整合.而且两种配置方法一样,只是格式不一样. 涉及的jar包 核心包shiro- ...

  9. Spring MVC 急速集成 Shiro 实录

    相信有很多的程序员,不愿意进行用户管理这块代码实现. 原因之一,不同的JavaEE 系统,用户管理都会有个性化的实现,逻辑很繁琐. 而且是系统门面,以后背锅的几率非常大,可谓是低收益高风险. 最近在系 ...

  10. Apache Shiro和Spring Security的详细对比

    参考资料: 1)Apache Shiro Apache Shiro:http://shiro.apache.org/ 在Web项目中应用 Apache Shiro:http://www.ibm.com ...

随机推荐

  1. 解决:无法从 Windows 应用商店下载。请检查网络连接

    今天在安装wsl的时候,装了几次一直中断,一直提示正在从Windows 应用商店下载,网络无法连接... 每次都是加载到2%就断了.网上搜了一圈,找到以下2种解决办法: 修改DNS把DNS修改为微软的 ...

  2. postman怎么调中文

    事先准备 1 安装好postman. 下载网址:https://www.postman.com/downloads/ 2 下载好app.zip中文压缩包,下载地址:https://wws.lanzou ...

  3. Flutter开发进阶学习指南Flutter开发进阶学习指南

    Flutter 的起源 Flutter 的诞生其实比较有意思,Flutter 诞生于 Chrome 团队的一场内部实验, 谷歌的前端团队在把前端一些"乱七八糟"的规范去掉后,发现在 ...

  4. javaSE面向对象编程

    面向对象编程 构造器 构造器就是和类名相同但无返回类型的方法. public class Person { //一个类即使什么都不写,它也会存在一个方法 //显示的定义构造器 String name; ...

  5. Spring Cloud Aliaba - Ribbon

    Ribbon(有关介绍见RestTemplate末尾) Ribbon负载均衡实现策略 Ribbon负载均衡实现策略通过接口IRule进行实现,默认使用ZoneAvoidanceRule规则进行负载均衡 ...

  6. filter,interceptor,controllerAdvice,aspect,controller执行顺序

    1.filter,这是java的过滤器,和框架无关的,是所有过滤组件中最外层的,从粒度来说是最大的. 配置方式,有直接实现Filter+@component,@Bean+@configuration( ...

  7. spring中的组合模式

    org.springframework.cache.support.CompositeCacheManager /* * Copyright 2002-2016 the original author ...

  8. Python语言系列-07-面向对象2

    重构父类__init__方法 #!/usr/bin/env python3 # author:Alnk(李成果) # 需求:Dog类要新增一个实例属性,但是Cat类不需要 class Animal(o ...

  9. 【笔记】模型泛化与岭回归与LASSO

    模型泛化与岭回归与LASSO 模型正则化 模型正则化,简单来说就是限制参数大小 模型正则化是用什么思路来解决先前过拟合的由于过于拟合导致的曲线抖动(线性方程前的系数都很大) 线性回归的目标就是求一个最 ...

  10. STM32—IIC通信(软件实现底层函数)

    使用GPIO引脚模拟SDA和SCL总线实现软件模拟IIC通信,IIC的具体通信协议层和物理层链接:IIC #ifndef __BSP_IIC_H #define __BSP_IIC_H #includ ...