Skip to main content

12 posts tagged with "java"

View All Tags

· 2 min read
Ma Chu

Java中的long类型是64位的,而int类型是32位的,因此在将long转换为int时,需要注意可能会发生数据截断。
如果long类型的值超出了int类型的范围,转换后的值可能会失真或者出现错误。下面是两种可能的方法来将long类型转换为int类型:

  1. 使用强制类型转换
    可以使用强制类型转换将long类型转换为int类型,但需要注意可能会出现数据截断的问题,如下所示:
long l = 1234567890L;
int i = (int) l; // 数据截断,i的值为-53922298
  1. 使用Math类的方法
    Java提供了Math类来处理数学运算,其中有一些方法可以将long类型转换为int类型,如下所示:
long l = 1234567890L;
int i = Math.toIntExact(l); // i的值为1234567890

其中,Math.toIntExact()方法会将long类型的值转换为int类型,如果long类型的值超出了int类型的范围,会抛出ArithmeticException异常。

· One min read
Ma Chu

在HTML中,可以使用CSS属性来控制文本的自动换行。其中,word-wrapwhite-space 属性可以用来实现自动换行。

word-wrap 属性可以强制文本在单词内换行,避免长单词溢出容器边界。可以将其设置为 break-word,如下所示:

span {
word-wrap: break-word;
}

white-space 属性可以控制如何处理空格和换行符。可以将其设置为 normalpre-wrap 来启用自动换行,如下所示:

span {
white-space: normal; /* 或者 pre-wrap */
}

同时,也可以使用 max-width 属性来限制span的宽度,超出的内容会自动换行。例如:

span {
max-width: 200px; /* 将span的最大宽度设置为200像素 */
}

使用这些属性可以实现span的自动换行。

· 4 min read
Ma Chu

Gradle 支持使用以下几种语言编写 build.gradle 文件:

  1. Groovy:Groovy 是 Gradle 的默认语言,也是最常用的一种。使用 Groovy 编写的 build.gradle 文件通常更加简洁易懂。

  2. Kotlin:从 Gradle 3.0 开始,Gradle 开始支持使用 Kotlin 作为 build.gradle 文件的编写语言。与 Groovy 相比,Kotlin 具有更强的类型安全和表达能力。

  3. Scala:Gradle 还支持使用 Scala 语言编写 build.gradle 文件,Scala 是一种强类型的函数式编程语言。

可以使用Java中的Groovy语言库来解析build.gradle文件并获取依赖信息。下面是一个示例代码片段,展示了如何使用Groovy来解析build.gradle文件并获取其依赖项:

import groovy.util.Node
import groovy.util.NodeList
import groovy.util.XmlParser

public class GradleDependencyParser {

public static void main(String[] args) {
String buildFilePath = "path/to/build.gradle";
GradleDependencyParser parser = new GradleDependencyParser();
parser.parse(buildFilePath);
}

public void parse(String buildFilePath) {
XmlParser parser = new XmlParser(false, false);
Node rootNode = parser.parse(new File(buildFilePath));
NodeList dependencies = rootNode.depthFirst().findAll { it.name() == 'dependencies' }[0];
dependencies.children().each { dependency ->
String group = dependency.attributes().get("group");
String name = dependency.attributes().get("name");
String version = dependency.attributes().get("version");
System.out.println("Group: " + group + ", Name: " + name + ", Version: " + version);
}
}
}

这个例子使用了groovy.util.XmlParser来解析build.gradle文件,然后使用depthFirst()方法遍历了整个XML树,查找所有名为dependencies的节点,并且遍历每个依赖项节点,获取其中的group、name和version属性,并打印输出。

需要注意的是,Gradle支持使用不同的语言来编写build.gradle文件,比如Groovy、Kotlin等,因此需要根据实际情况调整代码来解析不同的build.gradle文件。

与解析 Groovy 编写的 build.gradle 文件类似,解析 Kotlin 编写的 build.gradle.kts 文件也可以使用 Groovy 提供的 API 进行解析。

