SpringSecurity入门(一)

1、引入依赖

spring-boot版本2.7.3,如未特殊说明版本默认使用此版本

      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
  			<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

2、编写controller并启动springboot服务

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello(){
        return "hello SpringSecurity";
    }
}
  • 启动

image.png

  • 访问http://localhost:8080/

image.png

  • 登陆使用账号:user,密码:04e74f23-0e97-4ee9-957e-2004a2e60692

image.png

  • SecurityProperties

image.png

3、自动配置SpringBootWebSecurityConfiguration

  • SecurityFilterChainConfiguration

image.png

  • WebSecurityConfigurerAdapter中有所有的Security相关的配置,只需要继承重新对应属性即可完成自定义
  • 由于新版本的Security已经弃用WebSecurityConfigurerAdapter所以注册SecurityFilterChain即可
  @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity.authorizeRequests()
                .mvcMatchers("/index").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and().build();
    }

image.png

4、默认登陆页面DefaultLoginPageGeneratingFilter

image.png

4.1、SecurityFilterChainConfiguration默认实现的SecurityFilterChain

  • 容器中没有WebSecurityConfigurerAdapter类型的bean实例自动配置才会生效

image.png

4.2、UsernamePasswordAuthenticationFilter

image.png

4.3、attemptAuthentication方法

image.png

4.4、 ProviderManager的authenticate方法

image.png

4.5、 AuthenticationProvider实现AbstractUserDetailsAuthenticationProvider中的authenticate方法

image.png

4.6、 UserDetails实现类DaoAuthenticationProvider的retrieveUser方法

image.png

4.7、UserDetailsService实现类InMemoryUserDetailsManager的loadUserByUsername方法

image.png

4.8、 UserDetailsService

image.png

4.9、 UserDetailsServiceAutoConfiguration

image.png

  • 容器中没有:AuthenticationManager、AuthenticationProvider、UserDetailsService、AuthenticationManagerResolver这4个bean实例才会加载InMemoryUserDetailsManager

image.png
image.png

4.10、 SecurityProperties

image.png
image.png
image.png

  • 可以通过spring.security.user.password=123456自定义密码

5、 自定义认证

5.1、由于新版本的Security已经弃用WebSecurityConfigurerAdapter所以注册SecurityFilterChain即可

github示例

    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity.authorizeRequests()
                .mvcMatchers("/index").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and().build();
    }

5.2、 自定义登陆页面

5.2.1、html

  • 使用UsernamePasswordAuthenticationFilter用户名和密码字段名必须是username和password,且必须是POST的方式提交

image.png

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<form th:action="@{/doLogin}" method="post">
    <p>用户名:<label>
        <input name="username" type="text"/>
    </label></p>
    <p>密码:<label>
        <input name="password" type="password"/>
    </label></p>
    <p>
        <input type="submit">
    </p>
</form>

</body>
</html>

5.2.2、SecurityFilterChain配置

@Configuration
public class WebSecurityConfigurer {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return
                //开启权限验证
                httpSecurity.authorizeRequests()
                //permitAll直接放行,必须在anyRequest().authenticated()前面
                .mvcMatchers("/toLogin").permitAll()
                .mvcMatchers("/index").permitAll()
                //anyRequest所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                //使用form表单验证
                .formLogin()
                //自定义登陆页面
                .loginPage("/toLogin")
                //自定义登陆页面后必须指定处理登陆请求的url
                .loginProcessingUrl("/doLogin")
                .and()
                 //禁止csrf跨站请求保护
                .csrf().disable()
                .build();
    }

5.2.3、 controller

@Controller
public class LoginController {

    @RequestMapping("toLogin")
    public String toLogin(){
        return "login";
    }
}

5.2.4、 自定义登陆使用的用户名和密码字段名使用usernameParameter和passwordParameter

