ISheepp / 2021

After graduating in Supcon
0 stars 1 forks source link

工作记录 #2

Open ISheepp opened 3 years ago

ISheepp commented 3 years ago

此issue记录在Supconit工作时遇到的问题以及解决方案,今天是正式入职的第二周第二天

ISheepp commented 3 years ago

List转Map(实习遇到的问题)

List<Map<String, Object>>Map<String, List<Map<String, Object>>>

场景

从es中获取算法容器的监控信息

返回体要求

"data": [
    {
      "name": "svc-aompsuanfarongqiyanshi-89",
      "instanceUptime": "1d 14h 54m 20s",
      "osCpu": 27,
      "instanceMem": "818.6MB/1.9GB",
      "algorithmInfos": null
    },
    {
      "name": "svc-aompquanxilukourongqi-91",
      "instanceUptime": "1d 14h 59m 18s",
      "osCpu": 64.86,
      "instanceMem": "829.6MB/1.9GB",
      "algorithmInfos": null
    },
    {
      "name": "svc-aompsuanfarongqiyanshi-86",
      "instanceUptime": "0d 7h 56m 34s",
      "osCpu": 15.98,
      "instanceMem": "377.5MB/1.9GB",
      "algorithmInfos": null
    }
  ]

List<Map>得到的是这种形式

image

最后需要转变为以serverNamekey的一个Map

image

解决办法

List<Map<String, Object>> container = containerManagementService.listAlgorithmContainer(current, size);
// 对获取到的集合根据服务名字分组处理
Map<String, List<Map<String, Object>>> map = new HashMap<>();
for (Map<String, Object> stringObjectMap : container) {
    List<Map<String, Object>> list = map.get(stringObjectMap.get("serverName"));
    if (list == null) {
        list = new ArrayList<>();
        map.put(stringObjectMap.get("serverName").toString(), list);
    }
    list.add(stringObjectMap);
}

目前找不到用stream流处理的办法

ISheepp commented 3 years ago

SpringBoot自带的Tomcat与外挂的有什么区别

ISheepp commented 3 years ago

SpringBoot FatJar启动原理

ISheepp commented 3 years ago

Java注解

如果参数名称是value,且只有一个参数,那么可以省略参数名称。

ISheepp commented 3 years ago

Spring 如何解决循环依赖

Spring只能解决单例bean的循环依赖,遇到prototype则抛异常BeanCurrentlyInCreationException 图解Spring解决循环依赖

ISheepp commented 3 years ago

使用Feign情况下,参数为空的情况如何解决(MultipartFile 参数的情况)

feign Body parameter 2 was null

feign issue

ISheepp commented 3 years ago

FeignClient自动生成代理类

configuration

@FeignClient注解

  1. name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现

    ribbon默认从注册中心读取需要进行feign调用的服务器列表,有时候我们想使用ribbonfeign进行基于声明式接口的api调用,但是调用的目标又不在注册中心里,我们可以通过手动配置的方式来实现。

    # 服务名称为 myservice
    # 对于这个服务,需要先禁用从 eureka 中读取服务列表
    myservice.ribbon.eureka.enabled=false
    # 为这个服务配置服务清单,可以是一个或N个
    myservice.ribbon.listOfServers=http://localhost:5000, http://localhost:5001
  2. url: url一般用于调试,可以手动指定@FeignClient调用的地址
  3. decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
  4. configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
  5. fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
  6. allbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
  7. path: 定义当前FeignClient的统一前缀

    @EnableFeignClients注解

主要用来启动FeignClient 以支持Feign,需要配置basePackages扫描包路径来扫描指定位置的@FeignClient注解声明的FeignClient客户端

Feign动态切换服务

Feign动态切换服务

如何根据环境动态指定feign调用服务名

聊聊如何根据环境动态指定feign调用服务名

ISheepp commented 3 years ago

Jarslink

ISheepp commented 3 years ago

@Valid使用

@RequestBody中加入@Valid可以对入参对象做校验

  1. @NotBlank一般作用于String,判断时将会去除空格 (trim操作),也会判断是否为null,即必须有实际字符
  2. @NotEmpty 一般作用于集合类型,将判断集合size是否为0,不能为null,而且长度必须大于0
  3. @NotNull 一般作用于基本类型,不能为null,但可以为empty,比如(" ")("")
ISheepp commented 3 years ago

Jdk动态代理和Cglib动态代理

//接口
interface Service {
    void doNeedTx();

    void doNotneedTx();
}

//目标类,实现接口
class ServiceImpl implements Service {

    @Transactional
    @Override
    public void doNeedTx() {
        System.out.println("execute doNeedTx in ServiceImpl");
    }

    //no annotation here
    @Override
    public void doNotneedTx() {
        this.doNeedTx();
    }
}

//代理类,也要实现相同的接口
class ProxyByJdkDynamic implements Service {

    //包含目标对象
    private Service target;

    public ProxyByJdkDynamic(Service target) {
        this.target = target;
    }

    //目标类中此方法带注解,进行特殊处理
    @Override
    public void doNeedTx() {
        //开启事务
        System.out.println("-> create Tx here in Proxy");
        //调用目标对象的方法,该方法已在事务中了
        target.doNeedTx();
        //提交事务
        System.out.println("<- commit Tx here in Proxy");
    }

