java升级版本
JDK 1.8 是 Java Development Kit 的第 8 版本,发布于 2014 年 3 月 18 日。这个版本是 Java SE(Standard Edition)的一部分,包含了 Java 编程语言的实现、编译器、调试工具和其他相关组件
- JDK 1.8: 这里的
1.8
表示 Java 的主要版本号为 8。 - Java SE 8: 这是正式的产品名称,表示 Java 标准版的第 8 版本
Lambda 表达式:
- 允许将函数作为参数传递,简化代码并提高可读性。
Stream API:
- 提供了一种高效且易于使用的处理集合数据的方式。
-
Nashorn JavaScript Engine:
- 内置了一个高性能的 JavaScript 引擎,允许在 Java 应用程序中执行 JavaScript 代码。
-
性能改进:
- 包括垃圾回收器的优化、G1 垃圾收集器的增强等。
-
长期支持 (LTS):
- JDK 1.8 是一个长期支持版本,这意味着它获得了 Oracle 和其他供应商的持续更新和支持,直到 2029 年底(根据 Oracle 的计划)。
- 对于需要长时间稳定运行的企业级应用,JDK 1.8 仍然是一个可靠的选择。
-
新功能和改进:
- JDK 1.8 引入了许多重要的新特性和改进,使其成为许多项目的基础。
- 然而,后续版本(如 JDK 11、17、21)继续引入更多新特性和改进,提供了更好的性能和安全性。
从Java 9开始,Oracle和OpenJDK社区对JDK的结构进行了重大调整,其中一个重要变化是不再默认包含独立的JRE(Java Runtime Environment)。相反,JDK本身现在可以作为运行时环境使用,这意味着你可以直接用JDK来运行Java应用程序,而不需要单独安装JRE。
Java 9引入了模块化系统(Project Jigsaw),这使得JDK变得更加灵活。通过jlink
工具,开发者可以根据需要创建自定义的运行时镜像,只包含应用程序所需的模块,从而减少部署包的大小
-
- 在以前的版本中,JDK和JRE是分开的。JDK主要用于开发,而JRE用于运行Java应用程序。从Java 9开始,这种区分被模糊化,JDK本身就包含了所有必要的运行时组件。
- 如果你只需要运行Java应用程序而不进行开发,你可以使用
jlink
创建一个最小化的运行时环境,而不是安装完整的JDK。
-
新的目录结构:
bin
:包含可执行文件,如java
、javac
等。conf
:包含配置文件,例如security
、net.properties
等。include
:包含C/C++头文件,用于JNI(Java Native Interface)开发。jmods
:包含模块化的JDK库(.jmod
文件),这些文件可以在构建自定义运行时镜像时使用。legal
:包含各个组件的许可信息。lib
:包含JDK的核心库和其他资源文件。release
:这是一个文本文件,包含当前JDK版本的详细信息
果你想要创建一个更轻量级的运行时环境,可以使用jlink
工具。以下是一个简单的例子,它会创建一个仅包含java.base
模块的运行时镜像:
。[JDK 11 版本也无需设置环境变量,以前下载JDK 8 版本需要配置环境变量,其他版本没有测试,可以自行安装测试]。
垃圾博客害人不浅,安了jdk11也需要配环境变量,也是傻,怎么会相信这个,不然
就配置俩步,一个是JAVA_HOME指向包,然后在Path当中加入JAVA_HOME的bin
h2数据库
第一次登陆可以用sa进行,密码可以不填。使用其他用户名登陆会自动创建用户,如果指定密码则下次登陆需要输入指定后的密码
用户名为sa
(这是H2的默认管理员用户名),会发生以下几件事情:
1. 自动创建数据库
- 如果你没有指定现有的数据库文件,H2会在你提供的路径或默认路径下自动创建一个新的数据库。对于嵌入式模式,这个路径通常是当前工作目录下的一个文件。
2. 创建默认用户 sa
- 如果你使用了
sa
作为用户名,并且没有提供密码(即密码为空),H2会默认认为这是管理员账户。首次启动时,它会创建这个用户并赋予其完全的权限。 - 如果你提供了密码,那么
sa
用户将被创建并设置为你提供的密码。
- 默认情况下,H2数据库并不启用严格的安全措施。这意味着任何人都可以连接到数据库,只要他们知道正确的URL和凭据(如
sa
用户名)。为了提高安全性,建议:- 设置强密码。
- 启用TLS/SSL加密(如果通过网络访问)。
- 使用更严格的访问控制机制,例如通过防火墙限制访问。
pro1
数据库URL中不允许使用相对于当前工作目录的文件路径。你需要使用绝对路径、~/name、./name 或者配置 baseDir 设置。
以嵌入式(本地)连接方式连接H2数据库
这种连接方式默认情况下只允许有一个客户端连接到H2数据库,有客户端连接到H2数据库之后,此时数据库文件就会被锁定,那么其他客户端就无法再连接了。
连接语法:jdbc:h2:[file:][<path>]<databaseName>
例如:
jdbc:h2:~/test // 连接位于用户目录下的test数据库
jdbc:h2:file:/data/sample
jdbc:h2:file:E:/H2/gacl // Windows only
await
和 fetch
- 减少嵌套:避免了回调地狱(callback hell)中常见的多层嵌套。
- 提高可读性:代码更易读,逻辑流程更直观。
明确错误处理
- 集中错误处理:使用
try...catch
块可以集中处理所有可能的错误,而不是在每个.then()
中分别处理。
function fetchData() {
fetch('https://api.example.com/data1')
.then(response1 => response1.json())
.then(data1 => {
fetch('https://api.example.com/data2')
.then(response2 => response2.json())
.then(data2 => {
const combinedData = { ...data1, ...data2 };
console.log(combinedData);
})
.catch(error2 => console.error('Error fetching data2:', error2));
})
.catch(error1 => console.error('Error fetching data1:', error1));
console.log('Fetching data...');
}
fetchData();
错误处理:
- 每个
.then()
链都有独立的.catch()
处理错误
- 嵌套过多:多个
.then()
链导致代码嵌套层级加深,难以阅读和维护。 - 错误处理分散:每个
.then()
链都需要单独处理错误,容易遗漏。 - 调试困难:复杂的嵌套结构增加了调试的难度
async function fetchData() {
try {
const response1 = await fetch('https://api.example.com/data1');
if (!response1.ok) {
throw new Error(`HTTP error! Status: ${response1.status}`);
}
const data1 = await response1.json();
const response2 = await fetch('https://api.example.com/data2');
if (!response2.ok) {
throw new Error(`HTTP error! Status: ${response2.status}`);
}
const data2 = await response2.json();
const combinedData = { ...data1, ...data2 };
console.log(combinedData);
} catch (error) {
console.error('Error fetching data:', error);
}
console.log('Fetching data completed.');
}
fetchData();
- 使用
await
关键字等待第一个fetch
请求完成,并解析 JSON 数据。 - 检查响应状态,如果失败则抛出错误。
- 使用
await
关键字等待第二个fetch
请求完成,并解析 JSON 数据。 - 检查响应状态,如果失败则抛出错误。
- 合并两个数据对象并打印结果。
await
关键字让代码按顺序执行,每个await
语句会暂停函数的执行,直到 Promise 完成。- 无回调:不需要使用回调函数来处理异步操作的结果,减少了嵌套层级。
- 明确的状态管理:每个步骤都可以通过简单的赋值语句处理,类似于同步代码中的变量赋值。
- 错误处理统一:使用
try...catch
块统一处理错误,避免了在每个.then()
中分散处理错误的情况。
使用await后不就使原本可以并发的两个请求,变成同步了吗?即两个fetch原本不存在等待关系,只是最后合并的时候需要都完成,而现在则是需等待第一个fetch结束后,第二个fetch才能发送?
等待所有请求完成
Promise.all([promise1, promise2])
.then(([data1, data2]) => {
const combinedData = { ...data1, ...data2 };
console.log(combinedData);
})
.catch(error => console.error('Error fetching data:', error));
- 使用
Promise.all
等待所有 Promise 完成。 - 当所有请求完成后,合并数据并处理结果
const [response1, response2] = await Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2')
]);
- 使用
Promise.all
并发发起两个fetch
请求。 - 使用
await
关键字等待所有请求完成,并将响应存储在数组中
pro2
HTTP 401 错误 - 未授权: (Unauthorized)
您的Web服务器认为,客户端发送的 HTTP 数据流是正确的,但进入网址 (URL) 资源 , 需要用户身份验证 , 而相关信息 1 )尚未被提供, 或 2 )已提供但没有通过授权测试。这就是通常所知的“ HTTP 基本验证 ”。 需客户端提供的验证请求在 HTTP 协议中被定义为 WWW – 验证标头字段 (WWW-Authenticate header field)
通常情况下,401 状态码意味着客户端需要提供有效的认证信息才能访问资源。
就是启用了spring security,但是是对所有请求加以限制,只要把login放通就好了
缺少认证信息:
你的应用程序可能配置了某种形式的认证机制(如基本认证、JWT 等),而你发送的请求中没有包含必要的认证信息。
检查你的应用程序配置,确保你了解并正确提供了所需的认证信息。
Spring Security 配置:
如果你使用了 Spring Security,确保你的安全配置允许 /login 路径的匿名访问。
你可以在 SecurityConfig 类中添加相应的配置,
@Bean 注解:
@Bean 注解告诉 Spring 容器这是一个需要管理的 Bean。在这个例子中,securityFilterChain 方法返回一个 SecurityFilterChain 对象,Spring 将会管理这个对象的生命周期。
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception:
这个方法返回一个 SecurityFilterChain 对象,用于配置 Spring Security 的安全规则。
HttpSecurity 是一个用于配置 HTTP 安全设置的对象。
http.csrf().disable():
csrf().disable() 关闭了 CSRF(跨站请求伪造)保护。CSRF 保护默认是启用的,但在某些情况下(如 API 开发)可能不需要它。
注意:关闭 CSRF 保护可能会带来安全风险,因此在生产环境中应谨慎使用。
http.authorizeRequests():
authorizeRequests() 方法用于配置哪些 URL 需要认证和授权。
http.antMatchers("/api/auth/login").permitAll():
antMatchers("/api/auth/login").permitAll() 配置了 /api/auth/login 路径允许所有用户访问,即使未认证的用户也可以访问。
这通常用于登录接口,允许用户在未登录的情况下访问登录页面或 API。
http.anyRequest().authenticated():
anyRequest().authenticated() 配置了所有其他请求都需要经过认证。
这意味着除了 /api/auth/login 路径外,其他所有路径都需要用户已经登录。
http.and():
and() 方法用于链式调用,继续配置其他安全设置。
http.httpBasic():
httpBasic() 方法启用了基本认证(HTTP Basic Authentication)。
基本认证是一种简单的认证机制,通过在请求头中包含 Authorization 字段来传递用户名和密码。
CSRF(Cross-Site Request Forgery,跨站请求伪造) 是一种常见的安全漏洞,攻击者通过诱导用户在已登录的网站上执行非预期的操作。具体来说,当一个用户已经登录到某个网站(例如银行网站),并且该网站没有适当的安全措施时,攻击者可以构造一个恶意请求,利用用户的认证信息(如 cookies)在用户不知情的情况下执行某些操作
-
用户登录目标网站:
- 用户先登录到一个受信任的网站(例如
bank.com
),并在浏览器中保存了该网站的认证 cookie。
- 用户先登录到一个受信任的网站(例如
-
访问恶意网站或点击恶意链接:
- 用户随后访问了一个恶意网站(例如
malicious.com
),或者点击了一个包含恶意代码的链接。
- 用户随后访问了一个恶意网站(例如
-
恶意网站发送请求:
- 恶意网站会自动向目标网站(
bank.com
)发送一个请求,利用用户已经在目标网站上存储的认证 cookie。 - 这个请求可能是转账、修改密码或其他敏感操作。
- 恶意网站会自动向目标网站(
-
目标网站处理请求:
- 因为目标网站识别出请求中的认证 cookie 是有效的,它会认为这是用户本人发起的操作,并执行相应的请求。
-
用户受到影响:
- 用户可能在不知情的情况下,进行了转账或其他敏感操作,导致账户资金被盗用或个人信息泄露。
回调地狱(Callback Hell) 是在使用异步编程时常见的问题,特别是在早期的 JavaScript 开发中。它指的是由于嵌套过多的回调函数而导致代码难以阅读、维护和调试的情况。回调地狱通常发生在需要顺序执行多个异步操作时,每个操作的结果依赖于前一个操作的结果
回调 是一种编程模式,其中一个函数(称为回调函数)作为参数传递给另一个函数,并在某个事件发生后被调用。回调函数允许异步操作完成后执行特定的逻辑
需要依次执行三个异步操作:读取文件、处理数据、写入文件。使用回调函数可能会导致以下代码结构:
在这个例子中,每个异步操作都嵌套在一个回调函数中,形成了一个“金字塔”形状的代码结构,这就是回调地狱的一个典型表现。
可读性差:
- 嵌套层级过多,代码变得难以阅读和理解。
- 缩进层级增加,影响代码的美观性和可维护性
const fs = require('fs');
try {
// 同步读取文件
const data = fs.readFileSync('input.txt', 'utf8');
console.log('File read successfully:', data);
// 处理数据
const processedData = processData(data);
console.log('Data processed successfully:', processedData);
// 同步写入文件
fs.writeFileSync('output.txt', processedData, 'utf8');
console.log('File written successfully');
} catch (err) {
console.error('Error:', err);
}
fs.readFileSync
和fs.writeFileSync
是同步方法,会阻塞主线程直到操作完成。- 程序按顺序执行每个操作,一个操作完成后才会开始下一个操作。
- 如果文件较大或磁盘较慢,整个程序会停滞不前
const fs = require('fs');
// 异步读取文件
fs.readFile('input.txt', 'utf8', function(err, data) {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log('File read successfully:', data);
// 处理数据
const processedData = processData(data);
console.log('Data processed successfully:', processedData);
// 异步写入文件
fs.writeFile('output.txt', processedData, 'utf8', function(err) {
if (err) {
console.error('Error writing file:', err);
return;
}
console.log('File written successfully');
});
});
console.log('Reading file...');
fs.readFile
和fs.writeFile
是异步方法,不会阻塞主线程。- 程序启动文件读取操作后立即继续执行后续代码(例如
console.log('Reading file...')
)。 - 当文件读取完成时,回调函数被调用,处理数据并启动文件写入操作。
- 文件写入完成后,另一个回调函数被调用,完成整个流程。
- 异步操作 是指那些不会阻塞主线程的操作,适用于 I/O 操作等耗时任务。
- 读取文件、处理数据、写入文件 这三个操作虽然是异步的,但它们之间存在依赖关系,必须按顺序执行。
- 回调地狱 是由于嵌套过多的回调函数导致代码难以维护的问题。
- Promise 和 async/await 提供了更好的方式来处理异步操作,使代码更清晰和易于维护。
pro3
这个就是接收的时候用的是requestParam,这个参数是在url路径上的,但是放到包里了,所以报错了
@RequestParam 用于从请求的查询参数中提取 username 和 password。例如,请求可能是:
POST http://localhost:8080/login?username=admin&password=admin
@PostMapping("/login")
public String login(@RequestBody LoginRequest loginRequest) {
System.out.println("postEnd has get an url!!!!!,get username: " + loginRequest.getUsername() + ",get password: " + loginRequest.getPassword());
if ("admin".equals(loginRequest.getUsername()) && "admin".equals(loginRequest.getPassword())) {
return "登录成功";
}
return "登录失败";
}
public static class LoginRequest {
private String username;
private String password;
// Getters and Setters
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@RequestBody
:- 用于将 HTTP 请求的正文内容转换为 Java 对象。
- 通常与 POST 或 PUT 请求一起使用。
- 需要配合 JSON 解析库(如 Jackson)将 JSON 字符串转换为 Java 对象。
-
定义请求体数据模型:
- 创建一个 Java 类来表示请求体中的数据结构。
-
控制器方法中使用
@RequestBody
:- 在控制器的方法参数前添加
@RequestBody
注解。
- 在控制器的方法参数前添加
-
配置 JSON 解析器:
- Spring Boot 自动配置了 Jackson 作为默认的 JSON 解析器,无需额外配置。
pro4
byd,localhost拼错了,不愧是你虫
表明浏览器阻止了跨域请求,因为后端没有正确配置 CORS 头。
确保后端正确配置了 CORS,允许来自前端应用的请求。你已经有一个基本的 CORS 配置,但需要确保它正确地允许 http://localhost:3000。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000") // 确保与前端端口一致
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}
registry.addMapping("/api/**"):
addMapping 方法用于指定哪些 URL 路径需要应用 CORS 配置。
"/api/**" 表示所有以 /api/ 开头的 URL 路径都将应用此 CORS 配置。
.allowedOrigins("http://localhost:3000"):
allowedOrigins 方法用于指定允许访问的源(Origin)。
"http://localhost:3000" 表示允许来自 http://localhost:3000 的请求访问这些 API。
注意:确保这个地址与你的前端应用的地址一致。
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS"):
allowedMethods 方法用于指定允许的 HTTP 方法。
这里允许 GET, POST, PUT, DELETE, 和 OPTIONS 方法。
.allowedHeaders("*"):
allowedHeaders 方法用于指定允许的请求头。
"*" 表示允许所有请求头。
你也可以指定具体的请求头,例如 .allowedHeaders("Content-Type", "Authorization")。
.allowCredentials(true):
allowCredentials 方法用于指定是否允许发送凭据(如 cookies、HTTP 认证信息等)。
true 表示允许发送凭据。
注意:如果设置了 allowCredentials(true),则 allowedOrigins 不能使用 "*",必须指定具体的源
路径映射:所有以 /api/ 开头的 URL 路径都将应用此 CORS 配置。
允许的源:允许来自 http://localhost:3000 的请求访问这些 API。
允许的 HTTP 方法:允许 GET, POST, PUT, DELETE, 和 OPTIONS 方法。
允许的请求头:允许所有请求头。
允许发送凭据:允许发送凭据(如 cookies、HTTP 认证信息等)。
安全建议
限制允许的源:尽量不要使用 "*" 作为 allowedOrigins,而是指定具体的源,以提高安全性。
限制允许的请求头:尽量不要使用 "*" 作为 allowedHeaders,而是指定具体的请求头。
凭据:如果不需要发送凭据,可以将 allowCredentials 设置为 false,以减少安全风险。