@Configuration
public class WebSecurityConfigurer {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return
                //开启权限验证
                httpSecurity.authorizeRequests()
                //permitAll直接放行,必须在anyRequest().authenticated()前面
                .mvcMatchers("/toLogin").permitAll()
                .mvcMatchers("/index").permitAll()
                //anyRequest所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                //使用form表单验证
                .formLogin()
                //自定义登陆页面
                .loginPage("/toLogin")
                //自定义登陆页面后必须指定处理登陆请求的url
                .loginProcessingUrl("/doLogin")
//               自定义接收用户名的参数名为uname
                .usernameParameter("uname")
//               自定义接收密码的参数名为pwd
                .passwordParameter("pwd")
                .and()
                 //禁止csrf跨站请求保护
                .csrf().disable()
                .build();
    }
}
  • form表单中对应参数名也需要修改,用户名为:uname,密码为:pwd

image.png

5.3、 自定义认证成功后访问的页面

  • successForwardUrl(转发),必须使用POST请求,每次都会跳转到指定请求
  • defaultSuccessUrl(重定向),必须使用GET请求,不会每次都跳转定义的页面,默认会记录认证拦截的请求,如果是拦截的受限资源会优先跳转到之前被拦截的请求。需要每次都跳转使用.defaultSuccessUrl(“/test”,true)即可

image.png

  • 二选一
//               登陆认证成功后跳转的页面(转发),必须使用POST请求
//                .successForwardUrl("/test")
//               陆认证成功后跳转的页面(重定向),必须使用GET请求
                 .defaultSuccessUrl("/test",true)

5.4、 前后端分离处理方式

image.png

5.4.1、 实现AuthenticationSuccessHandler接口

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Map<String,Object> map = new HashMap<>();
        map.put("msg", "登陆成功");
        map.put("code", HttpStatus.OK);
        map.put("authentication", authentication);
        String s = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(s);
    }
}

5.4.2、修改SecurityFilterChain配置

  • 使用successHandler(new MyAuthenticationSuccessHandler())
@Configuration
public class WebSecurityConfigurer {

    @Bean
    @SuppressWarnings("all")
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return
                //开启权限验证
                httpSecurity.authorizeRequests()
                //permitAll直接放行,必须在anyRequest().authenticated()前面
                .mvcMatchers("/toLogin").permitAll()
                .mvcMatchers("/index").permitAll()
                //anyRequest所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                //使用form表单验证
                .formLogin()
                //自定义登陆页面
                .loginPage("/toLogin")
                //自定义登陆页面后必须指定处理登陆请求的url
                .loginProcessingUrl("/doLogin")
//               自定义接收用户名的参数名为uname
                .usernameParameter("uname")
//               自定义接收密码的参数名为pwd
                .passwordParameter("pwd")
//               登陆认证成功后跳转的页面(转发),必须使用POST请求
//                .successForwardUrl("/test")
//               陆认证成功后跳转的页面(转发),必须使用GET请求
//                 .defaultSuccessUrl("/test",true)
                 //不会每次都跳转定义的页面,默认会记录认证拦截的请求,如果是拦截的受限资源会优先跳转到之前被拦截的请求。需要每次都跳转使defaultSuccessUrl("/test",true)
//                 .defaultSuccessUrl("/test")
//                前后端分离时代自定义认证成功处理
                .successHandler(new MyAuthenticationSuccessHandler())
                .and()
                 //禁止csrf跨站请求保护
                .csrf().disable()
                .build();
    }
}

5.4.3、返回数据

image.png

6、 认证失败处理

  • failureForwardUrl,转发,请求必须是POST
  • failureUrl,重定向,请求必须是GET

6.1、org.springframework.security.authentication.ProviderManager#authenticate

image.png

6.2、 org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter#doFilter(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain)

image.png

6.3、 org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter#unsuccessfulAuthentication

image.png

6.4、 org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler#onAuthenticationFailure

image.png

6.5、 org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler#saveException

image.png

  • 如果是转发异常信息存在request里面
  • 如果是重定向异常信息存在session里面,默认是重定向
  • 参数名:SPRING_SECURITY_LAST_EXCEPTION

6.7、 前端取值展示

  • 修改SecurityFilterChain配置
