《Spring Guides系列学习》guide35 - guide40
要想全面快速学习Spring的内容,最好的方法肯定是先去Spring官网去查阅文档,在Spring官网中找到了适合新手了解的官网Guides,一共68篇,打算全部过一遍,能尽量全面的了解Spring框架的每个特性和功能。
接着上篇看过的guide34,接着往下看。
guide35、Scheduling Tasks
@Scheduled注解: 是spring boot提供的用于定时任务控制的注解,主要用于控制任务在某个指定时间执行,或者每隔一段时间执行.注意需要配合@EnableScheduling使用,配置@Scheduled主要有三种配置执行时间的方式,cron,fixedRate,fixedDelay。
1、cron表达式
该参数接收一个cron表达式,cron表达式是一个字符串,字符串以5或6个空格隔开,分开共6或7个域,每一个域代表一个含义。[年]不是必须的域,可以省略[年],则一共6个域。
表达式语法:
[秒] [分] [小时] [日] [月] [周] [年]
2、 fixedDelay
上一次执行完毕时间点之后多长时间再执行。如:
@Scheduled(fixedDelay = 5000) //上一次执行完毕时间点之后5秒再执行
3、fixedRate
上一次开始执行时间点之后多长时间再执行。如:
@Scheduled(fixedRate = 5000) //上一次开始执行时间点之后5秒再执行
具体参数设置可参考:https://segmentfault.com/a/1190000038938579
@EnableScheduling注解:用来使@Schedule注解功能可用的注解
使用也很简单:
@Component
public class ScheduledTasks {private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");@Scheduled(fixedRate = 5000)public void reportCurrentTime() {log.info("The time is now {}", dateFormat.format(new Date()));}
}@SpringBootApplication
@EnableScheduling
public class SchedulingTasksApplication {public static void main(String[] args) {SpringApplication.run(SchedulingTasksApplication.class);}
}
运行结果:
guide36、Building Java Projects with Gradle
简单介绍使用gradle创建项目。
Gradle是继Maven之后的新一代构建工具,它采用基于groovy的DSL语言作为脚本,相比传统构建工具通过XML来配置而言,最直观上的感受就是脚本更加的简洁、优雅。如果你之前对Maven有所了解,那么可以很轻易的转换到Gradle,它采用了同Maven一致的目录结构,可以与Maven一样使用Maven中央仓库以及各类仓库的资源,并且Gradle默认也内置了脚本转换命令可以方便的将POM转换为build.gradle。
参考文档:https://www.jianshu.com/p/7ccdca8199b8
一个简单的Gralde脚本,或许包含如下内容,其中标明可选的都是可以删掉的部分
- 插件引入:声明你所需的插件
- 属性定义(可选):定义扩展属性
- 局部变量(可选):定义局部变量
- 属性修改(可选):指定project自带属性
- 仓库定义:指明要从哪个仓库下载jar包
- 依赖声明:声明项目中需要哪些依赖
- 自定义任务(可选):自定义一些任务
//定义扩展属性(给脚本用的脚本)
buildScript {repositories {mavenCentral()}
}
//应用插件,这里引入了Gradle的Java插件,此插件提供了Java构建和测试所需的一切。
apply plugin: 'java'
//定义扩展属性(可选)
ext {foo="foo"
}
//定义局部变量(可选)
def bar="bar"//修改项目属性(可选)
group 'pkaq'
version '1.0-SNAPSHOT'//定义仓库,当然gradle也可以使用各maven库 ivy库 私服 本地文件等,后续章节会详细介绍(可选)
repositories {jcenter()
}//定义依赖,这里采用了g:a:v简写方式,加号代表了最新版本(可选)
dependencies {compile "cn.pkaq:ptj.tiger:+"
}//自定义任务(可选)
task printFoobar {println "${foo}__${bar}"
}
使用gradle build指令进行编译打包。
guide37、Accessing Relational Data using JDBC with Spring
主要介绍了jdbcTemplate的使用。
什么是JDBC?JDBC是Java DataBase Connectivity的缩写,它是Java程序访问数据库的标准接口。使用Java程序访问数据库时,Java代码并不是直接通过TCP连接去访问数据库,而是通过JDBC接口来访问,而JDBC接口则通过JDBC驱动来实现真正对数据库的访问。
jdbcTemplate:Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中。
JdbcTemplate主要提供以下五类方法:
execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
update方法及batchUpdate方法:
update方法用于执行新增、修改、删除等语句;
batchUpdate方法用于执行批处理相关语句;
query方法及queryForXXX方法:用于执行查询相关语句; call方法:用于执行存储过程、函数相关语句。
构建一个实体类
public class Customer {private long id;private String firstName, lastName;...
主类:
@SpringBootApplication
public class RelationalDataAccessApplication implements CommandLineRunner {public static void main(String args[]) {SpringApplication.run(RelationalDataAccessApplication.class, args);}@AutowiredJdbcTemplate jdbcTemplate;@Overridepublic void run(String... strings) throws Exception {log.info("Creating tables");jdbcTemplate.execute("DROP TABLE customers IF EXISTS");jdbcTemplate.execute("CREATE TABLE customers(" +"id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))");// Split up the array of whole names into an array of first/last namesList<Object[]> splitUpNames = Arrays.asList("John Woo", "Jeff Dean", "Josh Bloch", "Josh Long").stream().map(name -> name.split(" ")).collect(Collectors.toList());// Use a Java 8 stream to print out each tuple of the listsplitUpNames.forEach(name -> log.info(String.format("Inserting customer record for %s %s", name[0], name[1])));// Uses JdbcTemplate's batchUpdate operation to bulk load datajdbcTemplate.batchUpdate("INSERT INTO customers(first_name, last_name) VALUES (?,?)", splitUpNames);log.info("Querying for customer records where first_name = 'Josh':");jdbcTemplate.query("SELECT id, first_name, last_name FROM customers WHERE first_name = ?", new Object[] { "Josh" },(rs, rowNum) -> new Customer(rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name"))).forEach(customer -> log.info(customer.toString()));}
}
运行结果:
guide38、Authenticating a User with LDAP
LDAP(轻型目录访问协议)是一种软件协议 ,使任何人都可以在公共互联网或公司内网上查找网络中的组织,个人和其他资源(例如文件和设备)的数据 。LDAP 是目录访问协议(DAP)的“轻量级”版本,它是 X.500( 网络中目录服务的标准 )的一部分。
构建一个简单的web应用程序,该应用程序由Spring Security的嵌入式LDAP服务器保护。并使用包含一组用户的数据文件加载LDAP服务器。
首先是maven加载对应的jar包依赖,写个controller
@RestController
public class HomeController {@GetMapping("/")public String index() {return "Welcome to the home page!";}
}
其次在项目中配置安全策略类:
@Configuration
public class WebSecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin();return http.build();}@Autowiredpublic void configure(AuthenticationManagerBuilder auth) throws Exception {auth.ldapAuthentication().userDnPatterns("uid={0},ou=people").groupSearchBase("ou=groups").contextSource().url("ldap://localhost:8389/dc=springframework,dc=org").and().passwordCompare().passwordEncoder(new BCryptPasswordEncoder()).passwordAttribute("userPassword");}}
通过定制一个WebSecurityConfig类来完成安全验证的设置。
还需要一个LDAP服务器, 这里使用了一个纯Java语言的内置服务器,Spring Boot为它提供了自动配置。ldapAuthentication()方法使得登录表单中用户名会插入到的uid={0},ou=people,dc=springframework,dc=org的“{0}”中。而passwordCompare()方法配置了密码编码器和密码属性。
还需要修改配置文件
spring.ldap.embedded.ldif=classpath:test-server.ldif
spring.ldap.embedded.base-dn=dc=springframework,dc=org
spring.ldap.embedded.port=8389
以及设置用户数据,LDAP服务器可以使用LDIF(LDAP数据交换格式)文件来交换用户数据。application.properties文件中的spring.ldap.embedded.ldif属性使得Spring Boot会加载对应的LDIF 文件。
配置好这些,再启动程序,访问接口就会重定向到spring security提供的登录页。输入用户名密码,就可以得到返回结果。
guide39、Messaging with RabbitMQ
介绍使用Spring AMQP的RabbitTemplate发布消息,并使用MessageListenerAdapter在POJO上订阅消息。
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)
AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。
首先安装rabbitmq,并启动。
brew install rabbitmqrabbitmq-server
创建一个接收器来响应已发布的消息。Receiver是一个 POJO,它定义了接收消息的方法。
@Component
public class Receiver {private CountDownLatch latch = new CountDownLatch(1);public void receiveMessage(String message) {System.out.println("Received <" + message + ">");latch.countDown();}public CountDownLatch getLatch() {return latch;}
}
注册监听器并发送消息
Spring AMQP RabbitTemplate提供了使用 RabbitMQ 发送和接收消息所需的一切。但是,您需要:
- 配置消息侦听器容器。
- 声明队列、交换以及它们之间的绑定。
- 配置一个组件发送一些消息来测试监听器
@SpringBootApplication
public class MessagingRabbitmqApplication {static final String topicExchangeName = "spring-boot-exchange";static final String queueName = "spring-boot";@BeanQueue queue() {return new Queue(queueName, false);}@BeanTopicExchange exchange() {return new TopicExchange(topicExchangeName);}@BeanBinding binding(Queue queue, TopicExchange exchange) {return BindingBuilder.bind(queue).to(exchange).with("foo.bar.#");}@BeanSimpleMessageListenerContainer container(ConnectionFactory connectionFactory,MessageListenerAdapter listenerAdapter) {SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.setQueueNames(queueName);container.setMessageListener(listenerAdapter);return container;}@BeanMessageListenerAdapter listenerAdapter(Receiver receiver) {return new MessageListenerAdapter(receiver, "receiveMessage");}public static void main(String[] args) throws InterruptedException {SpringApplication.run(MessagingRabbitmqApplication.class, args).close();}}
该queue()方法创建一个 AMQP 队列。该exchange()方法创建主题交换。binding()方法将这两个方法绑定起来,并且定义了rabbitTemplate发布到主体交换时要发生的行为。
listenerAdapter()在容器中注册为消息侦听器。它侦听spring-boot队列中的消息。因为该类Receiver是一个 POJO,所以它需要包装在 中MessageListenerAdapter
发送测试消息
@Component
public class Runner implements CommandLineRunner {private final RabbitTemplate rabbitTemplate;private final Receiver receiver;public Runner(Receiver receiver, RabbitTemplate rabbitTemplate) {this.receiver = receiver;this.rabbitTemplate = rabbitTemplate;}@Overridepublic void run(String... args) throws Exception {System.out.println("Sending message...");rabbitTemplate.convertAndSend(MessagingRabbitmqApplication.topicExchangeName, "foo.bar.baz", "Hello from RabbitMQ!");receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);}}
运行结果:
guide40、Validating Form Input
构建一个简单的Spring MVC应用程序,它接受用户输入,并使用标准的验证注释检查输入。
其实核心就是一些javax.validation中的注解。
public class PersonForm {@NotNull@Size(min=2, max=30)private String name;@NotNull@Min(18)private Integer age;...
@NotNull注解: 是在 Java 中常用的非空检查注解。它的作用是表明使用该注解的变量、参数或返回值不能为 null,否则会抛出空指针异常。
@Min 验证 Number 和 String 对象是否大等于指定的值
@Max 验证 Number 和 String 对象是否小等于指定的值
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) 验证字符串长度是否在给定的范围之内
@Valid 表示对这个对象属性需要进行验证
@NotEmpty 被注释的元素不为空(可用于String,Collection,Map,arrays)
@NotBlank 只应用于字符串且在比较时会去除字符串的首位空格
@GetMapping ("/get")
public String check(@Valid PersonForm personForm){return personForm.toString();
}
简单调用下接口,如果参数不满足校验,就直接返回400了,后台显示有bindException异常。
可以用BindingResult获取校验结果:
@GetMapping ("/get")
public String check(@Valid PersonForm personForm, BindingResult bindingResult){if (bindingResult.hasErrors()) {return bindingResult.getAllErrors().get(0).getDefaultMessage();}return personForm.toString();
}
不用BindingResult的话,其实也可以做一个全局异常处理,有异常的话返回信息给前端
@RestControllerAdvice
public class ValidExceptionHandler {@ExceptionHandler(BindException.class)public String validExceptionHandler(BindException exception) {return exception.getAllErrors().get(0).getDefaultMessage();}
}
文献参考:https://blog.csdn.net/sunnyzyq/article/details/103527380
相关文章:

