记录一些琐碎知识,方便查看

定时任务的使用过程,以及使用分布式定时任务的意义(方便细粒度管理和调度)

https://www.jianshu.com/p/672dc60f1293

@Value注解使用下面方式注入如果配置文件中存在以配置文件中为主,配置文件中不存在则赋值默认值xxx(@Value注解不能为静态的属性赋值)

@Value("${server.web.domain:xxx}") private String domain;

1.对于mysql中的group by分组语句,涉及到合并时,默认会以数据库中id最小的数据为主(不求和就会丢弃id大的数据,如果需要根据key进行分组,value是key相同的实体的集合,可以使用stream流中的分组方法)
2.List集合中使用remove方法移除元素时,需要注意索引左移问题导致的异常(https://zhuanlan.zhihu.com/p/413921093)
3.List集合的时间复杂度要高于Set集合,使用集合中的contains方法时,优先使用Set集合(效率很高)
4.清空数据库的自增id命令 truncate 表名(会清空数据)
5.mapper起别名映射不上可以使用resultmap手动映射(待定)
6.mapper中当传入的值为integer类型的0时,会默认识别为空串(mybatis的锅)
7.使用@NotBlank(message = "不能为空!"),抛出这个异常:

             HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.String'. Check configuration for

检查一下当前引入的包是不是引错了,引用javax.validation.constraints.NotBlank这个包肯定会报错,要换成org.hibernate.validator.constraints.NotBlank

8.Arrays.asList方法中的注意事项:

这个方法只适用于一些简单的场合,比如快速声明一个集合,判断某个值是否存在等等。但是如果声明后调用集合的add,clear,remove方法等,就会报java.lang.UnsupportedOperationException的异常

9.CollectionUtils工具类的使用(求集合的交集,补集,并集)

CollectionUtils工具类的常用方法_brandomCC的博客-CSDN博客_collectionutils

10.mysql使用嵌套子查询去删除数据时会报错,原因: mysql不允许对同一张表查询之后再来更新删除,而对不同的表可以执行先子查询再进行更新删除

解决方案如下mysql 的删除修改嵌套查询问题 - 代码先锋网

11.rabbmitmq发送消息失败的补偿机制详解:

rabbitmq消息ACK确认机制及发送失败处理 - 甜菜波波 - 博客园

12.spring中Aop切面使用的例子包括自定义注解的使用:

@Aspect注解_小白不很白的博客-CSDN博客_@aspect

13.mysql将多行字段数值合并为一行字段数据

mysql将多行字段数值合并为一行字段数据_dongyue520的博客-CSDN博客_mysql 合并多行字段

14.@Value注解详解

@Value的诸多用法_weixin_45614626的博客-CSDN博客_@value

15.@RequestParm注解和@RequestBody注解的区别

@RequestBody和@RequestParam区别全面详细_一斤白菜的博客-CSDN博客_@requestparam

16.生成的单号的数字左边补充0

java补充0 java数字左侧补零补0 NumberFormat实现数字左侧补0-蒲公英云

17.如果公司可以使用分页插件可以用pagehelper,但是会出现分页失效的情况需要手写分页,下面为手写分页代码:

public static <T> List<T> pageList(List<T> list, int pageNum, int pageSize) {
    // 计算总页数
    int page = list.size() % pageSize == 0 ? list.size() / pageSize : list.size() / pageSize + 1;
    pageNum = pageNum <= 0 ? 1 : pageNum;
    pageNum = Math.min(pageNum, page);
    int begin = 0;
    int end = 0;
    if (pageNum != page) {
        begin = (pageNum - 1) * pageSize;
        end = begin + pageSize;
    } else {
        begin = (pageNum - 1) * pageSize;
        end = list.size();
    }
    if (CollectionUtils.isNotEmpty(list)) {
        return list.subList(begin, end);
    } else {
        return null;
    }
}

18.常用的代码整理正则如下:

单行注释替换为多行注释:
ctrl+r(替换)
//+(.*$)
/**\n     *$1\n     */
ctrl+alt+l

行尾注释替换:
查找:
(^[^\r\n]+[\S]+[^\r\n]+)(//.+$),
替换为:
\t$2\r\n$1,
然后Ctrl+alt+l格式化

19.@NotNull,@NotBlank,@NotEmpty注解的区别:

@NotNull用于校验基本类型,可以校验为null和""两种情况

@NotBlank用于校验字符串,可以校验为null和""和" "三种情况

@NotEmpty用于校验集合,可以校验为null和size>0两种情况

20.ThreadLocal可以实现多线程间的数据隔离,填充的数据只属于当前线程,当前线程的数据对于其他线程来说是隔离的(spring中的事务的隔离就是基于ThreadLocal+Aop来实现的;获取和数据库的交互的Connection对象也是基于ThreadLocal实现),它的底层维护着一个ThreadLocalMap(每个线程都有自己的map),map的底层基于数组实现,一个map可以存储多个ThreadLocal对应的数据,map的key是当前的ThreadLocal对象,value是对应存储的数据,当我们调用ThreadLocal的get()方法时,会先根据当前Thread去获取对应的map,然后根据ThreadLocal去获取map中对应的value数据。

参考链接:Java中ThreadLocal的实际用途是啥? - 知乎

21.动态sql中批量插入中foreach中数据量大导致的问题

被 foreach 坑惨了,再也不敢乱用了....(解决方案:①自己手写插入语句,分页分批次的插入②依旧采用动态sql插入,不要使用foreach默认的执行器,而是去使用BatchInsert这个批处理器)

22.BeanUtils中浅拷贝导致的问题

https://blog.csdn.net/qq_50652600/article/details/123400746

(最快解决方案,不使用BeanUtils工具类,而是直接使用set方法去赋值)

23.Thread中run方法和start方法区别

  • start() 可以启动一个新线程,run()不能
  • start()不能被重复调用,run()可以
  • start()中的run代码可以不执行完就继续执行下面的代码,即进行了线程切换。直接调用run方法必须等待其代码全部执行完才能继续执行下面的代码。
  • start() 实现了多线程,run()没有实现多线程

24.实现了Serializable接口还要指定serialVersionUID值的原因

为什么实现了Serializable接口还要指定serialVersionUID值呢? - 码农教程

25.maven下的依赖,提供各种加密和解密方法的jar包,详情如下:

https://www.cnblogs.com/zrbfree/p/5659848.html

26.mysql中开启慢查询日志的命令

如何开启mysql慢查询日志?_mysql开启慢查询日志_普通网友的博客-CSDN博客

27.java中拦截器(Filter)和过滤器(interceptor)的区别和使用

Java里过滤器(filter)与拦截器(Interceptor)的区别和使用_java过滤器和拦截器_落丶寞的博客-CSDN博客

28.集合工具类使用场景描述

package test.demo;

import cn.hutool.core.bean.BeanUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ConvertUtils {

    public interface Producer<T, V> {

        /**
         * 生成数据
         *
         * @param filedIds
         * @return
         */
        List<V> generic(List<T> filedIds);

    }

    public static <T, K, V> Map<K, V> keyListToMap(List<?> sourceList, String sourceKeyFiled, String returnKeyFiled, Producer<T, V> producer) {

        List<T> idFields = new ArrayList<>();
        for (Object object : sourceList) {
            idFields.add(BeanUtil.getProperty(object, sourceKeyFiled));
        }
        List<V> genericList = producer.generic(idFields);
        Map<K, V> returnMap = new HashMap<>(genericList.size());
        for (V object : genericList) {
            returnMap.put(BeanUtil.getProperty(object, returnKeyFiled), object);
        }
        return returnMap;


    }

}
//roleManagerList集合中是返回的数据集合(实体中包含areaLayer字段),
        // 通过List<String> areaLayerList = roleManagerList.stream().map(RoleManager::getAreaLayer).collect(Collectors.toList());
        //得到areaLayerList,List<KQBean> kqBeanList = kqService.findComkqByLayers(areaLayers) 需求是根据areaLayers查询得到kqBeanList集合,将areaLayer和KQBean中areaLayer
        //相同的KQBean中的数据取一部分值,两层for循环效率低下,使用工具类先放在map中然后获取


 List<RoleManager> roleManagerList = roleManagerMapper.getRoleInfoByUserName(userName);
        if (CollectionUtils.isNotEmpty(roleManagerList)) {
            List<String> areaLayerList = roleManagerList.stream().map(RoleManager::getAreaLayer).collect(Collectors.toList());

            List<RoleManager> adminList = roleManagerMapper.getAdminByAreaLayers(areaLayerList);

            Map<String, String> adminMap = new HashMap<>();

            adminList.forEach(roleManager -> adminMap.put(roleManager.getAreaLayer(), roleManager.getUserName()));

            Map<String, KQBean> kqBeanMap = ConvertUtils.keyListToMap(roleManagerList,
                    "areaLayer",
                    "kqlayer", (ConvertUtils.Producer<String, KQBean>) areaLayers -> {
                        List<KQBean> kqBeanList = kqService.findComkqByLayers(areaLayers);
                        return kqBeanList;
                    });
            List<RoleManagerDTO> resultList = new ArrayList<>();
            roleManagerList.forEach(roleManager -> {
                RoleManagerDTO role = new RoleManagerDTO();
                BeanUtils.copyProperties(roleManager, role);
                KQBean kqBean = kqBeanMap.get(roleManager.getAreaLayer());
                role.setLongitude(kqBean.getLongitude());
                role.setLatitude(kqBean.getLatitude());
                role.setKqName(kqBean.getKqname());
                role.setAreaPath(kqBean.getAreapath());
                role.setSuperAdmin(adminMap.get(roleManager.getAreaLayer()));
                resultList.add(role);
            });
            return resultList;
        }
        return new ArrayList<>();

29.根据两个经纬度计算相距多少公里的工具类

依赖:

<dependency>
    <groupId>org.gavaghan</groupId>
    <artifactId>geodesy</artifactId>
    <version>1.1.3</version>
</dependency>
package cn.chci.hmcs.river.monitor.utils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * double的计算不精确,会有类似0.0000000000000002的误差,正确的方法是使用BigDecimal或者用整型
 * 整型地方法适合于货币精度已知的情况,比如12.11+1.10转成1211+110计算,最后再/100即可 以下是摘抄的BigDecimal方法:
 */

/**
 * 说明:Double工具类
 * from:www.1b23.com
 */
public class DoubleUtil implements Serializable {
    private static final long serialVersionUID = -3345205828566485102L;
    // 默认除法运算精度
    private static final Integer DEF_DIV_SCALE = 2;

    /**
     * 提供精确的加法运算。
     *
     * @param value1 被加数
     * @param value2 加数
     * @return 两个参数的和
     */
    public static Double add(Double value1, Double value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1));
        BigDecimal b2 = new BigDecimal(Double.toString(value2));
        return b1.add(b2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     *
     * @param value1 被减数
     * @param value2 减数
     * @return 两个参数的差
     */
    public static double sub(Double value1, Double value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1));
        BigDecimal b2 = new BigDecimal(Double.toString(value2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     *
     * @param value1 被乘数
     * @param value2 乘数
     * @return 两个参数的积
     */
    public static Double mul(Double value1, Double value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1));
        BigDecimal b2 = new BigDecimal(Double.toString(value2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时, 精确到小数点以后10位,以后的数字四舍五入。
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @return 两个参数的商
     */
    public static Double divide(Double dividend, Double divisor) {
        return divide(dividend, divisor, DEF_DIV_SCALE);
    }

    /**
     * 提供(相对)精确的除法运算。 当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入。
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @param scale    表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static Double divide(Double dividend, Double divisor, Integer scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(dividend);
        BigDecimal b2 = new BigDecimal(divisor);
        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 提供指定数值的(精确)小数位四舍五入处理。
     *
     * @param value 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double value, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(value));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
    }

    public static Boolean ifInteger(double value){

        return Math.floor(value)==Math.ceil(value);

    }
}
package cn.chci.hmcs.river.monitor.utils;

import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;

import java.text.DecimalFormat;

/**
 * @author Admin
 */
public class DistanceUtils {

    public static final String KMFormt = "公里";

    public static final String MFormt = "米";

    public static final Double KM = 1000d;


    public static String meterFormat(Double meter) {

        if (meter > KM) {
            Double kmFormatVal = DoubleUtil.divide(meter, KM, 1);

            if (DoubleUtil.ifInteger(kmFormatVal)) {
                DecimalFormat decimalFormat = new DecimalFormat("#");
                String formattedValue = decimalFormat.format(kmFormatVal);
                return formattedValue + KMFormt;
            }
            return kmFormatVal + KMFormt;
        }

        DecimalFormat decimalFormat = new DecimalFormat("#");
        String formattedValue = decimalFormat.format(meter);
        return formattedValue + MFormt;
    }


    public static Double distanceMeterUtil(double lat1, double lng1, double lat2, double lng2) {

        GlobalCoordinates source = new GlobalCoordinates(lat1, lng1);
        GlobalCoordinates target = new GlobalCoordinates(lat2, lng2);


        return getDistanceMeter(source, target, Ellipsoid.Sphere);
    }

    public static String distanceMeterFormat(double lat1, double lng1, double lat2, double lng2) {

        Double distanceMeter = distanceMeterUtil(lat1, lng1, lat2, lng2);
        return meterFormat(distanceMeter);
    }

    public static double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid) {

        //创建GeodeticCalculator,调用计算方法,传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);
        return geoCurve.getEllipsoidalDistance();
    }


    public static void main(String[] args) {
        String distanceMeter = distanceMeterFormat(39.909049, 116.398029, 39.486585, 115.975083);
        System.out.println(distanceMeter);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值