@Configuration
public class WebSecurityConfigurer {

    @Bean
    @SuppressWarnings("all")
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return
                //开启权限验证
                httpSecurity.authorizeRequests()
                //permitAll直接放行,必须在anyRequest().authenticated()前面
                .mvcMatchers("/toLogin").permitAll()
                .mvcMatchers("/index").permitAll()
                //anyRequest所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                //使用form表单验证
                .formLogin()
                //自定义登陆页面
                .loginPage("/toLogin")
                //自定义登陆页面后必须指定处理登陆请求的url
                .loginProcessingUrl("/doLogin")
//               自定义接收用户名的参数名为uname
                .usernameParameter("uname")
//               自定义接收密码的参数名为pwd
                .passwordParameter("pwd")
//               登陆认证成功后跳转的页面(转发),必须使用POST请求
//                .successForwardUrl("/test")
//               陆认证成功后跳转的页面(转发),必须使用GET请求
//                 .defaultSuccessUrl("/test",true)
                 //不会每次都跳转定义的页面,默认会记录认证拦截的请求,如果是拦截的受限资源会优先跳转到之前被拦截的请求。需要每次都跳转使defaultSuccessUrl("/test",true)
//                 .defaultSuccessUrl("/test")
//                前后端分离时代自定义认证成功处理
                .successHandler(new MyAuthenticationSuccessHandler())
//               认证失败跳转页面,必须使用POST请求         
                .failureForwardUrl("/toLogin")
            //  认证失败跳转页面,,必须使用GET请求
                // .failureUrl("/toLogin")
                .and()
                 //禁止csrf跨站请求保护
                .csrf().disable()
                .build();
    }
}
  • html增加取值
<!--  重定向错误信息存在session中  -->
<p th:text="${session.SPRING_SECURITY_LAST_EXCEPTION}"></p>
<!--  转发错误信息存在request中  -->
<p th:text="${SPRING_SECURITY_LAST_EXCEPTION}"></p>

6.8、 前后端分离处理方式

image.png

6.8.1、 实现AuthenticationFailureHandler接口

public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        Map<String,Object> map = new HashMap<>();
        map.put("msg", exception.getMessage());
        map.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
        String s = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(s);
    }
}

6.8.2、修改SecurityFilterChain配置

  • failureHandler
@Configuration
public class WebSecurityConfigurer {

    @Bean
    @SuppressWarnings("all")
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return
                //开启权限验证
                httpSecurity.authorizeRequests()
                //permitAll直接放行,必须在anyRequest().authenticated()前面
                .mvcMatchers("/toLogin").permitAll()
                .mvcMatchers("/index").permitAll()
                //anyRequest所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                //使用form表单验证
                .formLogin()
                //自定义登陆页面
                .loginPage("/toLogin")
                //自定义登陆页面后必须指定处理登陆请求的url
                .loginProcessingUrl("/doLogin")
//               自定义接收用户名的参数名为uname
                .usernameParameter("uname")
//               自定义接收密码的参数名为pwd
                .passwordParameter("pwd")
//               登陆认证成功后跳转的页面(转发),必须使用POST请求
//                .successForwardUrl("/test")
//               陆认证成功后跳转的页面(转发),必须使用GET请求
//                 .defaultSuccessUrl("/test",true)
                 //不会每次都跳转定义的页面,默认会记录认证拦截的请求,如果是拦截的受限资源会优先跳转到之前被拦截的请求。需要每次都跳转使defaultSuccessUrl("/test",true)
//                 .defaultSuccessUrl("/test")
//                前后端分离时代自定义认证成功处理
                .successHandler(new MyAuthenticationSuccessHandler())
//               认证失败跳转页面,必须使用POST请求
//                .failureForwardUrl("/toLogin")
//               认证失败跳转页面,必须使用GET请求
//                 .failureUrl("/toLogin")
//               前后端分离时代自定义认证失败处理
                .failureHandler(new MyAuthenticationFailureHandler())
                .and()
                 //禁止csrf跨站请求保护
                .csrf().disable()
                .build();
    }
}