《Spring Guides系列学习》guide35 - guide40
要想全面快速学习Spring的内容,最好的方法肯定是先去Spring官网去查阅文档,在Spring官网中找到了适合新手了解的官网Guides,一共68篇,打算全部过一遍,能尽量全面的了解Spring框架的每个特性和功能。 接着上篇看过的gu…...

《算法导论》拓展之 一维二维最近点对问题
一维点对问题 描述:一维最近点对问题是指在给定的一维点集中找到距离最近的两个点。具体来说,给定一维坐标轴上的 n 个点,要找出其中的两个点,使它们的距离最小。 解决办法:解决这个问题的一种常见方法是使用排序和线…...

【C++】动态存储分配
动态存储分配是指在程序运行时根据需要动态地分配和释放内存空间。 C中提供了两个关键的运算符用于动态存储分配:new和delete。 使用new运算符可以在堆(heap)上动态地分配内存空间,并返回所分配内存的首地址。语法如下࿱…...

小狗避障-第14届蓝桥杯省赛Scratch中级组真题第4题
[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第139讲。 小狗避障,本题是2023年5月7日举行的第14届蓝桥杯省赛Scratch图形化编程中级组编程第4题…...

GPT学习笔记-Embedding的降维与2D,3D可视化
嵌入(Embedding)在机器学习和自然语言处理中是一种表示离散变量(如单词、句子或整个文档)的方式,通常是作为高维向量或者矩阵。嵌入的目标是捕捉到输入数据中的语义信息,使得语义相近的元素在嵌入空间中的距…...

Nautilus Chain上线主网,为DeFi和流支付的未来构建基础
近日,加密行业权威平台 Coinmarketcap 发表了一篇名为“Zebec 模块化 Layer3 链 Nautilus Chain上线主网,为 DeFi 和流支付的未来构建基础”的文章,文中对 Zebec 生态公链 Nautilus Chain 的生态进展进行了简要的报道,并对其进行了…...

java设计模式之命令设计模式的前世今生
命令设计模式是什么? 命令设计模式是一种行为型设计模式,它允许将请求封装为对象,并将其传递给调用者,从而使调用者可以在不知道请求具体细节的情况下进行操作。命令模式的主要目的是解耦请求的发送者和接收者,以及通…...

离散系统函数零积点分析
离散系统函数零积点分析 在 Matlab中,系统函数的零极点就可以通过函数 roots 得到。 函数的零极点也可以通过函数 tf2zp 获得,其调用格式为:[Z, P, K] tf2zp(B, A),函数 tf2zp 可以将H(z)的有理分式转换为零极点增益形式&#…...

Karl Guttag:苹果VST MR头显也无法突破AR的物理局限
据近期的爆料、传闻显示,苹果将6月份的WWDC2023上首次公布AR/VR头显。对此,AR/VR光学专家Karl Guttag持怀疑态度,他此前在DisplayDaily的文章中写道,苹果研发AR/VR头显更像是担心错过新技术趋势。回顾过去的一些关键的AR产品&…...

mysql倒库操作遇到的问题
背景:本地windows 10安装了mysql数据库后,需要把远程库的表结构和数据全部导入进来。 操作:导出数据库,导入数据库。 第一步:导出数据库 使用dump命令即可。 登陆mysql数据库 mysql -hhost --default-character-s…...

ELK企业级日志分析系统
ELK概述 为什么要使用 ELK 日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷,性能安全性,从而及时采取措施纠正错误。 …...

华为OD机试真题 Java 实现【基站维修工程师】【2023Q1 200分】,附详细解题思路
一、题目描述 小王是一名基站维护工程师,负责某区域的基站维护。 某地方有n个基站(1<n<10),已知各基站之间的距离s(0<s<500),并且基站x到基站y的距离,与基站y到基站x的距离并不一定会相同。 小王从基站1出发,途径每个基站1次,然后返回基站1,需要请你…...

SSM 如何使用 TCC 机制实现分布式事务?
SSM 如何使用 TCC 机制实现分布式事务? 分布式事务是现代分布式系统中必不可少的一部分,而 TCC 机制(Try-Confirm-Cancel)是一种常用的分布式事务处理方式。在 SSM 框架中,我们可以使用 TCC 机制来管理分布式事务。本…...

如何在上架App之前设置证书并上传应用
App上架教程 在上架App之前想要进行真机测试的同学,请查看《iOS- 最全的真机测试教程》,里面包含如何让多台电脑同时上架App和真机调试。 P12文件的使用详解 注意: 同样可以在Build Setting 的sign中设置证书,但是有点麻烦&…...

华清远见 day04
break 打破循环,再也不执行 continue 跳出本次循环,继续执行下一次循环; 常量 字面常量 宏常量 #define A 100 //定义一个宏常量, 名为:A 值为:100 位置 在 头文件 下面 ,文件开头 输入时间秒 得到 小时 分钟 秒的时间输出 用到 三运算符; 宏常量 Mi 是60 t1 /Mi>6…...

如何处理Vue应用程序中的错误和异常情况?
处理Vue应用程序中的错误和异常情况是开发中非常重要的一环,但是对于新手来说,这往往是一个比较棘手的问题。不过别担心,下面我将为大家详细解答。 首先,我们需要知道的是,在Vue中,错误和异常情况是两个不…...

javascript基础十六:Ajax 原理是什么?如何实现?
一、是什么 AJAX全称(Async Javascript and XML) 即异步的JavaScript 和XML,是一种创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情况下,与服务器交换数据,并且更新部分网页 Ajax的原理简单来说通过XmlHttpRequ…...

大话手游原始服务端搭建教程Centos
大话手游原始服务端搭建教程Centos 大家好,我是艾西,今天给大家分享一款回合制的ARPG大话手游搭建教程。游戏场景、精美的画面以及多元的人物做的非常棒。在游戏中可以穿越神话世界,同时也可以结交好友,加入团队,共同…...

C语言中的通用工具库stdlib.h
目录 1、malloc和free:用于动态内存分配和释放。 2、atoi和atof:用于将字符串转换为整数或浮点数。 3、rand和srand:用于生成随机数和设置随机数种子。 4、system:用于执行系统命令。 5、exit:用于退出程序。 6、…...

优化带排序的分页查询
优化带排序的分页查询 浅分页: select user_no,user_name,socre from student order by score desc limit 5,20 深分页: select user_no,user_name,socre from student order by score desc limit 80000,20 因为偏移量深分页更大,所以深分页执…...

chatgpt赋能python:Python如何删除空白
Python 如何删除空白 在SEO优化过程中,我们需要保证我们的网页内容的质量和可读性。其中,一个重要的因素是删除空白。在Python中,我们可以使用多种方法来删除空白,下面我们将介绍一些方法并讨论它们的优缺点。 方法一࿱…...

[论文阅读] Explicit Visual Prompting for Low-Level Structure Segmentations
[论文地址] [代码] [CVPR 23] Abstract 我们考虑了检测图像中低层次结构的通用问题,其中包括分割被操纵的部分,识别失焦像素,分离阴影区域,以及检测隐藏的物体。每个问题通常都有一个特定领域的解决方案,我们表明&am…...

swagger在spring项目中的使用
一、Swagger2介绍 前后端分离开发模式中,api文档是最好的沟通方式。 Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。 及时性 (接口变更后,能够及时准确地通知相关前后端开发人员)规范性 (并且保…...

操作系统第五章——输入输出管理(中)
提示:若我会见到你,事隔经年,我如何向你招呼,以眼泪,以沉默 文章目录 5.2.1 IO核心子系统知识总览功能要在那个层次实现 5.2.2 假脱机技术(SPOOLing)知识总览什么是脱机技术假脱机技术——输入井…...

【网络】socket套接字基础知识
目录 IP地址和端口号 源IP地址和目的IP地址 端口号 源端口号和目的端口号 TCP/UDP协议 网络字节序 大小端 如何定义网络数据流地址 网络字节序和主机字节序的转换 socket编程接口 sockaddr结构 IP地址和端口号 源IP地址和目的IP地址 在IP数据包头部中,会…...

Go语言介绍以及Go语言环境安装
初步介绍: Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。 Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源&am…...

FPGA纯verilog实现CameraLink视频接收和发送,附带工程源码和技术支持
目录 1、前言2、CameraLink协议基础3、目前我已有的CameraLink收发工程4、设计方案5、CameraLink解码模块详解6、CameraLink编码模块详解7、vivado工程详解8、上板调试验证9、福利:工程代码的获取 1、前言 FPGA实现CameraLink视频编解码目前有两种方案:…...

k8s中的service、api-server、kube-proxy有什么区别
在Kubernetes(K8s)中,Service、API Server和kube-proxy是三个不同的组件,它们在集群中扮演着不同的角色和功能。下面我将为你解释它们之间的区别: 1. Service(服务): Service是K8s中…...

记录::opencv编译,cmake编译vs动态库
环境:window7,cmake-gui,vs2013 opencv:3.4.4 opencv_contrib:3.4.4(nonfree模块,主要为了用sift) 链接:https://pan.baidu.com/s/1OXg2IRaxTLTVqM2PVR2ZFA 提取码&a…...

网易SmartAuto,中文编程就是爽
上一篇我们应该用中文编程发出来后,果不其然不少人很不以为然,还有直说“骗钱的,估计也没人会上当”。这样的反应是在预料之中。 行胜于言,我今天讲一个我们已经用了好几年的产品,用来做UI自动化测试的SmartAuto&#…...