Java 开发常用工具方法
BigDecimal与Double的区别和使用场景
https://blog.csdn.net/qq_43842093/article/details/135038362
Double的问题
在计算时会出现不精确的问题
public static void main(String[] args) {
System.out.println(12.3 + 45.6); // 57.900000000000006
System.out.println(12.3 / 100); // 0.12300000000000001
}
小数部分无法使用二进制准确的表示
等于判断在使用时需要注意
public static void main(String[] args) {
double a = 2.111111111111111111111111112;
double b = 2.111111111111111111111111113;
// duoble超过15位以后就会不对了
System.out.println(a == b); // true
}
BigDecimal的问题
使用除法时除不尽会报 ArithmeticException 异常
public static void main(String[] args) {
// 报异常:Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
System.out.println(BigDecimal.valueOf(121).divide(BigDecimal.valueOf(3)));
}
public static void main(String[] args) {
// 需要指定精度和舍入方式,当除不尽时也不会报异常
// 运行结果为 40.33
System.out.println(BigDecimal.valueOf(121).divide(BigDecimal.valueOf(3), 2, RoundingMode.HALF_UP));
}
new BigDecimal(double)结果或许预料不到
public static void main(String[] args) {
BigDecimal a = new BigDecimal(12.3);
BigDecimal b = BigDecimal.valueOf(12.3);
// Double的小数位其实无法被精确表示,所以传入的.3被精度扩展之后精度丢失,展示出来的并不是精确的.3
// 结果为12.300000000000000710542735760100185871124267578125
System.out.println(a);
// 从底层代码可以看出来,BigDecimal.valueOf 会先转换为字符串之后再调用new BigDecimal,不会造成精度丢失
// 结果为12.3
System.out.println(b);
}
所以一般情况下会使用BigDecimal.valueOf()而不是new BigDecimal()。
另:BigDecimal.valueOf() 是静态工厂类,永远优先于构造函数。
BigDecimal是不可变类
不可变类代表着,任何针对BigDecimal的修改都将产生新对象。所以每次对BigDecimal的修改都要重新指向一个新的对象。
public static void main(String[] args) {
BigDecimal a = BigDecimal.valueOf(12.3);
a.add(BigDecimal.valueOf(2.1));
System.out.println(a); // 12.3,值未修改
BigDecimal b = BigDecimal.valueOf(12.3);
// 重新赋值给新对象
BigDecimal c = b.add(BigDecimal.valueOf(2.1));
System.out.println(c); // 14.4
}
BigDecimal大小的比较都需要使用compareTo,如果需要返回更大的数或更小的数可以使用max、min。还要注意在BigDecimal中慎用equals。
public static void main(String[] args) {
BigDecimal a = BigDecimal.valueOf(12.3);
BigDecimal b = BigDecimal.valueOf(12.32);
System.out.println(a.compareTo(b)); // -1
System.out.println(b.compareTo(a)); //1
System.out.println(a.max(b)); // 12.32
System.out.println(a.min(b)); // 12.3
System.out.println(b.max(a)); // 12.32
System.out.println(b.min(a)); // 12.3
System.out.println(BigDecimal.valueOf(1).equals(BigDecimal.valueOf(1.0))); //false
}
BigDecimal重写了equals方法,在equals方法里比较了小数位数,在方法注释上也有说明,所以 BigDecimal.valueOf(1).equals(BigDecimal.valueOf(1.0)) 为什么结果为false就可以理解了。
静态map初始化并赋值问题
代码评审——静态map初始化并赋值问题_map静态代码块改造-CSDN博客
// 方法一
public static final Map<String, String> staticMap = createMap();
private static Map<String, String> createMap() {
Map<String, String> result = new HashMap<>();
result.put("1", "one");
result.put("2", "two");
return Collections.unmodifiableMap(result);
}
// 方法二
public static final Map<String, String> staticMap;
static {
staticMap = new HashMap<String, String>();
staticMap.put("1", "one");
staticMap.put("2", "two");
staticMap.put("3", "three");
staticMap.put("4", "four");
staticMap.put("5", "five");
}
// 方法三:使用Map.ofEntries初始化(仅支持Java 9+)其中,Map.of()仅能初始化10以内的数据
private static final Map<String,String> staticMap = Map.ofEntries(
entry("1", "one"),
entry("2", "two"),
entry("3", "three"),
entry("4", "four"),
entry("5", "five")
);
简单文件读写
// 读取数据
Path path = Paths.get("D:/aa.txt");
byte[] data = Files.readAllBytes(path);
String result = new String(data, StandardCharsets.UTF_8);
// 写入到文件
FileWriter writer = new FileWriter("D:/aa.txt");
writer.write("hello world");
writer.close();
CollectionUtils
import org.apache.commons.collections4.CollectionUtils;
// 判断集合是否为空
CollectionUtils.isEmpty(list)
CollectionUtils.isNotEmpty(list)
// 不要用 list.isEmpty(),因为如果 list = null,会报空指针异常。
// 控制层接口中如果规定返回的数据是 List<实体类> 的型式,而结果为空的话,可以使用:
return Lists.newArrayList();
// 初始化集合
List<Object> list = Lists.newArrayList();
StringUtils
// lang包可视作废弃,不再使用
import org.apache.commons.lang3.StringUtils;
// 常用方法
isEmpty(String str) //是否为空,空格字符为false
isNotEmpty(String str) //是否为非空,空格字符为true
isBlank(String str) //是否为空,空格字符为true
isNotBlank(String str) //是否为非空,空格字符为false
trim(String str) //去除字符串两端的控制符,空字符串、null 返回 null
trimToEmpty(String str) //去除字符串两端的控制符,空字符串、null 返回""
stripToNull(String str) //去除字符串两端的空白符,空字符串、null 返回null
stripToEmpty(String str) //去除字符串两端的空白符,空字符串、null 返回""
strip(String str, String stripChars) //去掉str两端的在stripChars中的字符
StringUtils.strip("000000134_76539000","0")="134_76539"
stripStart (String str,String stripChars) //去除str 前端在stripChars中的字符
stripEnd (String str,String stripChars) //去除str 后端在stripChars中的字符
equals(String str1,String str2) //比较两个字符串是否相等,如果两个均为空则认为相等
indexOf(String str,char searchChar) //返回searchChar 在字符串中第一次出现的位置,如果没找到则返回 -1,如果str 为null 或者 "",也返回-1
indexOf(String str,char searchChar,int startPos) //返回字符searchChar从startPos开始在字符串str中第一次出现的位置。
contains(String str,char searchChar) //str中是否包含字符searchChar,str为null 或者 searchChar为null,返回false 。
StringUtils.contains("", "") = true
StringUtils.contains("dfg", "") = true
containsIgnoreCase(String str,String searchStr) //str中是否包含字符searchChar,不区分大小写
int indexOfAny(String str, char[] searchChars) //找出字符数组searchChars中的字符第一次出现在字符串str中的位置。 如果字符数组中的字符都不在字符串中,则返回-1 ,如果字符串为null或"",则返回-1
subString(String str,int start) //从start 开始,包含start 那个字符,得到字符串str 的子串,如果start为负数,则从后面开始数起。如果str 为null 或者 "" 则返回其本身
subStringBefore(String str,String separator) //得到字符串separator第一次出现前的子串。不包含那个字符,如果str 为null 或者 "" 则返回其本身。
subStringAfter(String str,String separator) //得到字符串separator第一次出现后的子串,不包含那个字符,如果 str 为null,或者"",则返回其本身
subString(String str,int start,int end) //同上
left(String str,int len) //得到字符串str从左边数len长度的子串,如果str 为null 或者 "",则返回其本身,如果len小于0,则返回""
right(String str,int len) //得到字符串str从右边数len长度的子串
mid(String str,int pos,int len) //得到字符串str从pos开始len长度的子串,pos小于0,则设为0。
split(String str) //把字符串拆分成一个字符串数组,用空白符 作为分隔符,字符串为null 返回null,字符串为"",返回空数组{}
split(String str,char c) //按照 char c 拆分字符串
join(Object[] arrey) //把数组中的元素连接成一个字符串返回
join(Object[] arrey,char c) //把数组中的元素拼接成一个字符串返回,把分隔符 c 也带上
deleteWhitespace(String str) //删除字符串中的所有空白符,包括转义字符
removeStart(String str,String remove) //如果字符串str是以remove开始,则去掉这个开始,然后返回,否则返回原来的串
removeEnd(String str,String remove) //如果字符串str是以字符串remove结尾,则去掉这个结尾,然后返回,否则返回原来的串。
remove(String str,char remove) //去掉字符串str中所有包含remove的部分,然后返回
replace(String str,String reql,String with) //在字符串text中用with代替repl,替换所有
replaceChars(String str,char old,char new) //在字符串中 new 字符代替 old 字符
replaceChars(String str, String searchChars, String replaceChars) //这个有点特别,先看下面三个例子
StringUtils.replaceChars("asssdf","s","yyy")) = "ayyydf"
StringUtils.replaceChars("asdf","sd","y")) = "ayf"
StringUtils.replaceChars("assssddddf","sd","y"))= "ayyyyf"
//解释:为什么会出现上面这样的结果呢?原来这个置换规则是这样的,他是拿searchChars的index,去replaceChars找相应的index然后替换掉,怎么说呢?比如说第一个例子 s 的index 是0,找到yyy相对应的index为0的字符是y。第二个例子 's' 的index是0,'d'的index是1, 字符's' 可以找到对应index为0的 'y',d就找不到index为'1'的的字符了,所以就直接过滤掉了,听明白了吗?
overlay(String str,String new,int start,int end) //用字符串new 覆盖字符串str从start 到 end 之间的串
chop(String str) //去掉字符串的最后一个字符,比如/r/n
repeat(String str,int repart) //重复字符串repeat次
rightPad(String str,int size,String padStr) //size长度的字符串,如果不够用padStr补齐
leftPad(String str,int size,String padStr) //同上
center(String str,int size) //产生一个字符串,长度等于size,str位于新串的中心
swapCase(String str) //字符串中的大写转小写,小写转换为大写
IOUtils
import org.apache.tomcat.util.http.fileupload.IOUtils;
try {
InputStream inputStream = new FileInputStream("d:/test.txt");
OutputStream outputStream = new FileOutputStream(new File("d:/test_copy.txt"));
IOUtils.copy(inputStream,outputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
RandomStringUtils
//产生5位长度的随机字符串,中文环境下是乱码[/b]
RandomStringUtils.random(5);
//使用指定的字符生成5位长度的随机字符串[/b]
RandomStringUtils.random(5, new char[]{'a','b','c','d','e','f', '1', '2', '3'});
//生成指定长度的字母和数字的随机组合字符串[/b]
RandomStringUtils.randomAlphanumeric(5);
//生成随机数字字符串[/b]
RandomStringUtils.randomNumeric(5);
//生成随机[a-z]字符串,包含大小写[/b]
RandomStringUtils.randomAlphabetic(5);
//生成从ASCII 32到126组成的随机字符串 [/b]
RandomStringUtils.randomAscii(4)
for (int i = 0;i<10;i++) {
System.out.println(RandomStringUtils.randomAlphanumeric(5).toLowerCase());
}
Lists
// 依赖:
/**
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
*/
import com.google.common.collect.Lists;
List<User> userList = Lists.newArrayList(
new User().setId("A").setName("张三"),
new User().setId("B").setName("李四"),
new User().setId("C").setName("王五")
);
Strings
// 创建空字符串
String str = Strings.EMPTY;
// 拆分字符串,如果要拆分:"com.fzai.test" 型式的字符串,"." 要加上转义字符 "\\."
String name = "com.fzai.test";
name.split("\\.");
FastJson
// 解决将对象转换成JSON字符串时出现 $ref 字符的问题:
JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
//JSONObject转对象
String JSONStr = JSON.toJSONString(jsonObject);
BusLine busLine = JSON.parseObject(JSONStr, BusLine.class);
// JSONArray转对象集合
String JSONStr = JSON.toJSONString(jsonArray);
List<BusLine> busLineList = JSON.parseObject(JSONStr,new TypeReference<List<BusLine>>(){});
Date
// 获取年月日
Date dt=new Date();
String year=String.format("%tY", dt);
String mon=String .format("%tm", dt);
String day=String .format("%td", dt);
System.out.println(year);
System.out.println(mon);
System.out.println(day);
Pattern
// 获取引号内的内容
public static List getContent(String str){
Pattern p1=Pattern.compile("\"(.*?)\"");
Matcher m = p1.matcher(str);
StringBuilder stringBuilder = new StringBuilder();
ArrayList<String> list = new ArrayList<String>();
while (m.find()) {
list.add(m.group().trim().replace("\"","")+" ");
}
return list;
}
stream
// 拆分字符串并将结果数组转换成Integer集合
String str = "1,2,3,4,5,6";
List<Integer> collect = Arrays.stream(StringUtils.split(str, ",")).map(Integer::parseInt).collect(Collectors.toList());
// 对象集合根据对象的某个字段去重
List<TermiteCensus> all = termiteCensusList.stream()
.collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
new TreeSet<>(Comparator.comparingLong(TermiteCensus::getDbBasicInformationId))), ArrayList::new));
list
list.removeif()
//问题:有0,1,2,3,4五个人,需要从list中获取数据,要求每个人的数据中不包含他们本身。
//思路:将原数据集合list复制到result,然后从result移除数据;
//注意:不能直接使用list做removeif(),因为如果直接从list移除数据,会把list中的0,1,2,3,4都移除,导致最后一次操作之后list中只剩5,6,7。
ArrayList<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);
ArrayList<Integer> result = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
result.addAll(list);
int finalI = i;
result.removeIf(j -> j == finalI);
System.err.println(result);
result.clear();
}
System.err.println(">>>"+list);
list.clear()
字符串等值判断忽略大小写
String order = "asc";//String order = "ASC";
if("asc".equalsIgnoreCase(order){
...
}
long和int互转
Long a = 123L;
Integer b = 123;
int i = a.intValue();
long l = b.longValue();
byte数组与InputStream之间的转换
https://blog.csdn.net/weixin_39911066/article/details/114800383
// 将File、FileInputStream 转换为byte[]数组:
File file = new File("file.txt");
InputStream input = new FileInputStream(file);
byte[] byt = new byte[input.available()];
input.read(byt);
// 将byte[]数组转换为InputStream:
byte[] byt = new byte[1024];
InputStream input = new ByteArrayInputStream(byt);
// 将byte[]数组转换为File:
File file = new File('');
OutputStream output = new FileOutputStream(file);
BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);
bufferedOutput.write(byt);
// 字符串(String) 与 byte[] 数组
String str = "字符串与byte[]数组";
byte[] bytes = str.getBytes();
InputStream inputStream = new ByteArrayInputStream(bytes);
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];
int rc = 0;
while ((rc = inputStream.read(buff, 0, 100)) > 0) {
byteArrayOutputStream.write(buff, 0, rc);
}
byte[] bytes1 = byteArrayOutputStream.toByteArray();
String string = new String(bytes1, StandardCharsets.UTF_8);
System.out.println("string = " + string);
} catch (IOException e) {
System.out.println(e.toString());
}
项目启动时执行指定代码
@Order(value = 1) // 根据value大小决定类执行顺序
@Component
public class MyApplicationRunner implements ApplicationRunner{
@Override
public void run(ApplicationArguments args) throws Exception{
//假装有代码
}
}
删除指定文件夹及文件夹下文件
/**
* 删除目标文件夹下所有文件
* @param file
* @return
*/
public boolean deleteFile(File file){
//判断文件不为null或文件目录存在
if (file == null || !file.exists()){
return false;
}
//取得这个目录下的所有子文件对象
File[] files = file.listFiles();
//遍历该目录下的文件对象
if (files != null) {
for (File f: files){
//判断子目录是否存在子目录,如果是文件则删除
if (f.isDirectory()){
deleteFile(f);
}else {
f.delete();
}
}
}
//删除空文件夹 for循环已经把上一层节点的目录清空。
file.delete();
return true;
}
LocalDateTime获取前一天
http://www.yq1012.com/shizhan/4329.html
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String timeNode = df.format(LocalDateTime.now().minusDays(1)); // 昨天
String timeNode = df.format(LocalDateTime.now().plusDays(1)); // 明天
实体对象转map
// fastjson
Map newMap = JSON.parseObject(JSON.toJSONString(newUser), Map.class);
从Timestamp获取年份
int year = Timestamp对象.getYear() + 1900;
获取当前年份
int now = Calendar.getInstance().get(Calendar.YEAR);
文件分隔符
File.separator
/**
* File.separator 的作用相当于 ' \ '
* 在 windows 中 文件文件分隔符 用 ' \ ' 或者 ' / ' 都可以
* 但是在 Linux 中,是不识别 ' \ ' 的,而 File.separator 是系统默认的文件分隔符号,在 UNIX 系统上,此字段的值为 ' / '
* 所以用 File.separator 保证了在任何系统下不会出错。
*/
/upload + File.separator + 20211105/test.zip
upload/20211105/test.zipt/.zip
文件大小转换
/**
* 定义GB的计算常量
*/
private static final int GB = 1024 * 1024 * 1024;
/**
* 定义MB的计算常量
*/
private static final int MB = 1024 * 1024;
/**
* 定义KB的计算常量
*/
private static final int KB = 1024;
/**
* 文件大小转换
*/
public static String getSize(long size) {
String resultSize;
if (size / GB >= 1) {
//如果当前Byte的值大于等于1GB
resultSize = DF.format(size / (float) GB) + "GB ";
} else if (size / MB >= 1) {
//如果当前Byte的值大于等于1MB
resultSize = DF.format(size / (float) MB) + "MB ";
} else if (size / KB >= 1) {
//如果当前Byte的值大于等于1KB
resultSize = DF.format(size / (float) KB) + "KB ";
} else {
resultSize = size + "B ";
}
return resultSize;
}
文件压缩
// 导包
import java.io.*;
import java.util.List;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import com.google.common.collect.Lists;
// 代码
List<File> files = Lists.newArrayList();
FileOutputStream f = null;
try {
f = new FileOutputStream("D:\\test.zip");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
CheckedOutputStream checkedOut = new CheckedOutputStream(f, new Adler32());
ZipOutputStream zipOut = new ZipOutputStream(checkedOut);
BufferedOutputStream bufferedOut = new BufferedOutputStream(zipOut);
try {
for (File file : files) {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
try {
// 设置文件名,如果为“aaa/bbb/ccc.txt”的形式,则会在test.zip中有对应的文件夹aaa、bbb
zipOut.putNextEntry(new ZipEntry(file.getName()));
byte[] buffer = new byte[1024];
int i = bis.read(buffer);
while (i != -1) {
bufferedOut.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bufferedOut.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bufferedOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
创建多级文件夹
mkdirs()
比如在D盘创建文件夹 temp,在temp中又创建file,在file中又创建download:
new file("D:/temp/file/download").makirs();
如果使用mkdir就只能一级一级创建。
日期转换
// 各种日期格式
// 中国标准时间:Wed Feb 13 2019 16:49:31 GMT+0800
// 格林威治时间:Wed, 13 Feb 2019 08:49:31 GMT
// 国际标准组织(ISO)格式:2019-02-13T08:49:31.342Z
// String转Timestamp
Timestamp.valueOf(string);
// String转LocalDateTime
String date = "2020-05-24 10:43:12";
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime time = LocalDateTime.parse(date, df);
System.err.println(time);
// Date转LocalDateTime
//将java.util.Date 转换为java8 的java.time.LocalDateTime,默认时区为东8区
Date date = new Date();
date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDateTime();
//将java8 的 java.time.LocalDateTime 转换为 java.util.Date,默认时区为东8区
Date.from(LocalDateTime.now().toInstant(ZoneOffset.of("+8")));
// LocalDateTime 转 Timestamp
Timestamp.valueOf(LocalDateTime.now())
// Timestamp 转 LocalDateTime
Timestamp.from(Instant.now()).toLocalDateTime()
// LocalDateTime转Instant
import java.time.LocalDateTime; //导入方法依赖的package包/类
public static Instant parseDateInstant(String strDate) {
LocalDateTime dateTime = parseDate(strDate);
if (dateTime != null) {
return dateTime.toInstant(ZoneOffset.UTC);
}
return null;
}
// LocalDateTime转字符串
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now())
// ISO时间转换成标准时间
Date parse = ISO8601Utils.parse(changeSafetyProblem.getAfterChange());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = dateFormat.format(parse);
String转数字类型
Integer.parseInt(str)
Long.parseLong(str)
Double.parseDouble(str)
array转list
Arrays.asList(array)
Object转Map
使用Apache中的BeanUtils类,导入commons-beanutils包
jar包的下载地址:https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils。
//1、map转换为object
public static Object mapToObject(Map<String, Object> map, Class<?> beanClass)
throws Exception {
if (map == null) {
return null;
}
Object obj = beanClass.newInstance();
org.apache.commons.beanutils.BeanUtils.populate(obj, map);
return obj;
}
//2、object转换为map
public static Map<?, ?> objectToMap(Object obj) {
if (obj == null) {
return null;
}
return new org.apache.commons.beanutils.BeanMap(obj);
}
利用java.lang.reflect.Field类完成Obj和Map之间的相互转换
//1、object转换成map
public Map<String,Object> Obj2Map(Object obj) throws Exception{
Map<String,Object> map=new HashMap<String, Object>();
Field[] fields = obj.getClass().getDeclaredFields();
for(Field field:fields){
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
return map;
}
//2、map转换为object
public Object map2Obj(Map<String,Object> map,Class<?> clz) throws Exception{
Object obj = clz.newInstance();
Field[] declaredFields = obj.getClass().getDeclaredFields();
for(Field field:declaredFields){
int mod = field.getModifiers();
if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
continue;
}
field.setAccessible(true);
field.set(obj, map.get(field.getName()));
}
return obj;
}
this::function
// this::function代表这个函数对象的方法,也可以用Object::function的方式。其中this::fuction不可以用在static方法上,而Object::function是用在Object类的static方法中。
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class Test {
public static void printValur(String str) {
System.out.println("print value : " + str);
}
public static void main(String[] args) {
List<String> al = Arrays.asList("a", "b", "c", "d");
al.forEach(Test::printValur);
// 下面的方法和上面等价的
Consumer<String> methodParam = Test::printValur; // 方法参数
al.forEach(x -> methodParam.accept(x));// 方法执行accept
}
}
HttpServletResquest、HttpServletResponse
@RequestMapping("/getTest")
publicResultgetTest(HttpServletResponseresponse,HttpServletRequestrequest){
try{
System.err.println(response.getStatus());//200
System.err.println("---------------------");
System.err.println(request.getRemoteAddr());//远程ip
System.err.println(request.getRemoteHost());//远程主机
System.err.println(request.getRemotePort());//远程端口
System.err.println(request.getRemoteUser());//远程用户
System.err.println(request.getRequestURI());//远程接口:/GCDA/getTest
System.err.println(request.getRequestURL());//远程地址:http://192.168.0.29:8082/GCDA/getTest
System.err.println(request.getServerName());//192.168.0.29
System.err.println(request.getServerPort());//8082
returnnewResult(true,MessageConstant.QUERY_GCDA_SUCCESS);
}catch(Exceptione){
e.printStackTrace();
returnnewResult(false,MessageConstant.QUERY_GCDA_FAIL);
}
}
String长度限制
String 类型长度不能大于等于65535,否则会编译失败。
数组转String并设置字符串编码
使用String类的构造方法:
byte[] bytes = new byte[]{72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100};
String str = new String(bytes);
System.out.println(str); // Hello World
str = new String(bytes, Charset.forName("UTF-8"));
System.out.println(str); // Hello World
使用编码类:
byte[] bytes = new byte[]{72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100};
Charset charset = Charset.forName("UTF-8");
ByteBuffer buffer = ByteBuffer.wrap(bytes);
String str = charset.decode(buffer).toString();
System.out.println(str); // Hello World
修改war包内容
1、将war包移动到一个干净的路径下,使用 jar xvf ROOT.war 命令将war进行解压操作。
2、修改相应的文件内容,修改想要修改的文件,比如web.xml。
3、使用 jar uvf ROOT.war WEB-INF/web.xml 将web.xml重新压缩到war包。
全局时间格式化
https://mp.weixin.qq.com/s/MeDfnL__jdEq7Yi48vg_vA
@JsonFormat 注解
@JsonFormat注解方式严格意义上不能叫全局时间格式化,应该叫部分格式化,因为@JsonFormat注解 需要用在实体类的时间字段上,而只有使用相应的实体类,对应的字段才能进行格式化。
@Data
public class OrderDTO {
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd")
private LocalDateTime createTime;
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
@JsonComponent 注解(推荐)
使用 @JsonComponent 注解自定义一个全局格式化类,分别对 Date 和 LocalDate 类型做格式化处理。实际开发中如果有个字段不想用全局格式化设置的时间样式,想自定义格式怎么办?那就需要和 @JsonFormat 注解配合使用了。@JsonFormat 注解的优先级比较高,会以 @JsonFormat 注解的时间格式为主。
@JsonComponent
public class DateFormatConfig {
@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
private String pattern;
/**
* @author xiaofu
* @description date 类型全局时间格式化
* @date 2020/8/31 18:22
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilder() {
return builder -> {
TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat(pattern);
df.setTimeZone(tz);
builder.failOnEmptyBeans(false)
.failOnUnknownProperties(false)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.dateFormat(df);
};
}
/**
* @author xiaofu
* @description LocalDate 类型全局时间格式化
* @date 2020/8/31 18:22
*/
@Bean
public LocalDateTimeSerializer localDateTimeDeserializer() {
return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());
}
}
@Configuration 注解
这种全局配置的实现方式与上边的效果是一样的。但是在使用此种配置后,字段手动配置@JsonFormat 注解将不再生效。
@Configuration
public class DateFormatConfig2 {
@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
private String pattern;
public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Bean
@Primary
public ObjectMapper serializingObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
/**
* @author xiaofu
* @description Date 时间类型装换
* @date 2020/9/1 17:25
*/
@Component
public class DateSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider) throws IOException {
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}
/**
* @author xiaofu
* @description Date 时间类型装换
* @date 2020/9/1 17:25
*/
@Component
public class DateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
try {
return dateFormat.parse(jsonParser.getValueAsString());
} catch (ParseException e) {
throw new RuntimeException("Could not parse date", e);
}
}
}
/**
* @author xiaofu
* @description LocalDate 时间类型装换
* @date 2020/9/1 17:25
*/
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.format(DateTimeFormatter.ofPattern(pattern)));
}
}
/**
* @author xiaofu
* @description LocalDate 时间类型装换
* @date 2020/9/1 17:25
*/
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException {
return LocalDateTime.parse(p.getValueAsString(), DateTimeFormatter.ofPattern(pattern));
}
}
}
两个字符串相似度
/**
* 字符串相似度
*
* @param sourceString /
* @param targetString /
* @return /
*/
public static double getStringSimilarity(String sourceString, String targetString) {
int[][] matrix;
int sourceStringLength = sourceString.length();
int targetStringLength = targetString.length();
int indexOfSourceString;
int indexOfTargetString;
char charOfSourceString;
char charOfTargetString;
int temp;
if (sourceStringLength == 0 || targetStringLength == 0) return 0;
matrix = new int[sourceStringLength + 1][targetStringLength + 1];
for (indexOfSourceString = 0; indexOfSourceString <= sourceStringLength; indexOfSourceString++) {
matrix[indexOfSourceString][0] = indexOfSourceString;
}
for (indexOfTargetString = 0; indexOfTargetString <= targetStringLength; indexOfTargetString++) {
matrix[0][indexOfTargetString] = indexOfTargetString;
}
for (indexOfSourceString = 1; indexOfSourceString <= sourceStringLength; indexOfSourceString++) {
charOfSourceString = sourceString.charAt(indexOfSourceString - 1);
for (indexOfTargetString = 1; indexOfTargetString <= targetStringLength; indexOfTargetString++) {
charOfTargetString = targetString.charAt(indexOfTargetString - 1);
if (charOfSourceString == charOfTargetString || charOfSourceString == charOfTargetString + 32 || charOfSourceString + 32 == charOfTargetString) {
temp = 0;
} else temp = 1;
matrix[indexOfSourceString][indexOfTargetString] = Math.min(Math.min(matrix[indexOfSourceString - 1][indexOfTargetString] + 1, matrix[indexOfSourceString][indexOfTargetString - 1] + 1), matrix[indexOfSourceString - 1][indexOfTargetString - 1] + temp);
}
}
return (1 - (double) matrix[sourceStringLength][targetStringLength] / Math.max(sourceString.length(), targetString.length())) * 100F;
}
全部评论