当前位置: 首页 > news >正文

spring指南学习随记(一)

一、creating aysnchronous methods(创建异步方法)

对应网址:入门指南 | 创建异步方法 --- Getting Started | Creating Asynchronous Methods

1.@JsonIgnorePropertise 该注解加在实体类上,用于配置json映射到实体类的规则(反序列化)。参数有ignoreUnknown=true,意为Jackson在反序列化过程中,如果碰到json对象结构中有的属性,实体类中没有则自动忽略。若不配置ignoreUnknown=ture,则遇到json有属性找不到对应实体类属性时,则会报错:unrecognizedpropertyException(无法识别属性错误)。

2.RestTemplate对象的用法

首先,restTemplate是为了简化restful风格的uri操作而设计的通用模版类。

自动注入和构建(通过RestTemplateBuilder):

       在spring的各类组件中用该结构自动注入RestTemplate实例

private final RestTemplate restTemplate;public GitHubLookupService(RestTemplateBuilder restTemplateBuilder) {this.restTemplate = restTemplateBuilder.build();}

2.1方法举例:

User results = restTemplate.getForObject(url, User.class);

getForObject方法简化网络请求过程,url参数意为要请求的url地址,User.class意为获取的json对象要自动映射的java类。

3.@Async注解:将方法标记为异步方法,若异步方法有返回对象,就需要CompletableFuture类来作为异步操作时的对象容器。因为异步操作时,异步执行的方法不占用主线程,所以线程池中线程执行完主线程后,会通过该容器修改异步方法执行状态。

流程:当主线程执行时遇到@Async注解标注的方法之后会将内部代码移交到线程池中线程执行,而主线程则先获得CompletableFuture.completedFuture(results),当线程池执行完异步逻辑后会修改CompletableFuture对应实例状态,并加入具体实例。然后后面就可以使用.get方法获取。

注意:要使用@Async注解一定要让方法在spring管理的组件内。

        3.1如何让springboot程序可以运行呢?

首先:要在程序的入口文件上加上注解@EnableAsync,这样就开启了spring的多线程能力,同时会默认使用内置的ThreadPoolTaskExecutor作为线程池,我们也可以通过在入口类中添加返回方法返回Executor对象实例来自定义线程池细节,应用启动后,spring会自动识别自定义线程池环境,为异步执行提供支持。


@Bean
public Executor taskExecutor(){ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//自定义线程池细节executor.setCorePoolSize(2);executor.setMaxPoolSize(2);executor.setQueueCapacity(500);executor.setThreadNamePrefix("GithubLookup-")executor.initialize();
return executor;
}

二、authenticating a User with LDAP(用LDAP验证用户)

对应网址:入门指南 | 使用 LDAP 验证用户 --- Getting Started | Authenticating a User with LDAP

1.引入依赖

<!--spring boot 自动配置的核心依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--LDAP的操作封装,不涉及安全方面,主要是简化crud操作和连接管理-->
<dependency><groupId>org.springframework.ldap</groupId><artifactId>spring-ldap-core</artifactId>
</dependency>
<!--上面两者的桥接组件,提供LDAP绑定认证的实现-->
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-ldap</artifactId>
</dependency>
<!--提供高性能的LDAP协议实现,支持SSL/TLS加密链接等等,纯java的LDAPv3协议栈
同时还引入了内置的LDAP服务器-->
<dependency><groupId>com.unboundid</groupId><artifactId>unboundid-ldapsdk</artifactId>
</dependency>

2.构建配置类,并填写验证过滤规则

