【笔记】项目工作中总结(三)

目录

HttpClient设置Protocol版本

FileOperate

Java写入String到txt

Java读取txt文本

Java中循环删除list中元素

Java double精度丢失

常用正则表达式

Spring Validation验证List

Java快捷创建List数组

Java7 使用下划线表示数字提高可读性

Java Lambda

自定义排序

Lambda表达式外部变量引用

匿名内部类TypeReference使用

SpringBoot从数据库加载配置到ConfigurableEnvironment

Generate https certificate (better run on Linux)

LDAP

英语口语

Tricks


HttpClient设置Protocol版本

SSLContextBuilder.setProtocol("TLSv1.2")

FileOperate

File 转 byte[]

// 方法一
       String excelFile = "/home/demo/db_table.xlsx";
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
            FileInputStream fis = new FileInputStream(excelFile);) {
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            byte[] data = bos.toByteArray();
            fis.close();
            bos.close();
            return data;
        }

// 方法二
        String excelFile = "/home/demo/db_table.xlsx";
        File file = new File(excelFile);
        if (!file.exists()) {
            log.error("upload file not exist. ");
            return;
        }
        Path path = Paths.get(file.getAbsolutePath());
        byte[] fileByteArray = Files.readAllBytes(path);
或者使用第三方工具:

org.apache.commons.io.FileUtils 

里边很多文件相关操作工具

Java写入String到txt

    public static void writeStringToFile(String filePath) throws IOException {
        String content = "This is a short piece of text. ";
        File txtFile = new File(filePath);
        if (!txtFile.getParentFile().exists()) {
            txtFile.getParentFile().mkdirs();
        }
        try (FileWriter fwriter = new FileWriter(txtFile);) {
            fwriter.write(content);
        }
    }

Java读取txt文本

    public static String readFileContent(File file) throws IOException {
        StringBuilder result = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            String line = null;
            while ((line = br.readLine()) != null) {// 使用readLine方法,一次读一行
                result.append(line).append("\n");
            }
        }
        return result.toString();
    }

Java中循环删除list中元素

Iterator<String> it = list.iterator();
while(it.hasNext()){
    String x = it.next();
    if(x.equals("del")){
        it.remove();
    }
}

ref: JAVA中循环删除list中元素的方法总结 - PC君 - 博客园

Java double精度丢失

非常经典问题,其实不仅仅是 Java 语言,还是 JS 等语言的通病,即:
当我们在计算 0.1+0.2 时,惊讶的发现,结果竟然不是 0.3,而是:0.30000000000000004。

public class TestUtil {
    public static void main(String[] args) {
        System.out.println("0.1+0.2 = " + (0.1 + 0.2));
        Double money = 0.60;
    }
}

输出:0.1+0.2 = 0.30000000000000004

原因:

问题很简单,是由于我们输入的十进制的 double 类型的数据在进行计算的时候,计算机会先将其转换为二进制数据,然后再进行相关的运算。

然而在十进制转二进制的过程中,有些十进制数是无法使用一个有限的二进制数来表达的,换言之就是转换的时候出现了精度的丢失问题。

解决:

Java 语言中最经典的便是使用 BigDecimal 来解决。

    // 方式一  不推荐,存在精度丢失  
    public BigDecimal(double val) {
        this(val,MathContext.UNLIMITED);
    }

    // 方式二  推荐
    public BigDecimal(String val) {
        this(val.toCharArray(), 0, val.length());
    }

    // 方式三 推荐(其实底层就是方式二)
    public static BigDecimal valueOf(double val) {
        // Reminder: a zero double returns '0.0', so we cannot fastpath
        // to use the constant ZERO.  This might be important enough to
        // justify a factory approach, a cache, or a few private
        // constants, later.
        return new BigDecimal(Double.toString(val));
    }

十进制小数转换成二进制小数采用"乘2取整,顺序排列"法。具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,此时0或1为二进制的最后一位。或者达到所要求的精度为止。

常用正则表达式

正则表达式:
+:   匹配一个或多个字符(至少一个)
*:    匹配零个或多个字符
?:    匹配零个或一个字符
{4}:  匹配固定次数4次
x|y:  匹配 x 或 y。例如,'z|food' 匹配"z"或"food"。'(z|f)ood' 匹配"zood"或"food"。
[xyz] 字符集。匹配包含的任一字符。例如,"[abc]"匹配"plain"中的"a"