    //目标类中此方法没有注解,只做简单的调用
    @Override
    public void doNotneedTx() {
        //直接调用目标对象方法
        target.doNotneedTx();
    }
}
ISheepp commented 3 years ago

ES字符串的text和keyword

text

  1. 支持分词,分词后分别建立索引(比如:对于‘林子洋’,ik分词器的smart分词会自动将其分成林、子、洋三个字符进行建立索引,所以单字符搜索可以搜索到,而比如‘子洋’则搜索不到)
  2. 支持模糊查询,支持准确查询
  3. 不支持聚合

keyword

  1. 不分词,直接建立索引
  2. 支持模糊查询,支持准确查询
  3. 支持聚合

字符串类型尽量使用keyword

ISheepp commented 3 years ago

API入参问题

基本数据类型,不使用RESTful

方法签名

@GetMapping("/test")
    public HttpResult<Object> test(long start, long end)

此时如果传参param只填key ,不填value image

后端会报错 image

基本数据类型,使用RESTful

方法签名

@GetMapping("/test/{start}/{end}")
    public HttpResult<Object> test(@PathVariable("start") long start, @PathVariable("end") long end)

此时不填写任何值,报404 image

包装类型,不使用RESTful

方法签名

@GetMapping("/test")
    public HttpResult<Object> test(Long start, Long end)

此时如果传参param只填key ,不填value

没有任何问题

ISheepp commented 3 years ago

Java比较器Comparator的使用

@Test
    public void testCompare(){
        EntityAge one = new EntityAge("lzy", 22);
        EntityAge two = new EntityAge("poi", 24);
        EntityAge three = new EntityAge("hhh", 13);
        List<EntityAge> list = Lists.newArrayList(one, two, three);
        List<EntityAge> collect = list.stream().sorted(new Comparator<EntityAge>() {
            @Override
            public int compare(EntityAge o1, EntityAge o2) {
                return o1.getAge() - o2.getAge();
            }
        }).collect(Collectors.toList());
        collect.forEach(System.out::println);
    }

image 左参数-右参数为升序

如果返回值为负数意味着o1比o2小,否则返回为零意味着o1等于o2,返回为正数意味着o1大于o2

如果返回值为负数 倒序,否则返回为零意味着o1等于o2,返回为正数意味着升序

ISheepp commented 3 years ago

几个日常开发中的问题

  1. 不要用Arrays.asList()来由数组转List 使用ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr)); 直接使用Arrays.asList()创建的List是固定的,不能add
  2. 检查数组中是否包含某个值
    Set<String> set = new HashSet<String>(Arrays.asList(arr));
    return set.contains(targetValue);

    创建Set消耗资源,直接使用return Arrays.asList(arr).contains(targetValue);

  3. 不能再循环中删除元素

    // 使用迭代器删除
    ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
    Iterator<String> iter = list.iterator();
    while (iter.hasNext()) {
    String s = iter.next();
    
    if (s.equals("a")) {
        iter.remove();
    }
    }
ISheepp commented 2 years ago

并行流parallelStream()

forkjoin

forkjoin

工作窃取算法

ISheepp commented 2 years ago

Redis 做队列

lpush和rpush

lpush 相当于头插法 rpush 相当于尾插法

ISheepp commented 2 years ago

对象中的某个字段去重

public class StreamUtils {

    /**
     * 对象中的某个字段去重
     *
     * @param keyExtractor Function
     * @return Predicate
     */
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        System.out.println("2222");
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    public static void main(String[] args) {
        List<Student> list = Lists.newArrayList(
                new Student("1", "11"),
                new Student("2", "1111111"),
                new Student("3", "11")
        );
        list.stream().filter(distinctByKey(Student::getPrice)).collect(Collectors.toList()).forEach(System.out::println);
    }
}
ISheepp commented 2 years ago

@Scheduled注解

  1. cron -- @Scheduled(cron="0/5 * * * *?")当时间达到设置的时间会触发事件。上面那个例子会每5秒执行一次。

  2. fixedRate -- @Scheduled(fixedRate=2000) 每两秒执行一次时间。

  3. fixedDelay -- @Scheduled(fixedDelay=2000) 每次任务执行完之后的2s后继续执行

  4. initialDelay --@Scheduled(initialDelay = 5000)初次执行任务之前需要等待的时间

ISheepp commented 2 years ago

Kafka auto.offset.reset

earliest 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费 latest 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 none topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常

ISheepp commented 2 years ago

Spring bean 注入顺序问题

问题来源

在启动SpringBoot项目的时候,有一个bean中写了一个@PostConstruct方法,其中调用了另一个bean的一个方法,无法获 取到被调用方法中的@Value修饰的一个静态常量

涉及点

解决办法

执行顺序 构造 -> @PostConstruct -> bean初始化(bean生命周期)

  1. 在构造的时候就注入要使用的bean
  2. 不使用@PostConstruct,在bean初始化完成之后init,(重写InitializingBean里的afterPropertiesSet方法)
ISheepp commented 2 years ago

Arrays.asList(T t) NPE问题

stack overflow

public class Client {
    public static void main(String[] args) throws Exception {
        Arrays.asList(null);
    }
}

throws a NullPointerException.

public static void main(String[] args) throws Exception {
    Arrays.asList(returnNull());
}

private static Object returnNull(){
    return null;
}

does not