7、 注销登录

7.1、 默认方式

.logout()
// 指定注销url,默认请求方式GET
.logoutUrl(“/logout”)
// 注销成功后跳转页面
.logoutSuccessUrl(“/toLogin”)

@Configuration
public class WebSecurityConfigurer {

    @Bean
    @SuppressWarnings("all")
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return
                //开启权限验证
                httpSecurity.authorizeRequests()
                //permitAll直接放行,必须在anyRequest().authenticated()前面
                .mvcMatchers("/toLogin").permitAll()
                .mvcMatchers("/index").permitAll()
                //anyRequest所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                //使用form表单验证
                .formLogin()
                //自定义登陆页面
                .loginPage("/toLogin")
                //自定义登陆页面后必须指定处理登陆请求的url
                .loginProcessingUrl("/doLogin")
//               自定义接收用户名的参数名为uname
                .usernameParameter("uname")
//               自定义接收密码的参数名为pwd
                .passwordParameter("pwd")
//               登陆认证成功后跳转的页面(转发),必须使用POST请求
//                .successForwardUrl("/test")
//               陆认证成功后跳转的页面(转发),必须使用GET请求
//                 .defaultSuccessUrl("/test",true)
                 //不会每次都跳转定义的页面,默认会记录认证拦截的请求,如果是拦截的受限资源会优先跳转到之前被拦截的请求。需要每次都跳转使defaultSuccessUrl("/test",true)
//                 .defaultSuccessUrl("/test")
//                前后端分离时代自定义认证成功处理
                .successHandler(new MyAuthenticationSuccessHandler())
//               认证失败跳转页面,必须使用POST请求
//                .failureForwardUrl("/toLogin")
//               认证失败跳转页面,必须使用GET请求
//                 .failureUrl("/toLogin")
//               前后端分离时代自定义认证失败处理
                .failureHandler(new MyAuthenticationFailureHandler())
                .and()
//               注销
                .logout()
//               指定注销url,默认请求方式GET
                .logoutUrl("/logout")
//               销毁session,默认为true
                .invalidateHttpSession(true)
//               清除认证信息,默认为true
                .clearAuthentication(true)
//               注销成功后跳转页面
                .logoutSuccessUrl("/toLogin")
                .and()
                 //禁止csrf跨站请求保护
                .csrf().disable()
                .build();
    }
}

7.2、 自定义方式

// 注销
.logout()
// 自定义注销url
.logoutRequestMatcher(newOrRequestMatcher(
newAntPathRequestMatcher(“/aa”,“GET”),
newAntPathRequestMatcher(“/bb”,“POST”)
))
// 注销成功后跳转页面
.logoutSuccessUrl(“/toLogin”)

@Configuration
public class WebSecurityConfigurer {

    @Bean
    @SuppressWarnings("all")
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return
                //开启权限验证
                httpSecurity.authorizeRequests()
                //permitAll直接放行,必须在anyRequest().authenticated()前面
                .mvcMatchers("/toLogin").permitAll()
                .mvcMatchers("/index").permitAll()
                //anyRequest所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                //使用form表单验证
                .formLogin()
                //自定义登陆页面
                .loginPage("/toLogin")
                //自定义登陆页面后必须指定处理登陆请求的url
                .loginProcessingUrl("/doLogin")
//               自定义接收用户名的参数名为uname
                .usernameParameter("uname")
//               自定义接收密码的参数名为pwd
                .passwordParameter("pwd")
//               登陆认证成功后跳转的页面(转发),必须使用POST请求
//                .successForwardUrl("/test")
//               陆认证成功后跳转的页面(转发),必须使用GET请求
//                 .defaultSuccessUrl("/test",true)
                 //不会每次都跳转定义的页面,默认会记录认证拦截的请求,如果是拦截的受限资源会优先跳转到之前被拦截的请求。需要每次都跳转使defaultSuccessUrl("/test",true)
//                 .defaultSuccessUrl("/test")
//                前后端分离时代自定义认证成功处理
                .successHandler(new MyAuthenticationSuccessHandler())
//               认证失败跳转页面,必须使用POST请求
//                .failureForwardUrl("/toLogin")
//               认证失败跳转页面,必须使用GET请求
//                 .failureUrl("/toLogin")
//               前后端分离时代自定义认证失败处理
                .failureHandler(new MyAuthenticationFailureHandler())
                .and()
//               注销
                .logout()
//               指定注销url,默认请求方式GET
//                .logoutUrl("/logout")
                .logoutRequestMatcher(new OrRequestMatcher(
                        new AntPathRequestMatcher("/aa","GET"),
                        new AntPathRequestMatcher("/bb","POST")
                ))
//               销毁session,默认为true
                .invalidateHttpSession(true)
//               清除认证信息,默认为true
                .clearAuthentication(true)
//               注销成功后跳转页面
                .logoutSuccessUrl("/toLogin")
                .and()
                 //禁止csrf跨站请求保护
                .csrf().disable()
                .build();
    }
}