Spring Validation验证List<XXXBO>

########
解决 Spring 中 针对List内的每个对象的 @Valid 校验不生效问题,直接在List增加注解@Valid即可

    @Valid
    @NotEmpty(message = "XXXBOList can not be null")
    private List<XXXBO> XXXBOList;

#########

String Join

String result = list.stream().collect(Collectors.joining(""));

####### 日期转换

        // String - LocalDateTime互转
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime time = LocalDateTime.now();
        String localTime = df.format(time);
        LocalDateTime ldt = LocalDateTime.parse("2018-01-12 17:07:05",df);
        System.out.println("LocalDateTime转成String类型的时间:"+localTime);
        System.out.println("String类型的时间转成LocalDateTime:"+ldt);


        // 计算时间差
        LocalDateTime now = LocalDateTime.now();
        Duration duration = Duration.between(updateTime, now);
        long minutes = duration.toMinutes();// 相差的分钟数

####### mysql日期函数

DATE_FORMAT    minute    second    date    time

select DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') from drs_data_set 
select * from ums_student where minute(create_time) = 03

Or

select * from ums_student where create_time > TIMESTAMP('022-06-23')

###### spring jdbc 快捷执行sql

// sql
ScriptUtils.executeSqlScript(dataSource.getConnection(), new ByteArrayResource(scriptToExecute.getBytes()));

Java快捷创建List数组

  • 通过Arrays.asList("a", "b");

但是这种方法构造出的List是固定长度的,如果调用add方法增加新的元素,会报异常:java.lang.UnsupportedOperationException,
其实也可以理解,这个List是由Array转换而来,而Array是不能动态增加长度的,适合于构造静态不变List。


构造动态List

  • 通过Java8引入的Stream提供的方法:

List list = Stream.of("a", "b").collect(Collectors.toList());

  • 通过guava提供的方法

List list3 = Lists.newArrayList("f", "g");

Java7 使用下划线表示数字提高可读性

例:

long number = 10_000_000_000_000_000L;

很实用的功能;通过下划线分隔,可以更直观的分辨数值中到底有多少位。

Java Lambda

自定义排序

        // sort by version: 1.2.9 < 1.2.10
        Collections.sort(dockerVersions, (o1, o2) -> {
            String v1 = o1.getVersion();
            String v2 = o2.getVersion();

            String[] v1Arrs = v1.split("\\.");
            String[] v2Arrs = v2.split("\\.");

            int len = v1Arrs.length > v2Arrs.length ? v1Arrs.length : v2Arrs.length;

            for (int i = 0; i < len; i++) {
                int v1Num = 0;
                int v2Num = 0;

                if (i < v1Arrs.length) {
                    v1Num = Integer.parseInt(v1Arrs[i]);
                }

                if (i < v2Arrs.length) {
                    v2Num = Integer.parseInt(v2Arrs[i]);
                }

                if ("desc".equals(order)) {
                    if (v2Num > v1Num) {
                        return 1;
                    } else if (v2Num < v1Num) {
                        return -1;
                    }
                } else {
                    if (v2Num < v1Num) {
                        return 1;
                    } else if (v2Num > v1Num) {
                        return -1;
                    }
                }
            }
            return 0;
        });


        // 对比原来没有lambda表达式的方式,需要用new Comparator使用匿名内部类的方式
        Collections.sort(list,new Comparator<Person>() {
            @Override
            public int compare(Person p1,Person p2) {
            	int sort = p1.getAge() - p2.getAge();
                if(sort>0) {
                	maxAge[0] = p1.getAge();
                	return 1;
                }else if(sort<0) {
                	maxAge[0] = p2.getAge();
                	return -1;
                }
                maxAge[0] = p1.getAge();
                return 0;
            }
        });

Lambda表达式外部变量引用

    Lambda表达式,其可以访问给它传递的变量,访问自己内部定义的变量,同时也能访问它外部的变量。但lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。

  

编译时会报错。因为变量existsInBigFolder被lambda表达式引用,所以编译器会隐式的把其当成final来处理。