以下是一个示例代码片段,展示了如何使用 Groovy 解析 Kotlin 编写的 build.gradle.kts 文件并获取其中的依赖项:

import groovy.util.Node
import groovy.util.NodeList
import groovy.util.XmlParser
import org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory
import javax.script.ScriptEngine

public class KotlinGradleDependencyParser {

public static void main(String[] args) {
String buildFilePath = "path/to/build.gradle.kts";
KotlinGradleDependencyParser parser = new KotlinGradleDependencyParser();
parser.parse(buildFilePath);
}

public void parse(String buildFilePath) {
ScriptEngine engine = new KotlinJsr223JvmLocalScriptEngineFactory().scriptEngine
engine.eval("file(\"" + buildFilePath + "\").readText()")
String dependencies = (String) engine.eval("kotlin.runCatching {"
+ "val deps = arrayListOf<String>()\n"
+ "dependencies {\n"
+ " classpath.forEach { dep -> deps.add(\"${dep.group}:${dep.name}:${dep.version}\") }\n"
+ "}\n"
+ "deps.joinToString(\"\n\")"
+ "}.getOrNull()");
System.out.println(dependencies);
}
}

这个例子使用了 org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory 类来创建一个可以解析 Kotlin 脚本的 ScriptEngine。然后使用 eval 方法将 Kotlin 脚本读入并执行,获取其中的依赖项,并将结果作为字符串返回。

需要注意的是,Kotlin 编写的 build.gradle.kts 文件与 Groovy 编写的 build.gradle 文件有所不同,因此需要根据实际情况调整代码来解析不同的 build.gradle.kts 文件。

· One min read
Ma Chu
@Configuration
public class CorsConfig {

@Value("${configure.cors.enable:true}")
private Boolean corsIsEnable;

private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 你需要跨域的地址 注意这里的 127.0.0.1 != localhost
// * 表示对所有的地址都可以访问
//corsConfiguration.addAllowedOrigin("*");
// 升级boot版本后需要使用addAllowedOriginPattern
corsConfiguration.addAllowedOriginPattern("*");
// 跨域的请求头
corsConfiguration.addAllowedHeader("*"); // 2
// 跨域的请求方法
corsConfiguration.addAllowedMethod("*"); // 3
//加上了这一句,大致意思是可以携带 cookie
//最终的结果是可以 在跨域请求的时候获取同一个 session
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}

@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//配置 可以访问的地址
if(corsIsEnable){
source.registerCorsConfiguration("/**", buildConfig()); // 4
}
return new CorsFilter(source);
}
}

· One min read
Ma Chu

不保留原List进行翻转

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
System.out.println("翻转前:" + list);
Collections.reverse(list);
System.out.println("反转后:" + list);

· One min read
Ma Chu

在使用webmagic爬取页面时,在download的时候,提示No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

原因是:jdk1.8高版本对ssl做了限制。

解决办法:

C:\Program Files\Java\jdk1.8.0_291\jre\lib\security目录下修改java.security文件。

image

找到jdk.tls.disabledAlgorithms,去除 SSLv3 即可(代表允许https)。

· 3 min read
Ma Chu
    public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true
System.out.println(a.equals(b)); // true

Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false
System.out.println(c.equals(d)); // true
}

Integer在判断相等时,当值定义在-128~127之间时,使用==或者equal()比较是一样的。但当值定义在这个范围时,equal()比较的是值,==比较的是内存地址