7.3、 前后端分离

image.png

7.3.1、 实现LogoutSuccessHandler接口

public class MyLogoutSuccessHandler implements LogoutSuccessHandler {

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Map<String,Object> map = new HashMap<>();
        map.put("msg", "注销成功");
        map.put("code", HttpStatus.OK.value());
        map.put("authentication", authentication);
        String s = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(s);
    }
}

7.3.2、 修改SecurityFilterChain配置

  • logoutSuccessHandler
@Configuration
public class WebSecurityConfigurer {

    @Bean
    @SuppressWarnings("all")
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return
                //开启权限验证
                httpSecurity.authorizeRequests()
                //permitAll直接放行,必须在anyRequest().authenticated()前面
                .mvcMatchers("/toLogin").permitAll()
                .mvcMatchers("/index").permitAll()
                //anyRequest所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                //使用form表单验证
                .formLogin()
                //自定义登陆页面
                .loginPage("/toLogin")
                //自定义登陆页面后必须指定处理登陆请求的url
                .loginProcessingUrl("/doLogin")
//               自定义接收用户名的参数名为uname
                .usernameParameter("uname")
//               自定义接收密码的参数名为pwd
                .passwordParameter("pwd")
//               登陆认证成功后跳转的页面(转发),必须使用POST请求
//                .successForwardUrl("/test")
//               陆认证成功后跳转的页面(转发),必须使用GET请求
//                 .defaultSuccessUrl("/test",true)
                 //不会每次都跳转定义的页面,默认会记录认证拦截的请求,如果是拦截的受限资源会优先跳转到之前被拦截的请求。需要每次都跳转使defaultSuccessUrl("/test",true)
//                 .defaultSuccessUrl("/test")
//                前后端分离时代自定义认证成功处理
                .successHandler(new MyAuthenticationSuccessHandler())
//               认证失败跳转页面,必须使用POST请求
//                .failureForwardUrl("/toLogin")
//               认证失败跳转页面,必须使用GET请求
//                 .failureUrl("/toLogin")
//               前后端分离时代自定义认证失败处理
                .failureHandler(new MyAuthenticationFailureHandler())
                .and()
//               注销
                .logout()
//               指定默认注销url,默认请求方式GET
//                .logoutUrl("/logout")
//               自定义注销url
                .logoutRequestMatcher(new OrRequestMatcher(
                        new AntPathRequestMatcher("/aa","GET"),
                        new AntPathRequestMatcher("/bb","POST")
                ))
//               销毁session,默认为true
                .invalidateHttpSession(true)
//               清除认证信息,默认为true
                .clearAuthentication(true)
//               注销成功后跳转页面
//                .logoutSuccessUrl("/toLogin")
                .logoutSuccessHandler(new MyLogoutSuccessHandler())
                .and()
                 //禁止csrf跨站请求保护
                .csrf().disable()
                .build();
    }
}

相关文章

SpringSecurity入门(二)

SpringSecurity入门(三)

SpringSecurity入门(四)

未完待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/701810.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】基础IO [万字之作]