以前Java的匿名内部类在访问外部变量的时候,外部变量必须用final修饰。现在java8对这个限制做了优化,可以不用显示使用final修饰,但是编译器隐式当成final来处理。

可以直接使用existsInBigFolder,即能访问它外部的变量:

        boolean existsInBigFolder = false;
        bigFolderCollection.stream().map(x -> {
            return existsInBigFolder = existingFilePath.contains(x);
        });
        
        bigFolderCollection.stream().map(x -> {
            return existingFilePath.contains(x);
        });

匿名内部类TypeReference使用

    一般在使用泛型的时候,对应像Map这样的接口类型使用泛型,如果想指定Map<String, Persong>,这样的固定Map类型的时候,直接使用Map<String, Persong>是肯定不行的,那么应该怎么办?

    有些第三方工具提供了TypeReference这样的类型引用抽象类,底层通过Java反射的方式获取属性类型;

源码:

package com.fasterxml.jackson.core.type;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * This generic abstract class is used for obtaining full generics type information
 * by sub-classing; it must be converted to {@link ResolvedType} implementation
 * (implemented by <code>JavaType</code> from "databind" bundle) to be used.
 * Class is based on ideas from
 * <a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html"
 * >http://gafter.blogspot.com/2006/12/super-type-tokens.html</a>,
 * Additional idea (from a suggestion made in comments of the article)
 * is to require bogus implementation of <code>Comparable</code>
 * (any such generic interface would do, as long as it forces a method
 * with generic type to be implemented).
 * to ensure that a Type argument is indeed given.
 *<p>
 * Usage is by sub-classing: here is one way to instantiate reference
 * to generic type <code>List&lt;Integer&gt;</code>:
 *<pre>
 *  TypeReference ref = new TypeReference&lt;List&lt;Integer&gt;&gt;() { };
 *</pre>
 * which can be passed to methods that accept TypeReference, or resolved
 * using <code>TypeFactory</code> to obtain {@link ResolvedType}.
 */
public abstract class TypeReference<T> implements Comparable<TypeReference<T>>
{
    protected final Type _type;
    
    protected TypeReference()
    {
        Type superClass = getClass().getGenericSuperclass();
        if (superClass instanceof Class<?>) { // sanity check, should never happen
            throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
        }
        /* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect
         *   it is possible to make it fail?
         *   But let's deal with specific
         *   case when we know an actual use case, and thereby suitable
         *   workarounds for valid case(s) and/or error to throw
         *   on invalid one(s).
         */
        _type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    }

    public Type getType() { return _type; }
    
    /**
     * The only reason we define this method (and require implementation
     * of <code>Comparable</code>) is to prevent constructing a
     * reference without type information.
     */
    @Override
    public int compareTo(TypeReference<T> o) { return 0; }
    // just need an implementation, not a good one... hence ^^^
}

使用样例:

            ObjectMapper mapper = new ObjectMapper();
            try {
                Map<String, Object> responseMap =
                    mapper.readValue(responseEntity.getBody(), new TypeReference<Map<String, Object>>() {});
                String access_token = (String)responseMap.get("access_token");
                credential.setAccessToken(access_token);
            } catch (JsonProcessingException e) {
                log.error("Json parse error:", e);
            }

SpringBoot从数据库加载配置到ConfigurableEnvironment

常用方式是将配置从application.properties,但有时也需从数据库加载配置

public class DatabasePropertiesProcessor implements BeanPostProcessor, InitializingBean, EnvironmentAware {

    private ConfigurableEnvironment environment;

    @Autowired
    private SystemConfigRepository systemConfigRepository;