-128到127的范围内,Integer不对创建对象,而是直接取系统缓存中的变量数据。

    /**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/

private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];

static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;

cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);

// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}

private IntegerCache() {}
}

/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

· 4 min read
Ma Chu

get请求和post请求本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。

GET

从指定的资源请求数据,用于获取数据,一般用于搜索排序和筛选之类的操作。

  1. 浏览器请求tcp连接(第一次握手)。
  2. 服务器答应进行tcp连接(第二次握手)。
  3. 浏览器确认,并发送get请求头和数据(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)。
  4. 服务器返回200 OK响应。

post

向指定的资源提交要被处理的数据,用于将数据发送给服务器,一般用于修改和写入数据。

  1. 浏览器请求tcp连接(第一次握手)。
  2. 服务器答应进行tcp连接(第二次握手)。
  3. 浏览器确认,并发送post请求头(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)。
  4. 服务器返回100 Continue响应。
  5. 浏览器发送数据。
  6. 服务器返回200 OK响应。

区别

  • 安全
    • post请求更安全,不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中。
    • get请求的是静态资源,则会缓存,如果是数据,则不会缓存。
  • 数据包
    • post请求发送的数据更大。
    • get请求有url长度限制,http协议本身不限制,请求长度限制是由浏览器和web服务器决定和设置。
  • post请求能发送更多的数据类型(get请求只能发送ASCII字符)。
  • 传参方式不同(get请求参数通过url传递,post请求放在request body中传递)。
  • get请求的是静态资源,则会缓存,如果是数据,则不会缓存。
  • get请求产生一个TCP数据包;post请求产生两个TCP数据包(get请求,浏览器会把http header和data一并发送出去,服务器响应200返回数据;post请求,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 返回数据)。

在发送 POST 的时候都没有带 Expect 头,server 也自然不会发 100 continue。

· One min read
Ma Chu

路由转发

location / {
proxy_pass http://127.0.0.1:8001; # 反向代理到 8001 端口
add_header Access-Control-Allow-Origin *;
}

· One min read
Ma Chu
select @@global.sql_mode;
set @@global.sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

· 2 min read
Ma Chu

将下列代码拷贝至jsencrypt.js中,在JSEncrypt.version = "3.1.4";前面加入

   //任意长度RSA Key分段加密解密长字符串
//获取RSA key 长度
JSEncrypt.prototype.getkeylength = function () {
return ((this.key.n.bitLength()+7)>>3);
};

// 分段解密,支持中文
JSEncrypt.prototype.decryptUnicodeLong = function (string) {
var k = this.getKey();
//解密长度=key size.hex2b64结果是每字节每两字符,所以直接*2
var maxLength = ((k.n.bitLength()+7)>>3)*2;
try {
var hexString = b64tohex(string);
var decryptedString = "";
var rexStr=".{1," + maxLength + "}";
var rex =new RegExp(rexStr, 'g');
var subStrArray = hexString.match(rex);
if(subStrArray){
subStrArray.forEach(function (entry) {
decryptedString += k.decrypt(entry);
});
return decryptedString;
}
} catch (ex) {
return false;
}
};

// 分段加密,支持中文
JSEncrypt.prototype.encryptUnicodeLong = function (string) {
var k = this.getKey();
//根据key所能编码的最大长度来定分段长度。key size - 11:11字节随机padding使每次加密结果都不同。
var maxLength = ((k.n.bitLength()+7)>>3)-11;
try {
var subStr="", encryptedString = "";
var subStart = 0, subEnd=0;
var bitLen=0, tmpPoint=0;
for(var i = 0, len = string.length; i < len; i++){
//js 是使用 Unicode 编码的,每个字符所占用的字节数不同
var charCode = string.charCodeAt(i);
if(charCode <= 0x007f) {
bitLen += 1;
}else if(charCode <= 0x07ff){
bitLen += 2;
}else if(charCode <= 0xffff){
bitLen += 3;
}else{
bitLen += 4;
}
//字节数到达上限,获取子字符串加密并追加到总字符串后。更新下一个字符串起始位置及字节计算。
if(bitLen>maxLength){
subStr=string.substring(subStart,subEnd)
encryptedString += k.encrypt(subStr);
subStart=subEnd;
bitLen=bitLen-tmpPoint;
}else{
subEnd=i;
tmpPoint=bitLen;
}
}
subStr=string.substring(subStart,len)
encryptedString += k.encrypt(subStr);
return hex2b64(encryptedString);
} catch (ex) {
return false;
}
};
//添加的函数与方法结束