目录 一.重谈文件 二.重谈C文件操作 1.操作 1.文件的打开和关闭 2.文件的读写操作 ​编辑 1.fgetc函数 2.fputc函数 3.fputs函数 4.fgets函数 5.fprintf函数 6.fscanf函数 7.fread函数 8.fwrite函数 三.重谈当前路径 四.系统文件操作接口 1.Open函数 2.write函数 3…

hot100 -- 栈

目录 &#x1f6a9;有效的括号 &#x1f33c;最小栈 AC 栈 AC 链表 &#x1f33c;字符串解码 &#x1f43b;每日温度 &#x1f352;柱状图中的最大矩形 解释 AC 单调栈 &#x1f6a9;有效的括号 20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 1&#xf…

[初阶数据结构] 包装类 | 泛型

目录 一. 包装类 1.1 什么是包装类? 1.2 包装类的意义 1.3 基本数据类型与包装类 1.4 装箱 1.5 拆箱 1.6 小总结 二. 泛型 2.1 什么是泛型? 2.2 泛型的意义 2.3 泛型的语法 2.4 泛型的编译 2.4.1 下载插件 2.4.2 分析 2.5 上界 2.6 泛型方法 2.7 小总结 三. 总结 一.…

conda虚拟环境,安装pytorch cuda cudnn版本一致,最简单方式

1、pytorch版本安装&#xff08;卸载也会有问题&#xff09; &#xff08;1&#xff09;版本如何选择参考和卸载 https://zhuanlan.zhihu.com/p/401931724 &#xff08;2&#xff09;对应版本如何安装命令 https://pytorch.org/get-started/previous-versions/ 最简答安装参考…

递推算法及相关问题详解

目录 递推的概念 训练&#xff1a;斐波那契数列 解析 参考代码 训练&#xff1a;上台阶 参考代码 训练&#xff1a;信封 解析 参考代码 递推的概念 递推是一种处理问题的重要方法。 递推通过对问题的分析&#xff0c;找到问题相邻项之间的关系&#xff08;递推式&a…

实验滤膜等分切割器八等分90mm

名称:滤膜切分器 型号: RNKF-90 适用范围:切分φ90mm玻璃纤维滤膜、石英纤维滤膜 等分数:2等分、4等分、8等分 使用方法: 1、开盖:逆时针旋转防尘盖&#xff0c;与切分台分开后&#xff0c;轻放于台面。 2、放膜:持专用镊子,镊子的长尖在下,短尖在上,取待切分滤膜1片,采样…

配置响应拦截器,全局前置导航守卫

1&#xff1a;配置响应拦截器 响应拦截器&#xff0c;统一处理接口的错误 问题&#xff1a;每次请求&#xff0c;都会有可能会错误&#xff0c;就都需要错误提示 说明&#xff1a;响应拦截器是咱们拿到数据的 第一个 数据流转站&#xff0c;可以在里面统一处理错误。 // 添…

uniapp小程序计算地图计算距离

我们拿到自身和目标距离经纬度 调用此方法即可计算出自身与目标的距离 最后我所展示的页面如下 具体效果可能会有点偏差 要求严格的可以在精细的计算一下

ant组件库日期选择器汉化

ant组件库日期选择器默认英文 如何汉化 跟着官网走不能完全实现汉化。 这里提供一个解决方案&#xff0c;首先&#xff0c;通过pnpm下载moment包。 然后引入和注册文件&#xff1a; import zhCN from ant-design-vue/es/locale/zh_CN;import moment from moment;moment.loca…

vue30:v-model语法糖的本质

在Vue.js框架中&#xff0c;v-model 是一个指令&#xff0c;用于在表单输入和应用状态之间创建双向数据绑定。它本质上是语法糖&#xff0c;意味着它提供了一种更简洁的方式来编写代码&#xff0c;而不需要显式地编写额外的代码。 具体来说&#xff0c;v-model 背后实际上是由…

外汇天眼:Equals集团发布战略评估通知:MDP不再考虑收购提议

