MyBatis 自带的二级缓存存在的问题
在前面我们使用 @CacheNamespace 实现了 430.MyBatis的二级缓存 ,这个底层使用 HashMap 来实现。在 单机环境 下没有问题,但是在 分布式环境 下就不行了。
在前面我们使用 @CacheNamespace 实现了 430.MyBatis的二级缓存 ,这个底层使用 HashMap 来实现。在 单机环境 下没有问题,但是在 分布式环境 下就不行了。
在 Java 中,你可以利用 URLEncoder 和 URLDecoder 来对 URL 字符串进行编解码,然后使用 String.split() 方法或者使用 正则表达式 来从 URL 字符串中获取参数。
/**
* 获取url中的参数
*
* @param url 链接
* @param key 参数key
* @return 参数值
*/
public static String getParameterFromUrl(String url, String key) {
String[] params = url.split("\\?");
String[] queryParams = params[1].split("&");
String result = "";
for (String queryParam : queryParams) {
String[] param = queryParam.split("=");
// System.out.println("key: " + param[0] + " value: " + param[1]);
if (param[0].equals(key)) {
result = param[1];
break;
}
}
return result;
}
pnpm 更新可以使用下面脚本
用 npm rm -g pnpm 之后在重新 npm i -g pnpm 就可以了。
主要使用了 ed25519 库
加解密和验证代码
// Common.js and ECMAScript Modules (ESM)
import * as ed from '@noble/ed25519';
// If you're using single file, use global variable instead: `window.nobleEd25519`
const verifyEd = async function (prikey, pubkey) {
console.log("你输入的私钥是:" + prikey)
console.log("环境变量中的公钥是:" + pubkey)
// ====================
// 新私钥开始
// ====================
// const newPrivateKey = ed.utils.randomPrivateKey();
// const privateKeyStr = Buffer.from(newPrivateKey).toString('base64');
// console.log("new privateKey=>", privateKeyStr)
// ====================
// 新私钥结束
// ====================
const privateKeyStr = prikey
const privateKey = Buffer.from(privateKeyStr, 'base64');
// console.log("parsed privateKey=>", privateKey)
// ====================
// 新公钥开始
// ====================
// const newPublicKey = await ed.getPublicKey(privateKey);
// const publicKeyStr = Buffer.from(newPublicKey).toString('base64');
// console.log("new publicKey=>", publicKeyStr)
// ====================
// 新公钥结束
// ====================
const publicKeyStr = pubkey
const publicKey = Buffer.from(publicKeyStr, 'base64');
// console.log("parsed publicKey=>", publicKey)
try {
const valiPass = "123456";
const message = Uint8Array.from(valiPass, x => x.charCodeAt(0))
// const messageStr = Buffer.from(message).toString('base64');
// console.log("校验密码:", valiPass)
const signature = await ed.sign(message, privateKey);
const isValid = await ed.verify(signature, message, publicKey);
// console.log("验证结果:", isValid ? "有效" : "无效")
return isValid;
} catch (e) {
console.warn("校验失败,请检查密码", e)
return false;
}
}
const privateKeyStr = "prikey";
const publicKeyStr = "pubkey"
const valiResult = verifyEd(privateKeyStr, publicKeyStr)
valiResult.then(function(item){
console.log("item=>", item)
})
注意:Struts2使用标签库找不到URI:[struts-tags]的taglib[s]问题解决
新建 login2.jsp 文件,内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Struts2.3 Login2</title>
</head>
<body>
<s:form action="login">
<s:textfield name="username" label="username"></s:textfield>
<s:textfield name="password" label="password"></s:textfield>
<s:submit label="submit"></s:submit>
</s:form>
</body>
</html>
包装类(Wrapper Class)。
针对原生数据类型的包装。 包装类(8 个)都位于 java.lang 包下。
java 中的 8 个包装类分别是:Byte,Short,Integer,Long,Float,Double,Character,Boolean。
他们的使用方式都是一样的,可以实现原生数据类型和包装类额双向转换。
数组(Array):相同类型 数据的集合叫做数组。
如何定义数组:
type[] 变量名 = new type[数组中元素的个数 ];
按照下列方式定义长度为 10 的数组:
int[] a = new int[10]; // 或者
int a[] = new int[10];
数组中的元素索引是从 0 开始的。对于数组来说,最大的索引 == 数组的长度 - 1 。
定义数组的第三种方式:
type[] 变量名 = new type[]{逗号分隔的初始化值列表}
Java 中的每个数组都有一个 length 属性,他表示数组的长度。
length 属性是 public,final,int 的。数组长度一旦确定,就不能改变大小。
类中的属性又叫做成员变量(member variable),属性用英文表示为 property 或者
attribute。
对象(Object)又叫做实例(Instance)。生成一个对象的过程又叫做实例化。
命名约定
a) 类:首字母大写,如果一个类名由多个单词构成,那么每个单词的首字母都大写,
中间不使用任何的连接符。比如 Person 类,MemberTest 类。
b) 方法:首字母小写。如果一个方法由多个单词构成,那么第一个单词的所有字母全
都小写,从第二个单词开始,每个单词的首字母大写。比如 add,addThreeInt。
c) 属性:命名约定与方法相同。比如 age,ageOfPerson。
属性需要定义在类中,又叫做成员变量;而定义在方法中的变量叫做局部变量。
如何定义属性?
class 类的名字{
修饰符 val 属性名称
}
public class Person{
修饰符 类型 属性名称;
}
如何使用属性?与方法一样,使用.运算符。首先需要生成类的实例,然后使用实例 +”.” 的方式来使用属性。
比如:
val person = Person()
person.age
Person person = new Person();
person.age
局部变量使用前必须要声明并赋初值;成员变量使用前必须要声明,但可以不赋初值。
成员变量与局部变量的联系与区别:
a) 无论是成员变量还是局部变量,使用前都需要声明(定义)。
b) 对于局部变量来说,使用前必须要初始化;对于成员变量来说,使用前可以不初 始化。如果没有初始化成员变量就开始使用,那么每个类型的成员变量都有一个 默认的初始值
i. byte、short、int、long 类型的初始值为 0
ii. float、double 类型的初始值为 0.0
iii. char 类型的初始值 ‘\u0000’
iv. boolean 类型的初始值为 false
引用类型(reference type):引用类型是用在对象上的。一个对象可以被多个引用所指
向,但同一时刻,每个引用只能指向唯一的一个对象。如果一个对象被多个引用所指向,
那么无论哪个引用对对象的属性进行了修改,都会反映到其他的引用当中。
Inheritence)、封装(Encapsulation)、多态 (Polymorphism) 修饰符 class 类的名字{
// 类的内容(包含了属性与方法)
}
break 语句:经常用在循环语句中,用于跳出整个循环,执行循环后面的代码。
continue 语句:经常用在循环语句中,用于跳出当前的这个循环(或者是跳出本次循环), 开始下一次循环的执行。
break 与 continue 可以搭配标签使用,在实际开发中,根本没有人会将 break 与 continue 搭配标签来使用。
面向对象程序设计(Object Oriented Programming,OOP;Object Oriented Design, OOD)。
什么是面向对象?
在面向对象程序设计中有两个重要的概念:类(class)与对象(object)。
类:类是一种抽象的概念,类中包含了数据(通常使用名词来表示)与对数据的操纵(通 常使用动词来表示)。
比如说人就是一种抽象的概念,人具有姓名、年龄、身高等数据, 还有吃饭、跑步等操纵数据的动作。
对象:对象是一种具体的概念,是类的一种具体表示方式。比如说人是一个类,而张三、 李四、王五等具体的人就是对象。
类所包含的内容,类一共包含两部分内容:
a) 数据,数据在类中称作属性(Property 或者 Attribute)或者叫成员变量(Member variable)。
b) 对数据的操纵,这种操纵在类中称作方法(method)。