@Scheduled 标记要调度的方法的注解,必须指定 cron,fixedDelay或fixedRate属性之一
延迟执行任务,任务在上个任务完成后达到设置的延时时间就执行
@Scheduled(fixedDelay = 5000):任务会在上个任务完成后经过5s再执行
任务间隔规定时间即执行
@Scheduled(fixedRate = 5000):任务每隔5s执行一次
cron表达式:([秒] [分] [时] [日] [月] [周] [年])[年]为非必须,一般用6或7个标识符表示任务的执行规则
混入(mixin)提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项(如data、methods、mounted等等)。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项
①前端传参:http://localhost:8089/text/123
后端接参:
// /{}是必须写的,id是自定义的
// @PathVariable 这个注解也是必须写的,否则接不到参数
@GetMapping("/{id}")
//使用什么类型去接收id的值,要看你后端需要什么类型
public void t1(@PathVariable String id) {
log.info(id);
}
②前端传递多个参数:http://localhost:8089/text/123/456
后端接参:
// /{}是必须写的,id是自定义的
// @PathVariable 这个注解也是必须写的,否则接不到参数
@GetMapping("/{id}/{num}")
//使用什么类型去接收id的值,要看你后端需要什么类型
public void t1(@PathVariable String id,@PathVariable String num) {
log.info(id + num);
}
前端传参:http://localhost:8080/text/test?id=123&name=admin
后端接参:
//首先要明确一点,前端访问的后端路径中 ?问号后边的都是参数
//@RequestParam 这个注解可以加,也可以不加
//当需要这个注解底层的一些功能时,需要加,否则,可以不加,不会出错
//value 这个可以改变前端传递参数的名字,"id" 他和前端的参数名一样即可,String id 这个id可以随便改名
//如果不加@RequestParam 前端传参时,name可以不传,不会报错
//但是加上@RequestParam 前端就必须传name的值,否则就i会出错
//required = false 加上他,就表示前端传参时,name可以不传,不会报错
@GetMapping("/testParam")
public void t2(@RequestParam(value = "id") String id,@RequestParam(required = false) String name) {
log.info(id + name);
}
①前端使用application/json,也就是json格式传参
后端接收:
//如果前端是以json格式传递参数
//那么在接收请求的时候,需要加上@RequestBody注解,值才能成功传递到后端
//如果不加就是null对象,因为item也会被初始化
//item是一个封装的实体类,建议在接收post请求时根据前端传递的json内容封装成实体类接收
@PostMapping("/testParam")
public void t3(@RequestBody Item item) {
log.info(item.getId()+item.getName());
}
②前端使用form-data格式,也就是表单格式传参
后端接收:
//如果前端使用form-data的格式传参,不可以写@RequestBody注解,否则会报错
//item是一个封装的实体类,建议在接收post请求时根据前端传递的json内容封装成实体类接收
@PostMapping("/testParam")
public void t4(Item item) {
log.info(item.getId()+item.getName());
}
//接收前端以逗号分隔的多个参数,使用集合必须加上@RequestParam
@PostMapping("/testParam")
public void t5(@RequestParam List<Long> ids) {
log.info("ids",ids);
}
②使用数组接收
//使用数组,加不加@RequestParam注解,都可以
@PostMapping("/testParam")
public void t6(Integer[] ids) {
log.info("ids",ids);
}
③使用可变参数接收
//使用可变参数,接收到的也是数组类型,也可以不加@RequestParam注解
@PostMapping("/testParam")
public void t6(Integer ...ids) {
log.info("ids",ids);
}
content-type
content-type: application/x-www-form-urlencoded;charset=utf-8
form-data: k1=v1&k2=v2
<form action="/" method="post" enctype="multipart/form-data">
<input type="text" name="name" value="some text">
<input type="file" name="fileName">
<button type="submit">Submit</button>
</form>
POST /foo HTTP/1.1
Content-Length: 68137
Content-Type: multipart/form-data;
boundary=---------------------------974767299852498929531610575
---------------------------974767299852498929531610575
Content-Disposition: form-data; name=“name” value=“some text”
---------------------------974767299852498929531610575
Content-Disposition: form-data; name=“fileName”; filename=“foo.txt”
Content-Type: text/plain
(content of the uploaded file foo.txt)
---------------------------974767299852498929531610575–
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8{“title”:“test”,“sub”:[“a”,“b”,“c”]}
function submit2() {
var xhr = new XMLHttpRequest();
xhr.timeout = 2000;
var obj = {a: 1, b: 2};
xhr.open(‘POST’, ‘/’);
xhr.send(obj);
}
POST http://www.example.com HTTP/1.1
method1 50
Content-Type: text/xml
注意:
对于axios请求,不同的请求方式content-type也不同
内连接:指连接结果仅包含符合连接条件的行,参与连接的两个表都应该符合连接条件
外连接:连接结果不仅包含符合连接条件的行同时也包含自身不符合条件的行。包括左外连接、右外连接和全外连接
左外连接:左边表数据行全部保留,右边表保留符合连接条件的行
右外连接:右边表数据行全部保留,左边表保留符合连接条件的行
全外连接:左外连接 union 右外连接
union:会对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序
union all:对两个结果集进行并集操作,包括重复行,不会对结果进行排序
#1.sql Union用法
select 字段1 from 表名1 Union select 字段2 from 表名2;
#2.sql Union All用法
select 字段1 from 表名1 Union all select 字段2 from 表名2;
示例:
-- 1.查询员工的姓名,及其所属的部门(使用隐式内连接)
select tb_emp.name, tb_dept.name
from tb_emp,
tb_dept
where tb_dept.id = tb_emp.dept_id;
示例:
-- 2.查询员工的姓名,及其所属的部门(使用显式内连接)
select tb_emp.name, tb_dept.name
from tb_emp
inner join tb_dept on tb_emp.dept_id = tb_dept.id;
-- inner join 表示两张表进行内连接,on之后加上进行连接的条件
相当于查询表1(左表)全表扫描,然后到右表匹配,示例:
-- 3.查询user表的所有数据,和对应的user_role表中角色id
SELECT
a.*,
b.role_id
FROM
user a
LEFT JOIN user_role b ON a.user_id = b.user_id;
相当于查询表2(右表)全表扫描,然后到左表匹配,示例:
SELECT
b.* ,
a.user_name
FROM
USER a
RIGHT JOIN user_role b ON a.user_id = b.user_id;
-- 4.查询员工及其所属领导的名字。你要查询的结果再一张表中,但是还不能使用单表查询得到结果。
select a.name,b.name from tb_emp a join tb_emp b on a.managerid=b.id;
-- 查询市场部的员工信息-----
-- 子查询返回的结果一列一条记录。 这个时候可以用=
select * from tb_emp where dept_id=(select id from tb_dept where name='市场部')
-- 多条记录
select * from tb_emp where dept_id in (select id from tb_dept where name in('市场部','研发部'))
SELECT NAME FROM tb_emp
WHERE salary > 8000 UNION
SELECT * FROM tb_emp
WHERE age > 40;
async用于声明一个function是异步的;await是等待一个异步方法执行完成
http协议:客户端浏览器或其他程序与web服务器之间的应用层通信协议
https协议:简单可以理解为http+SSL/TLS,在http下加入SSL层,SSL用于保证安全的http数据传输
SSL(Secure Socket Layer,安全套接字层):SSL协议位于TCP/IP协议与各种应用层协议之间
TLS(Transport Layer Security,传输层安全):是一种基于SSL,更新出的更安全的密码协议
HTTP访问过程:HTTP请求过程中,客户端和服务器之间没有任何的身份确认过程,数据全部明文传输,易受到黑客攻击,面临各种风险,如窃听风险、篡改风险和冒充风险
HTTP向HTTPS演化过程:
存在的问题:黑客也可以利用公钥获取客户端发送的数据,从而冒充服务器,发送给客户端假的公钥,为了防止黑客冒充,服务器向客户端发送一个SSL证书,包括证书的发布机构CA、证书的有效期、公钥、证书所有者和签名等信息,客户端接收到服务器发来的SSL证书时,会对证书进行校验
普通请求步骤:客户端发送请求给服务器——服务器处理该请求——服务器将处理结果响应给该客户端
介绍:cookie由网络服务器发送出来以存储在网络浏览器上,下次该用户又回到该网络服务器时,可以从该浏览器中读取回该信息
生命周期:创建Cookie的时候可以指定一个Expire值,这就是Cookie的生存周期,在这个周期内Cookie有效,超出周期Cookie就会被清除(毫秒)。注:Cookie的生存周期设置为 ‘0’或负值 ,这样在关闭浏览器时,就马上清除Cookie,不会记录用户信息,更加安全
介绍:session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,session保存在服务器上,客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了
当会话过期或放弃后,服务器终止该对话
页面会话结束回将sessionstorage中的数据清除
生命周期:
数据长期保存,关闭浏览器/标签页,数据仍然存在
#nginx进程数,建议设置为等于CPU总核心数。
worker_processes 1;
# 事件区块开始
events {
#单个进程最大连接数(最大连接数=连接数*进程数)
#根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为。
worker_connections 1024;
}
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
#include:导入外部文件mime.types,将所有types提取为文件,然后导入到nginx配置文件中
include mime.types;
#默认文件类型
default_type application/octet-stream;
#开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
#sendfile指令指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度,降低系统uptime。
sendfile on;
#长连接超时时间,单位是秒
keepalive_timeout 65;
# 第一个Server区块开始,表示一个独立的虚拟主机站点
server {
# 提供服务的端口,默认80
listen 80;
# 提供服务的域名主机名
server_name localhost;
#对 "/" 启用反向代理,第一个location区块开始
location / {
root html; #服务默认启动目录
index index.html index.htm; # 默认的首页文件,多个用空格分开
}
# 错误页面路由
error_page 500 502 503 504 /50x.html; # 出现对应的http状态码时,使用50x.html回应客户
location = /50x.html { # location区块开始,访问50x.html
root html; # 指定对应的站点目录为html
}
}
}
三部分组成:
全局块:
主要设置一些nginx服务器整体运行的配置指令,包括配置运行nginx服务器的用户(组)、允许生成的worker process数,进程PID存放路径、日志存放路径和类型以及配置文件的引入等
events块:
events块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等
http块:
配置核心!!!代理、缓存和日志等绝大数功能和第三方模块的相关配置
http块 = http全局块 + server块
http全局块
http全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
server 块
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,
该技术的产生是为了 节省互联网服务器硬件成本。
每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。
而每个 server 块也分为全局 server 块,以及可以同时包含多个 location 块。
全局 server 块
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。
location 块
一个 server 块可以配置多个 location 块。
这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),
对虚拟主机名称 (也可以是IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,
对特定的请求进行处理。 地址定向、数据缓 存和应答控制等功能,
还有许多第三方模块的配置也在这里进行。
使用默认简单的配置,然后指定server_name和root,主要是告诉nginx代理的ip是xxx,然后我放在服务器的文件在bbb文件夹即可。nginx便会在用户访问这个ip时,自动的将bbb文件夹中的index.html返回到浏览器来展示页面
nginx接收到一个请求后,首先由listen和server_home指令匹配server模块,再匹配server模块里面得location,location就是实际地址
nginx采用异步非阻塞的I/O多路复用时间驱动模型,可以同时处理大量的并发请求:
优点:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpClientExample {
public static void main(String[] args) throws Exception {
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("https://api.example.com/endpoint"); // 替换为目标项目的URL
HttpResponse response = httpClient.execute(httpGet);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("Response Status Code: " + response.getStatusLine().getStatusCode());
System.out.println("Response Body: " + responseBody);
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpURLConnectionExample {
public static void main(String[] args) throws Exception {
URL url = new URL("https://api.example.com/endpoint"); // 替换为目标URL
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法(GET、POST、PUT等)
connection.setRequestMethod("GET");
// 获取响应状态码
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// 读取响应内容
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
System.out.println("Response Body: " + response.toString());
}
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class RestTemplateExample {
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity("https://api.example.com/endpoint", String.class); // 替换为目标URL
String responseBody = response.getBody();
System.out.println("Response Status Code: " + response.getStatusCode());
System.out.println("Response Body: " + responseBody);
}
}
df : 表示显示文件系统的磁盘使用情况;-T :表示显示文件系统的类型;-H:表示以人可读的格式显示磁盘容量,以适应更容易阅读的输出格式
注意: 如果nohup方式启动项目失败,使用java -jar 的方式启动,观察输出日志报错
not exists:
not in:
主要区别:
执行顺序:先执行on and 条件,后执行where条件筛选
执行顺序:
在 SQL Server 存储过程中,内部 SQL 语句的执行顺序通常是按照它们在存储过程中的定义顺序执行的。SQL Server 会逐一执行存储过程中的每个 SQL 语句,确保它们按照定义的顺序执行
begin … end:
BEGIN
-- 一组数据库更新操作
UPDATE table1 SET column1 = value1;
INSERT INTO table2 (column2) VALUES (value2);
-- 其他操作
END
IF condition
BEGIN
-- 如果条件为真,执行此代码块
END
ELSE
BEGIN
-- 如果条件为假,执行此代码块
END
CREATE PROCEDURE MyProcedure
AS
BEGIN
-- 存储过程中的 SQL 语句
END
1.避免使用select *
2.使用union all 代替union
3.小表驱动大表
例子:
假如有order和user两张表,其中order表有10000条数据,而user表有100条数据。时如果想查一下,所有有效的用户下过的订单列表。可以使用in关键字实现:
select * from order
where user_id in (select id from user where status=1)
也可以使用exists关键字实现:
select * from order
where exists (select 1 from user where order.user_id = user.id and status=1)
在以上这种业务场景,使用in关键字去实现业务需求,更加合适:
4.批量操作
如果我们需要批量向数据库中插入一批数据,应该避免在业务代码里面for循环里面重复插入,而是减少与数据库的连接次数,批量插入,因为每次远程请求数据库都会消耗性能。
批量操作每批的数据数量尽量控制在500以内,数据多余500,需要分多批次处理
5.用连接查询代替子查询
例子:
子查询
select * from order
where user_id in (select id from user where status=1)
连接查询
select o.* from order o
inner join user u on o.user_id = u.id
where u.status=1
6.选择合理的字段类型
char表示固定字符串类型,该类型的字段存储空间的固定的,会浪费存储空间
varchar表示变长字符串类型,该类型的字段存储空间会根据实际数据的长度调整,不会浪费存储空间
7.提升group by效率
例子:过滤订单中用户大于等于200的用户
反例:
select user_id,user_name from order
group by user_id
having user_id <= 200;
正例:
select user_id,user_name from order
where user_id <= 200
group by user_id
先筛选再分组可以有效缩小数据范围,进而提高分组效率
8.索引优化