Equals Group plc (LON)今天发布了一份关于其战略评估的通知。 Equals公司不再与Madison Dearborn Partners, LLC (MDP)就公司的收购提议进行讨论。MDP因此发布了一份声明&#xff0c;确认其不打算为公司提出收购提议。 然而&#xff0c;MDP与其投资组合公司MoneyGram Interna…

台式电脑怎么连WiFi?4个宝藏方法收藏好!

“我有一部台式电脑&#xff0c;现在不知道应该怎么操作才能让电脑正确连接WiFi&#xff0c;不知道大家有什么简单的连接方法吗&#xff1f;希望可以给我出出主意。” 随着无线网络的普及和科技的飞速发展&#xff0c;越来越多人选择使用WiFi来连接互联网。对于笔记本电脑和移动…

计算机网络(3) 字节顺序:网络字节序与IPv4

一.小端与大端 小端&#xff08;Little endian&#xff09;&#xff1a;低字节保存在内存低地址&#xff0c;高字节保存在内存高地址。 大端&#xff08;Big endian&#xff09;&#xff1a;低字节保存在内存高地址&#xff0c;高字节保存在内存低地址。 例如&#xff08;14…

Android 中USB-HID协议实现

前言 所有通过USB连接android设备进行通讯的步骤都是大同小异&#xff1a;查询usb设备列表 ——>匹配对应的设备类型&#xff08;如productid , vendorId&#xff09;等——>连接usb设备&#xff0c;找到连接通讯的节点——>配置通讯信息&#xff0c;进行通讯。以上是…

Java数据结构之ArrayList(如果想知道Java中有关ArrayList的知识点,那么只看这一篇就足够了!)

前言&#xff1a;ArrayList是Java中最常用的动态数组实现之一&#xff0c;它提供了便捷的操作接口和灵活的扩展能力&#xff0c;使得在处理动态数据集合时非常方便。本文将深入探讨Java中ArrayList的实现原理、常用操作以及一些使用场景。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨…

鸿蒙开发:通过startAbilityByType拉起垂类应用

通过startAbilityByType拉起垂类应用 使用场景 开发者可通过特定的业务类型如导航、金融等&#xff0c;调用startAbilityByType接口拉起对应的垂域面板&#xff0c;该面板将展示目标方接入的垂域应用&#xff0c;由用户选择打开指定应用以实现相应的垂类意图。垂域面板为调用…

Linux网络编程(二)Socket编程

Socket编程 一、网络套接字概念&#xff1a;socket 一个文件描述符指向一个套接字&#xff08;该套接字内部由内核借助两个缓冲区实现。&#xff09;在通信过程中&#xff0c; 套接字一定是成对出现的。二、网络字节序和主机字节序的转换函数&#xff08;ip和端口&#xff09…

代码随想录算法训练营第二十一天|530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

530.二叉搜索树的最小绝对差 题目链接&#xff1a;530.二叉搜索树的最小绝对差 文档讲解&#xff1a;代码随想录 状态&#xff1a;还可以 思路&#xff1a;使用中序遍历来遍历二叉搜索树。在中序遍历过程中&#xff0c;比较当前节点和前驱节点的值&#xff0c;更新最小差值。返…

中国四大高原矢量示意图分享

我们在《中国地势三级阶梯示意图分享》一文中&#xff0c;为你分享了中国三级阶梯示意图的矢量文件。 现在&#xff0c;我们再为你分享中国四大高原的矢量示意图文件&#xff0c;你可以在文末查看文件的领取方法。 我国四大高原是如何划分的&#xff1f; 中国四大高原分别为…

你觉得前端开发人员有必要学习Rust吗?

有必要&#xff0c;为什么&#xff1f; 1. 性能优势 Rust能编译成高效的机器码&#xff0c;这对于需要高性能处理的前端项目尤其有利。例如&#xff0c;处理复杂的数据计算或图像处理时&#xff0c;Rust可以提供接近于C/C的性能&#xff0c;同时避免诸如内存泄漏或缓冲区溢出…