    @Override
    public void afterPropertiesSet() throws Exception {
        if (environment != null) {
            List<SystemConfig> systemConfigList = systemConfigRepository.findByAsyStatusAndAsyEnv("ACTIVE", "DEV");
            Map<String, Object> systemConfigMap = systemConfigList.stream().collect(Collectors.toMap(SystemConfig::getKey, SystemConfig::getVal));
            environment.getPropertySources().addFirst(new MapPropertySource("propertiesFromDatabase", systemConfigMap));
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        if (environment instanceof ConfigurableEnvironment) {
            this.environment = (ConfigurableEnvironment) environment;
        }
    }
}
    /**
     * @param target 目标源数据
     * @return 将目标源中不为空的字段取出
     */
    private static String[] getNoNullProperties(Object target) {
        BeanWrapper srcBean = new BeanWrapperImpl(target);
        PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
        Set<String> noEmptyName = new HashSet<>();
        for (PropertyDescriptor p : pds) {
            Object value = srcBean.getPropertyValue(p.getName());
            if (value != null) noEmptyName.add(p.getName());
        }
        String[] result = new String[noEmptyName.size()];
        return noEmptyName.toArray(result);
    }

Generate https certificate (better run on Linux)

######### Generate https certificate (better run on Linux)
https://www.cnblogs.com/php-no-2/p/11276323.html
1. Generate server.key >>> server.key
$ openssl genrsa -des3 -out server.key 2048

# remove password
$ openssl rsa -in server.key -out server.key

2. Generate server.csr >>> server.csr
$ openssl req -new -key server.key -out server.csr

3. Create CA cert >>> ca.crt
$ openssl req -new -x509 -key server.key -out ca.crt -days 3650

4. Create Server cert >>> server.crt
$ openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey server.key -CAcreateserial -out server.crt
ca.crt   ca.srl    server.crt   server.csr   server.key

LDAP

################## LDAP
LDAP: Lightweight Directory Access Protocol
LDIF: LDAP Data Interchange Format File 
LDAP简称
o - organization; 组织名,如“Example,Inc.”
ou - organization unit; 组织单位,类似于Linux文件系统中的子目录,它是一个容器对象,组织单位可以包含其他各种对象(包括其他组织单元),如“market”
c - country; 国家,如“CN”或“US”等.
dc - domainComponent; 域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com
sn - sur-name; 姓,如“Johansson”
cn - common name; 公共名称,如“Thomas Johansson”
dn - Distinguished Name; 惟一辨别名,类似于Linux文件系统中的绝对路径,每个对象都有一个惟一的名称, 如“uid= tom,ou=market,dc=example,dc=com”,在一个目录树中DN总是惟一的
rdn - Relative dn; 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson”
uid  - User Id; 用户ID,如“tom”

常用objectClass类型:
alias  applicationEntity  dSA  applicationProcess  bootableDevice  certificationAuthority  certificationAuthority-V2  country  
cRLDistributionPoint  dcObject  device  dmd  domain  domainNameForm  extensibleObject  groupOfNames  groupOfUniqueNames  
ieee802Device  ipHost  ipNetwork  ipProtocol  ipService  locality  dcLocalityNameForm  nisMap  nisNetgroup  nisObject  
oncRpc  organization  dcOrganizationNameForm  organizationalRole  organizationalUnit  dcOrganizationalUnitNameForm  person  
organizationalPerson  inetOrgPerson  uidOrganizationalPersonNameForm  residentialPerson  posixAccount  posixGroup  shadowAccount  
strongAuthenticationUser  uidObject  userSecurityInformation 

###### 状态机
https://blog.didispace.com/spring-statemachine/
使用Spring StateMachine框架实现状态机

英语口语

  • prerequisite    underscore    hyphen    dash
  • strong possibility    stand a good chance
  • alll runs good.
  • Life was like a box of chocolates,you never know what you’re gonna get.
  • Go on, please.

英语时间表达:

一种直接读:eg. 1:20 one twenty(小时+分钟)
另一种要用介词past(30分钟内包括30分钟),to (超过30分钟)

  • 1:20 twenty past one (分钟+past+小时)
  • 1:40 twenty to two (差20分钟到两点) (60分钟减40)分钟+to +小时(1+1)
  • 如果分钟是15,45要用a quarter,(一刻钟) 如:1:15 a quarer past one    1:45 a quarer to two
  • 如果分钟是30要用half(一半,二分之一) 如:1:30 half past one

CommandLineRunner

Tricks

  • 建立目录可以加前缀 "1_0PathName",使目录结构清晰

SKILL Accquired
ThreadLocalRandom.current()
CommandLine
CopyOnWriteArrayList
@Import只能用在类上 ,@Import通过快速导入的方式实现把实例加入spring的IOC容器中
spring-integration-sftp
canel
RabbitMq

SFTP:
import org.springframework.integration.annotation.MessagingGateway;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值