@Configuration
class WebSecurityConfig {//自定义SpringSecurity的核心过滤链类SecurityFilterChain的验证规则@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {//调用链httpSecurity.authorizeHttpRequests(requests-> {requests.anyRequest().fullyAuthenticated();}).formLogin(Customizer.withDefaults());//用自定义器定义使用默认数据登录,获取相关资源。return httpSecurity.build();}//定义如何验证用户登录规则@Autowiredpublic void configure(AuthenticationManagerBuilder auth) throws Exception {auth    //配置使用ldapAuthentication的验证方式.ldapAuthentication()//定义在ldap服务器目录中查找的DN路径.userDnPatterns("uid={0},ou=people")//这里的ou是为了查询用户对应的组而确定应该给的权限.groupSearchBase("ou=groups").contextSource()//这里我们通过url配置访问ldap服务器,并拼接上我们的根目录路径(即DC).url("ldap://localhost:8389/dc=springframework,dc=org").and()//这里我们将用户输入的密码加密后,对比ldap中的密码进而验证密码//注意这里的lDAP服务器中的密码加密方式要和passwordEncoder一致。.passwordCompare().passwordEncoder(new BCryptPasswordEncoder()).passwordAttribute("userPassword");}

这里涉及到对LDAP结构的了解和LDIF的相关知识。

3.编写LDAP服务器的配置类(内嵌)

#LDAP相关配置#指定访问的服务器的根目录DN(类似路径)
spring.ldap.embedded.base-dn=dc=springframework,dc=org#指定初始化的数据文件
spring.ldap.embedded.ldif=classpath:test-server.ldif#指定内嵌的LDAP服务器的端口
spring.ldap.embedded.port=8389

        3.1配置中指定的test-server.ldif文件内容如下(classpath:表示默认从resources目录下寻找)

dn: dc=springframework,dc=org
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: springframeworkdn: ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groupsdn: ou=subgroups,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: subgroupsdn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: peopledn: ou=space cadets,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: space cadetsdn: ou=\"quoted people\",dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: "quoted people"dn: ou=otherpeople,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: otherpeopledn: uid=ben,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Ben Alex
sn: Alex
uid: ben
userPassword: $2a$10$c6bSeWPhg06xB1lvmaWNNe4NROmZiSpYhlocU/98HNr2MhIOiSt36dn: uid=bob,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Bob Hamilton
sn: Hamilton
uid: bob
userPassword: bobspassworddn: uid=joe,ou=otherpeople,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Joe Smeth
sn: Smeth
uid: joe
userPassword: joespassworddn: cn=mouse\, jerry,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Mouse, Jerry
sn: Mouse
uid: jerry
userPassword: jerryspassworddn: cn=slash/guy,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: slash/guy
sn: Slash
uid: slashguy
userPassword: slashguyspassworddn: cn=quote\"guy,ou=\"quoted people\",dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: quote\"guy
sn: Quote
uid: quoteguy
userPassword: quoteguyspassworddn: uid=space cadet,ou=space cadets,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Space Cadet
sn: Cadet
uid: space cadet
userPassword: spacecadetspassworddn: cn=developers,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: developers
ou: developer
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org
uniqueMember: uid=bob,ou=people,dc=springframework,dc=orgdn: cn=managers,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: managers
ou: manager
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org
uniqueMember: cn=mouse\, jerry,ou=people,dc=springframework,dc=orgdn: cn=submanagers,ou=subgroups,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: submanagers
ou: submanager
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org

4.最后设置Controller页面(就是正常业务逻辑的controller)


@RestController
class HomeController {@GetMapping("/")public String index(){return "欢迎来到我的应用";}
}

5.验证,启动服务并访问应用服务后,会自动跳转到LDAP服务验证界面(我们之前配置过使用的是默认的界面),输入用户:ben 密码:benspassword,即可通过授权。

6.bug出现与解读:

6.1因为在自动配置SecurityFilterChain过程中我注入bean的方法名好巧不巧使用的是springSecurityFilterChain,这就导致报错:说找不到我方法中自动注入的HttpSecurity.

6.2原因分析:因为我使用的是SpringBoot3.5.5对应的SpringSecurity的版本是6.x,6版本以后虽然强制用户要自定义过滤链,但是在旧版本中若用户没有定义SecurityFilterChain则会自动注入默认的过滤链,好巧不巧,我自定义的方法名又是springSecurityFilterChain,并且我还没有在@Bean中用name属性自定义bean名称,spring自动使用方法名作为bean名。另外SpringSecurity是兼容旧版本的,所以当检测到有名称为springSecurityFilterChain时,会默认其具有最高优先级,进行提前注入,而恰恰因为此,HttpSecurity还没有被注册,就没有bean实例,故而报错。

6.3修改了方法名为securityFilterChain,则成功!

7.成果

访问localhost:1314/(我的服务器地址)会自动跳转到localhost:1314/login进行登录,从而调用验证逻辑,

此时

        若输入正确的账户和密码:ben   benspassword则跳转到正确映射

若密码或用户名输入错误,则提示:


文章转载自:

http://H6cuwGIT.dwgcx.cn
http://Yr3OmRX3.dwgcx.cn
http://E3CRfQa6.dwgcx.cn
http://56K5OyH0.dwgcx.cn
http://ScwwM99H.dwgcx.cn
http://qblt04mQ.dwgcx.cn
http://rIkWD865.dwgcx.cn
http://eynDA44X.dwgcx.cn
http://g9iO4r9r.dwgcx.cn
http://sqbldXyx.dwgcx.cn
http://WduAROIx.dwgcx.cn
http://QFRjmFrJ.dwgcx.cn
http://94bwkPne.dwgcx.cn
http://F9Q2oHQQ.dwgcx.cn
http://M9UMqU5B.dwgcx.cn
http://F5mMM142.dwgcx.cn
http://CcUzJdZv.dwgcx.cn
http://QHaRyZIV.dwgcx.cn
http://g34zzfim.dwgcx.cn
http://LXtSqATn.dwgcx.cn
http://oFUNXJwv.dwgcx.cn
http://qNU7LRng.dwgcx.cn
http://a8TVsj7C.dwgcx.cn
http://FtArjd7W.dwgcx.cn
http://FJhT1jSG.dwgcx.cn
http://4XuA0BC6.dwgcx.cn
http://7BxFyDQg.dwgcx.cn
http://haLPMA1E.dwgcx.cn
http://3tPg7MY1.dwgcx.cn
http://JMWepJa7.dwgcx.cn
http://www.dtcms.com/a/374227.html

相关文章:

  • 安装配置简易VM虚拟机(CentOS 7)
  • 虚拟机中centos简单配置
  • commons-logging
  • 【小宁学习日记6 PCB】电路原理图
  • Rust位置表达式和值表达式
  • 对比:ClickHouse/MySQL/Apache Doris
  • 2025年学英语学习机选购指南
  • 浪涌测试主要用于评估电子设备或元器件在遭受短时高强度电压 / 电流冲击(浪涌)时的耐受能力
  • ANDROID,Jetpack Compose, 贪吃蛇小游戏Demo
  • html中列表和表格的使用
  • MyBatis-Plus 深度解析:IService 接口全指南
  • iPaaS 如何帮助 CIO 减少 50% 的集成成本?
  • [运动控制]PID算法再深入--多环组合控制
  • llm的一点学习笔记
  • JVM详解(一)--JVM和Java体系结构
  • Java字符串处理:String、StringBuilder与StringBuffer
  • SQL 注入与防御-第十章:确认并从 SQL 注入攻击中恢复
  • MCP(模型上下文协议)入门教程1
  • 已知两个平面点的坐标、切线方向、曲率,构造三阶Bezier曲线的方法
  • STM32添加库函数
  • Python 示例(Tkinter)
  • 学习如何基于ACP-SDK构建多智能体系统
  • Dify 从入门到精通(第 83/100 篇):Dify 的多模态模型性能调优(高级篇)
  • 【docker】镜像制作
  • 前端安全攻防:XSS, CSRF 等防范与检测
  • Unity鱼眼特效
  • MySQL表结构优化:安全删除字段(DROP COLUMN)的完整指南与避坑手册
  • Java全栈技术选型指南
  • Leptos框架深度解析:用Rust构建高性能Web应用的未来
  • 嵌入式学习day45-硬件—汇编