1.业务层导入service

    private final MarketingActivityService marketingActivityService;
    private final MarketingActivityAuditLogService marketingActivityAuditLogService;
    private final MarketingService marketingService;


    @Autowired
    public MarketingActivityController(MarketingActivityService marketingActivityService,
                                       MarketingActivityAuditLogService marketingActivityAuditLogService, MarketingService marketingService) {
        this.marketingActivityService = marketingActivityService;
        this.marketingActivityAuditLogService = marketingActivityAuditLogService;
        this.marketingService = marketingService;
    }

2.collect.stream().collect()

作用:list->map

用法:https://blog.csdn.net/huyizeng7300/article/details/116696994

List<DataCustomerTagPOJO> pojos = BeanConversionUtils.beanListConversion(allTagList, DataCustomerTagPOJO.class);

Map<String, DataCustomerTagPOJO> allTagMap = pojos.stream().collect(Collectors.toMap(DataCustomerTagPOJO::getTagCode, b -> b, (k1, k2) -> k1));

3.JSONObject.parseArray

作用: 该方法将Json字符串数据转换成集合对象。

https://www.cnblogs.com/luxianyu-s/p/9592218.html

String devInfoList = [{"devId":"869718026017001","cabinetId":17,"devType":13,"devTypeStr":"XXX","devName":"XALTE_2003A","cabinetNo":1,"cabinetDoorNo":3}]List<BatchDevInDto> batchDevInDtoList = JSONObject.parseArray(devInfoList, BatchDevInDto.class);

4.@RequestBody&@RequestParam(xxx)

RequestBody:获取前端放在请求body里面的参数

5.MalformedInputException: Input length = 1

yml里面不能有中文注释

6.查看Java类型

public static void main(String[] ags){     
    Integer i=1;          
    System.out.println(i.getClass().toString());   //返回class java.lang.Integer
}

7.swagger

@Api:修饰整个类,描述Controller的作用

@ApiOperation:描述一个类的一个方法,或者说一个接口

@ApiParam:单个参数描述



@ApiModel:用对象来接收参数

@ApiProperty:用对象接收参数时,描述对象的一个字段



其它若干


@ApiResponse:HTTP响应其中1个描述

@ApiResponses:HTTP响应整体描述

8.list下的增强for – forEach

package com.example.demo.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * list下的 增强for循环
 */
public class ForTest {
    public static void main(String[] args) {

        List<Integer> list = new ArrayList<>();

        list.add(1);
        list.add(2);
        list.add(3);
        list.add(5);
        list.add(65);

        //普通
        for (int i = 0; i < list.size(); i++) {
            System.out.println("list.get(i) = " + list.get(i));
        }

        //增强一
        for(Integer i : list){
            System.out.println("i = " + i);
        }

        //增强方式二
        list.forEach(item -> System.out.println("item = " + item));


    }
}

9、BeanConversionUtils? BeanList =>list

return BeanConversionUtils.beanListConversion(list, SubdivisionResultVO.class);2
    
  @Override
    public SubdivisionResultVO getSubdivisionById(Long id) {
        log.info("通过id查询人群,id:{}", id);
        SubdivisionDO subdivisionDO = this.getById(id);

        return BeanConversionUtils.beanConversion(subdivisionDO, new SubdivisionResultVO());
    }   

10.JedisUtils.getBean

public UserSessionVo getUserSession() {
   //获取用户缓存
   UserSessionVo userSessionVo = JedisUtils.getBean(CacheKey.CRM_JDM_USER_SESSION_KEY + getSessionId(), UserSessionVo.class);
   return userSessionVo;
}

11.mybatis-plus

1.orderByDesc

queryWrapper.orderByDesc("update_time");

2.ne(boolean condition, R column, Object val)

ne --> 不等于

public Boolean hasExistSubName(String masterId, Long id, String subName, int isCategory) {
    QueryWrapper<SubdivisionDO> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("master_id", masterId).eq("subdivision_name", subName).
            eq("is_category", isCategory).eq("state", SystemConstant.STATE_1);
    /**
     * ne(boolean condition, R column, Object val)
     *
     * null != id :查询条件   -->   null != id 时,添加“id” <>id的条件,否则不添加
     *
     */
    queryWrapper.ne(null != id ,"id", id);
    List<SubdivisionDO> list = this.list(queryWrapper);

    return list.size() > 0;
}

3.page

@Override
public PageDTO<SubdivisionResultVO> queryTable(SearchSubdivisionVO searchSubdivisionVO) {
    log.info("查询人群列表");
    Page<SubdivisionDO> subdivisionDOPage = new Page<>(searchSubdivisionVO.getStart(), searchSubdivisionVO.getLength());
    QueryWrapper<SubdivisionDO> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("state", SystemConstant.STATE_1).eq("master_id", searchSubdivisionVO.getMasterId()).eq("is_category", SystemConstant.STATE_0);
    if (null != searchSubdivisionVO.getCategoryId()) {
        queryWrapper.eq("parent_id", searchSubdivisionVO.getCategoryId());
    }
    if (null != searchSubdivisionVO.getPackageType()) {
        queryWrapper.eq("package_type", searchSubdivisionVO.getPackageType());
    }
    if (null != searchSubdivisionVO.getIsSaveAs()) {
        queryWrapper.eq("is_save_as", searchSubdivisionVO.getIsSaveAs());
    }
    if (StringUtils.isNotBlank(searchSubdivisionVO.getSubName())) {
        queryWrapper.like("subdivision_name", searchSubdivisionVO.getSubName());
    }
    queryWrapper.orderByDesc("update_time");

    Page<SubdivisionDO> page = new Page<>();
    page.setCurrent(searchSubdivisionVO.getStart());
    page.setSize(searchSubdivisionVO.getLength());
    page = this.page(subdivisionDOPage, queryWrapper);
	// ???
    return PageDTO.voPageConversion(page,SubdivisionResultVO.class);
}

12.命名规范

# JDM

## 对象定义要求

对象定义:
前端交互:requestVO/responseVO
数据库持久对象:DO
数据库业务对象:BO
内部传输处理对象:DTO

requestVO包含:xxInsertVO 、xxUpdateVO、xxDeleteVO、xxQueryVO
responseVO包含:xxResultVO
插入:xxInsertVO 
更新:xxUpdateVO
删除:xxDeleteVO
查询:xxQueryVO
响应结果:xxResultVO

一个requestVO如果包含多个复杂对象,复杂对象定义为DTO;

13.抛出异常的新方式

@Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveSubdivision(CreateSubdivisionVO fromSubdivision, String shopId) {
        
        
    }

14.开发规范的几个常用词

PO(Persistant Object) 持久对象
用于表示数据库中的一条记录映射成的 java 对象。PO 仅仅用于表示数据,没有任何数据操作。通常遵守 Java Bean 的规范,拥有 getter/setter 方法。

可以理解是一个PO就是数据库中的一条记录;可以理解某个事务依赖的原始数据;好处是可以将一条记录最为一个对象处理,可以方便转化为其他对象

BO(Business Object) 业务对象
封装对象、复杂对象,里面可能包含多个类
主要作用是把业务逻辑封装为一个对象。这个对象可以包括一个或多个其它的对象。

用于表示一个业务对象。BO 包括了业务逻辑,常常封装了对 DAO、RPC 等的调用,可以进行 PO 与 VO/DTO 之间的转换。BO 通常位于业务层,要区别于直接对外提供服务的服务层:BO 提供了基本业务单元的基本业务操作,在设计上属于被服务层业务流程调用的对象,一个业务流程可能需要调用多个 BO 来完成。

比如一个简历,有教育经历、工作经历、社会关系等等。
我们可以把教育经历对应一个PO,工作经历对应一个PO,社会关系对应一个PO。
建立一个对应简历的BO对象处理简历,每个BO包含这些PO。
这样处理业务逻辑时,我们就可以针对BO去处理。

VO(Value Object) 表现对象
前端界面展示;value object值对象;ViewObject表现层对象;主要对应界面显示的数据对象。对于一个WEB页面,或者SWT、SWING的一个界面,用一个VO对象对应整个界面的值;对于Android而言即是activity或view中的数据元素。

用于表示一个与前端进行交互的 java 对象。有的朋友也许有疑问,这里可不可以使用 PO 传递数据?实际上,这里的 VO 只包含前端需要展示的数据即可,对于前端不需要的数据,比如数据创建和修改的时间等字段,出于减少传输数据量大小和保护数据库结构不外泄的目的,不应该在 VO 中体现出来。通常遵守 Java Bean 的规范,拥有 getter/setter 方法。

DTO(Data Transfer Object) 数据传输对象
前端调用时传输;也可理解成“上层”调用时传输;
比如我们一张表有100个字段,那么对应的PO就有100个属性。但是我们界面上只要显示10个字段,客户端用WEB service来获取数据,没有必要把整个PO对象传递到客户端,这时我们就可以用只有这10个属性的DTO来传递结果到客户端,这样也不会暴露服务端表结构.到达客户端以后,如果用这个对象来对应界面显示,那此时它的身份就转为VO.

用于表示一个数据传输对象。DTO 通常用于不同服务或服务不同分层之间的数据传输。DTO 与 VO 概念相似,并且通常情况下字段也基本一致。但 DTO 与 VO 又有一些不同,这个不同主要是设计理念上的,比如 API 服务需要使用的 DTO 就可能与 VO 存在差异。通常遵守 Java Bean 的规范,拥有 getter/setter 方法

DAO(Data access object) 数据访问对象
这个大家最熟悉,和上面几个O区别最大,基本没有互相转化的可能性和必要.,主要用来封装对数据库的访问。通过它可以把POJO持久化为PO,用PO组装出来VO、DTO;

用于表示一个数据访问对象。使用 DAO 访问数据库,包括插入、更新、删除、查询等操作,与 PO 一起使用。DAO 一般在持久层,完全封装数据库操作,对外暴露的方法使得上层应用不需要关注数据库相关的任何信息。

POJO(Plain ordinary java object) 简单java对象
一个POJO持久化以后就是PO;直接用它传递、传递过程中就是DTO;直接用来对应表示层就是VO。

举个例子:
事情:统计研发部门中的季度绩效(暂定以工程师填写的为准,当然实际上大部分不是)
过程:CTO发布统计绩效请求(附带要求:每个人对应的绩效等级)->各个组(也可以是子部门)负责人发布统计绩效请求(每个对应的绩效等级,并将绩效分为了3个方面)->每位开发工程师统计自己绩效(自身各个方面);
可以从例子中看到:每个责任人要求都不同;
对于CTO,他需要知道的是该季度所用员工的绩效等级;这里可以认为VO:员工姓名、绩效等级;
开发工程师:需将本人这个季度的各个方面的表现都列出来:员工姓名、绩效等级、A方面表现内容及等级、B方面表现内容及等级、C方面表现内容及等级、D方面表现内容及等级、E方面表现内容及等级、F方面表现内容及等级、E方面表现内容及等级;此处可认为是PO:员工姓名、绩效等级、A方面表现内容、A方面等级….E方面表现内容、E方面等级;
然后开发工程师将员工姓名、绩效等级、A方面表现内容及等级、B方面表现内容及等级、C方面表现内容及等级内容传递给小组负责人;此处传递的对象就是DTO
小组负责人:从开发工程师中获取到数据后,经过评定,然后得出员工姓名、绩效等级、原因;此处的评定,可以理解为BO;

14.Objects中的equals方法

避免空指针

Objects.equals(a,b);

//容易空指针
String str = null;
String str2 = "abc";
boolean flag = str.equals(str2);

15.java中两个Integer比较大小需要注意的误区

通过下面的例子,来了解 Integer 比较大小需要注意的几点。

Integer a = 1;
Integer b = 1;
System.out.println(a == b);     // true

Integer c = 128;
Integer d = 128;
System.out.println(c == d);    // false
这是因为 Integer 类在内存中有一个值的范围为[-128, 127]的对象池。

只要 Integer 对象的值在[-128, 127]范围内,都是从这个对象池中取。所以只要是这个范围的 Integer 对象,只要值相同,就是同一个对象。那么 == 的结果,就是 true。超过了这个范围,则会 new 新的 Integer 对象,尽管值相同,但是已经是不同的对象了。

如果你是这样写:

Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println(a == b);    // false
那么结果就是 false 了,因为他重新生成对象了;

如果超过了 [-128, 127] 之间的值,被装箱后的 Integer 对象并不会被重用,即相当于每次装箱时都新建一个 Integer 对象,所以 Integer c = 128Integer d = 128 参考的不同的对象。内存地址不同,结果是 false,对象如果要比较值,应该用 .equals()方法。

16.浮点类型的比较

\8.**强制**】浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用

equals 来判断。

说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进

制无法精确表示大部分的十进制小数,具体原理参考《码出高效》。

反例:

 float a = 1.0f - 0.9f;

 float b = 0.9f - 0.8f;

 if (a == b) {

 // 预期进入此代码快,执行其它业务逻辑

 // 但事实上 a==b 的结果为 false

 }

 Float x = Float.valueOf(a);

 Float y = Float.valueOf(b);

 if (x.equals(y)) {

 // 预期进入此代码快,执行其它业务逻辑

 // 但事实上 equals 的结果为 false

 }

正例:

(1) 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。

 float a = 1.0f - 0.9f;

 float b = 0.9f - 0.8f;

 float diff = 1e-6f;

 if (Math.abs(a - b) < diff) {

 System.out.println("true");

 }

(2) 使用 BigDecimal 来定义值,再进行浮点数的运算操作。

 BigDecimal a = new BigDecimal("1.0");

 BigDecimal b = new BigDecimal("0.9");

 BigDecimal c = new BigDecimal("0.8");

 BigDecimal x = a.subtract(b);

 BigDecimal y = b.subtract(c);

 if (x.equals(y)) {

 System.out.println("true");

 }

16.BigDecimal

【BigDecimal是什么?】

1、简介
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

2、构造器描述
BigDecimal(int) 创建一个具有参数所指定整数值的对象。
BigDecimal(double) 创建一个具有参数所指定双精度值的对象。 //不推荐使用
BigDecimal(long) 创建一个具有参数所指定长整数值的对象。
BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。//推荐使用

3、方法描述
add(BigDecimal) BigDecimal对象中的值相加,然后返回这个对象。
subtract(BigDecimal) BigDecimal对象中的值相减,然后返回这个对象。
multiply(BigDecimal) BigDecimal对象中的值相乘,然后返回这个对象。
divide(BigDecimal) BigDecimal对象中的值相除,然后返回这个对象。
toString() 将BigDecimal对象的数值转换成字符串。
doubleValue() 将BigDecimal对象中的值以双精度数返回。
floatValue() 将BigDecimal对象中的值以单精度数返回。
longValue() 将BigDecimal对象中的值以长整数返回。
intValue() 将BigDecimal对象中的值以整数返回。

代码示例在15

【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

说明:下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行

append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。

StringBuffer sb = new StringBuffer();
for (int i = 0; i < 100; i++) {
    sb.append("hello");
}

System.out.println(sb.toString());

17.ArrayList的subList()

【强制】ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异
常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList 而是 ArrayList 的一个视图,对
于 SubList 子列表的所有操作最终会反映到原列表上。
//NNegative example:
List<String> list = new ArrayList<String>();
list.add("22");
//warn
List<String> test = (ArrayList<String>) list.subList(0, 1);  


//Positive example:
List<String> list2 = new ArrayList<String>(list.subList(0, 1));

其中subList(0, 1)取得的是下标为00的元素,不包含下标为1的元素.

18.Map keySet时不能添加问题

强制】使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添

加元素操作,否则会抛出 UnsupportedOperationException 异常。

public class MapTest {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<>();
        map.put("one", "first");
        map.put("two", "second");
        for (String str : map.keySet()) {
            map.put("three", "3");//异常:java.util.ConcurrentModificationException
            System.out.println(map.get(str));

        }
    }
}

19.集合转数组

参考:https://www.runoob.com/java/java-arraylist-toarray.html

arraylist.toArray(T[] arr)

强制】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一

致、长度为 0 的空数组。

反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它类型数组将出

现 ClassCastException 错误。

正例:

List list = new ArrayList<>(2);

list.add(“guan”);

list.add(“bao”);

String[] array = list.toArray(new String[0]);

说明:使用 toArray 带参方法,数组空间大小的 length:

1) 等于 0,动态创建与 size 相同的数组,性能最好。

2) 大于 0 但小于 size,重新创建大小等于 size 的数组,增加 GC 负担。

Java 开发手册

12/44

3) 等于 size,在高并发情况下,数组创建完成之后,size 正在变大的情况下,负面影响与上相同。

4) 大于 size,空间浪费,且在 size 处插入 null 值,存在 NPE 隐患。

20.Array.asList()得到的List不能修改

使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方

法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适

配器模式,只是转换接口,后台的数据仍是数组。

String[] str = new String[] { “yang”, “hao” };

List list = Arrays.asList(str);

第一种情况:list.add(“yangguanbao”); 运行时异常。

第二种情况:str[0] = “changed”; 也会随之修改,反之亦然。

1.修改异常

package com.example.demo.Test;

import java.util.Arrays;
import java.util.List;

public class ListTest {
    public static void main(String[] args) {

        Integer[] arr = new Integer[]{3, 343, 54};
        List list = Arrays.asList(arr);
        for (Object item : list) {
            System.out.println(item);
        }

        list.add(43);//异常




    }
}


Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at com.example.demo.Test.ListTest.main(ListTest.java:16)

2.数组改变 list随之改变

package com.example.demo.Test;

import java.util.Arrays;
import java.util.List;

public class ListTest {
    public static void main(String[] args) {

        Integer[] arr = new Integer[]{3, 343, 54};
        List list = Arrays.asList(arr);
//      list.add(43);
        arr[2] = 888;

        for (Object item : list) {
            System.out.println(item);
        }

    }
}



3
343
888

Process finished with exit code 0

21.instanceof用法

public class Application {

public static void main(String[] args) {

// Object > Person > teacher
// Object > Person > Student
// Object > String
Object o = new Student(); // 主要看这个对象是什么类型与实例化的类名
// instanceof关键字可以判断左边对象是否是右边类或者子类的一个实例
System.out.println(o instanceof Student); // o 是Student类的一个实例对象 所以判断右边类跟student有无关系 以及显示声明有无关系
System.out.println(o instanceof Person); // true
System.out.println(o instanceof Object); // true
System.out.println(o instanceof String); // false
System.out.println(o instanceof Teacher); // 无关系
System.out.println("========================");
Person person = new Student();
System.out.println(person instanceof Person); // true
System.out.println(person instanceof Object); // true
// System.out.println(person instanceof String); // 编译错误
System.out.println(person instanceof Teacher); // 无关系
  }
}

22.forEach循环不remove、add

强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用

Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。

正例:

List<String> list = new ArrayList<>();

list.add("1");

list.add("2");

Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {

String item = iterator.next();

if (删除元素的条件) {

iterator.remove();

}

}

反例:

for (String item : list) {

if ("1".equals(item)) {

list.remove(item);

}

}

22.集合初始化

1.map初始值

集合初始化时,指定集合初始值大小。

说明:HashMap 使用 HashMap(int initialCapacity) 初始化。

正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即 loader factor)默认

为 0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值)。

反例:HashMap 需要放置 1024 个元素,由于没有设置容量初始大小,随着元素不断增加,容量 7 次被

迫扩大,resize 需要重建 hash 表,严重影响性能。

2.map遍历

【推荐】使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应

的 value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效率更高。如果是 JDK8,

使用 Map.forEach 方法。

正例:values()返回的是 V 值集合,是一个 list 集合对象;keySet()返回的是 K 值集合,是一个 Set 集合

对象;entrySet()返回的是 K-V 值组合集合。

package com.example.demo.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapTest {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<>();
        map.put("one", "first");
        map.put("two", "second");
//        for (String str : map.keySet()) {
            map.put("three", "3");
//            System.out.println(map.get(str));
//
//        }

        Set<Map.Entry<String, String>> entrySet = map.entrySet();

        for (Map.Entry<String, String> entry : entrySet) {
            System.out.println("entry = " + entry.getKey()+","+entry.getValue());
        }

    }
}

3.map不能存null值

高度注意 Map 类集合 K/V 能不能存储 null 值的情况,如下表格:

集合类 Key Value Super 说明

Hashtable 不允许为 null 不允许为 null Dictionary 线程安全

ConcurrentHashMap 不允许为 null 不允许为 null AbstractMap 锁分段技术(JDK8:CAS)

TreeMap 不允许为 null 允许为 null AbstractMap 线程不安全

HashMap 允许为 null 允许为 null AbstractMap 线程不安全

反例:由于 HashMap 的干扰,很多人认为 ConcurrentHashMap 是可以置入 null 值,而事实上,存储

null 值时会抛出 NPE 异常

23.List去重

1.利用 Set 集合去重

import lombok.Data;
 
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
 
public class DistinctExample {
    public static void main(String[] args) {
        // 创建并给 List 赋值
        List<Person> list = new ArrayList<>();
        list.add(new Person("李四", "123456", 20));
        list.add(new Person("张三", "123456", 18));
        list.add(new Person("王五", "123456", 22));
        list.add(new Person("张三", "123456", 18));
        // 去重操作
        HashSet<Person> set = new HashSet<>(list);
        // 打印集合信息set.forEach(p -> System.out.println(p));
    }
}

2.自定义去重

import lombok.Data;
 
import java.util.ArrayList;
import java.util.List;
 
public class DistinctExample {
    public static void main(String[] args) {
        // 创建并给 List 赋值
        List<Person> list = new ArrayList<>();
        list.add(new Person("李四", "123456", 20));
        list.add(new Person("张三", "123456", 18));
        list.add(new Person("王五", "123456", 22));
        list.add(new Person("张三", "123456", 18));
        // 去重操作
        List<Person> newList = new ArrayList<>(list.size());
        list.forEach(i -> {
            if (!newList.contains(i)) { // 如果新集合中不存在则插入newList.add(i);
            }
        });
        // 打印集合newList.forEach(p -> System.out.println(p));
    }
}

3.使用 Stream 去重

public class DistinctExample {
    public static void main(String[] args) {
        // 创建并给 List 赋值
        List<Person> list = new ArrayList<>();
        list.add(new Person("李四", "123456", 20));
        list.add(new Person("张三", "123456", 18));
        list.add(new Person("王五", "123456", 22));
        list.add(new Person("张三", "123456", 18));
        // 去重操作
        list = list.stream().distinct().collect(Collectors.toList());
        // 打印集合信息
        list.forEach(p -> System.out.println(p));
    }
}
 
@Data
class Person {
    private String name;
    private String password;
    private int age;
 
    public Person(String name, String password, int age) {
        this.name = name;
        this.password = password;
        this.age = age;
    }
}

24.switch参数null值问题

当 switch 括号内的变量类型为 String 并且此变量为外部参数时,必须先进行 null

判断。

package com.example.demo.Test;

public class SwitchTest {
    public static void main(String[] args) {
        method(null);
    }

    public static void method(String param) {
        switch (param) {
            // 肯定不是进入这里
            case "sth":
                System.out.println("it's sth");
                break;
            // 也不是进入这里
            case "null":
                System.out.println("it's null");
                break;
            // 也不是进入这里
            default:
                System.out.println("default");
        }
    }
}


Exception in thread "main" java.lang.NullPointerException

25.参数校验???

【参考】下列情形,需要进行参数校验:

1) 调用频次低的方法。

2) 执行时间开销很大的方法。此情形中,参数校验时间几乎可以忽略不计,但如果因为参数错误导致

中间执行回退,或者错误,那得不偿失。

3) 需要极高稳定性和可用性的方法。

4) 对外提供的开放接口,不管是 RPC/API/HTTP 接口。

5) 敏感权限入口。

12.【参考】下列情形,不需要进行参数校验:??????????没懂

1) 极有可能被循环调用的方法。但在方法说明里必须注明外部参数检查要求。

2) 底层调用频度比较高的方法。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底层才会暴露

问题。一般 DAO 层与 Service 层都在同一个应用中,部署在同一台服务器中,所以 DAO 的参数校验,可

以省略。

3) 被声明成 private 只会被自己代码所调用的方法,如果能够确定调用方法的代码传入参数已经做过检

查或者肯定不会有问题,此时可以不校验参数。

26、注释开发规范

强制】所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释、除了返回值、参数、

异常说明外,还必须指出该方法做什么事情,实现什么功能。

说明:对子类的实现要求,或者调用注意事项,请一并说明。

\3. 【强制】所有的类都必须添加创建者和创建日期。

27.随机数

注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够

取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后

取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。

public class RandomTest {
    public static void main(String[] args) {
        Random random = new Random();
        for(int i=0;i<100;i++) {
              //用于生成0~100之间的随机数(包含0不包含100)
            System.out.println(random.nextInt(100));
            }
        }
    
    for(int i=0;i<100;i++) {
            System.out.println(random.nextLong());
        }
}

46
62
46
69
2
-6801696996200159747
4054216794411610809
4965870808550007374
702570525935977311

28.时间规范

强制】获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();

说明:如果想获取更加精确的纳秒级时间值,使用 System.nanoTime()的方式。在 JDK8 中,针对统计时

间等场景,推荐使用 Instant 类。

\5. 【强制】日期格式化时,传入 pattern 中表示年份统一使用小写的 y。

说明:日期格式化时,yyyy 表示当天所在的年,而大写的 YYYY 代表是 week in which year

(JDK7 之后引入的概念),意思是当天所在的周属于的年份,一周从周日开始,周六结束,

只要本周跨年,返回的 YYYY 就是下一年。另外需要注意:

  • 表示月份是大写的 M

  • 表示分钟则是小写的 m

  • 24 小时制的是大写的 H

  • 12 小时制的则是小写的 h

正例:表示日期和时间的格式如下所示:

new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

日期转换

package com.example.demo.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TimeTest {
    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());
        System.out.println(new Date().getTime());
        StringBuffer sb = new StringBuffer();


        /**
         * 日期转字符串
         */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = sdf.format(new Date());

        System.out.println(dateString);

        /**
         * 字符串转日期
         */
        Date date;
        try {
            date = sdf.parse(dateString);
            System.out.println(date);
        } catch (ParseException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }


    }
}

29.数据库规范

小数类型为 decimal,禁止使用 float 和 double。

如果存储的字符串长度几乎相等,使用 char 定长字符串类型。

\8. 【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长

度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索

引效率。

强制】表必备三字段:id, create_time, update_time。

说明:其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。create_time, update_time

的类型均为 datetime 类型。

强制】必须使用varchar(20)存储手机号

a)涉及到区号或者国家代号,可能出现±()

b)手机号会去做数学运算么?

c)varchar可以支持模糊查询,例如:like“138%”

【推荐】表的命名最好是遵循“业务名称_表的作用”。

正例:jdpay_task / force_project / trade_config

30.类型转换

​ char

​ ↓

Byte→short→int→long—›float→double

自动转换有以下规律:

  1. 小的类型自动转化为大的类型
  2. 整数类型可以自动转化为浮点类型,可能会产生舍入误差

1.自动类型转换(隐式转换)

小的类型自动转化为大的类型

  • 示例1
byte A = 70;
int b = A + 30;
System.out.println("b = " + b);//b = 100
  • 示例2
byte a = 0;

int b = a;

long c = a;

float d = a;

double e = a;

System.out.println("b="+b);

System.out.println("c="+c);

System.out.println("d="+d);

System.out.println("e="+e);

2.整数类型可以自动转化为浮点类型

float A = 2 + 10f;

float B = A - 11.9f;

System.out.println(B)//0.10000038

1.Integer => int

Integer item = new Integer();
//Integer => int
item.intValue() 

2.字符型与数字之间转换

// String -> Integer,Float,Double
String str = "4775";
Integer integer = Integer.parseInt(str);
Float f = Float.parseFloat(str);
Double d = Double.parseDouble(str);

System.out.println("integer = " + integer);// integer = 4775
System.out.println("f = " + f);// f = 4775.0
System.out.println("d = " + d);// d = 4775.0


// String -> 字符串数组
// 方式一
String str1 = "字符串转数组";

String[] strArr1 = new String[str1.length()];
for (int i = 0; i < str1.length(); i++) {
    strArr1[i] = String.valueOf(str1.charAt(i));
    System.out.println("strArr1[i] = " + strArr1[i]);
}
// 方式二 根据正则表达是分割字符串
String[] strArr2 = str1.split("");
for (String item :
        strArr2) {
    System.out.println("item = " + item);
}


// String -> byte[]
byte[] bytes = str1.getBytes(StandardCharsets.UTF_8);
for (byte b : bytes) {
    System.out.print(b);
}


/*------------------------------------------------------------------------------------------*/


/**
 *@Description: int Integer FLOAT double array -> String
 * @param [args]
 * @return void
 * @author HuiLong.Ding
 * @date 2022/7/28 11:23
 */

int a = 10;
Integer b = 12;
Long l= 342L;
Float f2 = 13f;
Double d3 = 442d;

String s1 = String.valueOf(a);
String s2 = String.valueOf(b);
String s5 = String.valueOf(l);
String s3 = String.valueOf(f2);
String s4 = String.valueOf(d3);

System.out.println("s1 = " + s1);
System.out.println("s2 = " + s2);
System.out.println("s5 = " + s5);
System.out.println("s3 = " + s3);
System.out.println("s4 = " + s4);

2.json => 对象

// 1.
JSONObject.parseObject(JedisUtils.getString(CacheKey.TAG_CATEGORY_MAP_KEY), new TypeReference<LinkedHashMap<String, TagCategoryVo>>() {
});


3.字符串 JSON=> List

// 2.
private List<DataCustomerTagDO> findAllTagListByCache() {
        String allTagListString = JedisUtils.getString(CacheKey.ALL_TAG_LIST_KEY);
        List<DataCustomerTagDO> dataCustomerTagDOS = JSONObject.parseArray(allTagListString, DataCustomerTagDO.class);
        if (null == dataCustomerTagDOS) {
            QueryWrapper<DataCustomerTagDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("state", SystemConstant.STATE_1).eq("visiable", SystemConstant.STATE_1).eq("status", SystemConstant.STATUS_1);
            dataCustomerTagDOS = this.list(queryWrapper);
            allTagListString = JSONObject.toJSONString(dataCustomerTagDOS);
            JedisUtils.saveString(CacheKey.ALL_TAG_LIST_KEY, allTagListString);
        }
        return dataCustomerTagDOS;
    }

4.List => JsonString

JedisUtils.saveString(CacheKey.GOODS_CATEGORY_TREE,JSONObject.toJSONString(treeNodeList));

5.ObjectListDO—>ObjectListVO

@Override
public List<SubdivisionResultVO> getSubdivisionList(String masterId) {
    log.info("查询商家人群列表");
    QueryWrapper<SubdivisionDO> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("master_id", masterId).eq("state", SystemConstant.STATE_1);
    List<SubdivisionDO> list = this.list(queryWrapper);

    return BeanConversionUtils.beanListConversion(list, SubdivisionResultVO.class);
}

6.ObjectDO—>ObjectVO

@Override
public SubdivisionResultVO getSubdivisionById(Long id) {
    log.info("通过id查询人群");
    SubdivisionDO subdivisionDO = this.getById(id);

    return BeanConversionUtils.beanConversion(subdivisionDO, new SubdivisionResultVO());
}

VO—> DO

public Boolean saveTemplate(SmsCareTemplateInsertVO smsCareTemplateInsertVO, UserSessionVo userSessionVo) {
        String content = smsCareTemplateInsertVO.getTemplate();
        String shortUrl = smsCareTemplateInsertVO.getTemplateParams();
        // 校验模板内容
        content = this.checkSmsTemplateContent(content,shortUrl,userSessionVo);
        // 提交京东审核获取modelId
        IsvSmsTemplateTypeEnum isvSmsTemplateTypeEnum = IsvSmsTemplateTypeEnum.getByCode(smsCareTemplateInsertVO.getMarketingManner());
        if(null == isvSmsTemplateTypeEnum){
            throw new ApiException("模板类型参数错误!");
        }
        Long modelId = this.isvCreateSmsTemplate(userSessionVo.getMasterId(),
                                                 smsCareTemplateInsertVO.getTemplate(),
                                                 smsCareTemplateInsertVO.getTemplateTitle(),
                                                 isvSmsTemplateTypeEnum.getModelTypeId(),
                                                 isvSmsTemplateTypeEnum.getOperators());
        log.info("modelId=={}", modelId);
        // 保存到本地库
        SmsCareTemplateDO smsCareTemplateDO = new SmsCareTemplateDO();
    
        BeanConversionUtils.beanConversion(smsCareTemplateInsertVO, smsCareTemplateDO);
    
        log.info("smsCareTemplateDO=={}", smsCareTemplateDO);
        smsCareTemplateDO.setModelId(modelId);//设置modelId
        smsCareTemplateDO.setMasterId(userSessionVo.getMasterId());
        smsCareTemplateDO.setShopId(userSessionVo.getShopId());
        smsCareTemplateDO.setTemplate(content);

        smsCareTemplateDO.setStatus(SystemConstant.STATUS_1);
        //TODO 这里原来使用的是saveOrUpdate
        return this.save(smsCareTemplateDO);
    }

7.时间类型转换

Date => LocalDateTime

Date orderTime = smsBillRecharge.getOrderTime();
LocalDateTime orderLocalDateTime = orderTime.toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
 /**
     * LocalDate转Date
     * @param localDate
     * @return
     */
    public static Date localDate2Date(LocalDate localDate) {
        if (null == localDate) {
            return null;
        }
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
}

/**
 * Date转LocalDate
 * @param date
 */
public static LocalDate date2LocalDate(Date date) {
    if (null == date) {
        return null;
    }
    return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

}

/**
 * Date转换为LocalDateTime
 * @param date
 */
public static LocalDateTime date2LocalDateTime(Date date){
    Instant instant = date.toInstant();
    ZoneId zoneId = ZoneId.systemDefault();
    LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
  return localDateTime;
}

/**
 * LocalDateTime转换为Date
 * @param localDateTime
 */
public static Date localDateTime2Date( LocalDateTime localDateTime){
    ZoneId zoneId = ZoneId.systemDefault();
    ZonedDateTime zdt = localDateTime.atZone(zoneId);
    Date date = Date.from(zdt.toInstant());
   return date;
}

https://blog.csdn.net/qq_33414176/article/details/115669100?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166174296116780357241408%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=166174296116780357241408&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-1-115669100-null-null.142v42pc_rank_34,185v2control&utm_term=Duration&spm=1018.2226.3001.4187)

Date、LocalDateTime、字符串 时间相互转化

LocalDateTime转unix时间戳

//获取秒数
Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
//获取毫秒数
Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
unix时间戳转LocalDateTime
long timestamp = System.currentTimeMillis();
LocalDateTime localDateTime = Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
DateStringDate d1 = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = format.format(d1);
String转date
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//注意月份是MM
Date date = simpleDateFormat.parse("2019-09-02");
System.out.println(date);
LocalDateTimeString
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
StringLocalDateTime
String dateStr = "2019-10-28 12:03:15";
DateTimeFormatter localDateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime date = LocalDateTime.parse(dateStr, localDateTimeFormat);
 DateLocalDateTime
LocalDateTime localDateTime = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTimeDate
Date date = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());

31.数据初始值

包装类基本数据类型
Booleanboolean false
Bytebyte 0
Shortshort 0
Integerint 0
Longlong0 L
Characterchar /0000
Floatfloat 0.0F
Doubledouble 0.0D

32、bug集合

1.equired a bean of type ‘XXX‘ that could not be found.

impl实现类没有添加@Service注释

参考:https://blog.csdn.net/weixin_39887965/article/details/124862563?ops_request_misc=&request_id=&biz_id=102&utm_term=.SubdivisionRecommendControlle&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-124862563.142v32experiment_2_v1,185v2control&spm=1018.2226.3001.4187

33.配置Redis开机自启

如何打开服务呢?

方式一:Win+R快捷键输入services.msc,然后回车或者点击确定

方式二:此电脑(win7我的电脑)邮件单击(管理->服务与应用程序->服务)

如何添加redis服务?

再一次运行cmd终端命令行,切换到redis所在的目录,

输入:

redis-server --service-install redis.windows-service.conf --loglevel verbose

34.try catch final return

35.枚举类 Enum

values(), ordinal() 和 valueOf() 方法

enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Serializable 和 java.lang.Comparable 两个接口。

values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量。
package com.example.demo.Test;

/**
 * @BelongsProject: demo
 * @BelongsPackage: com.example.demo.Test
 * @Author: HuiLong.Ding
 * @Description: TODO
 * @Date: 2022/07/26  10:20
 */

public class EnumTest {
    public static void main(String[] args) {
        Color c = Color.RED;
        System.out.println(c);

        // 迭代元素
        for (Color cc : Color.values()) {
            System.out.println("cc = " + cc);

        }

        // 调用 values()
        Color[] arr = Color.values();

        // 迭代枚举
        for (Color col : arr)
        {
            // 查看索引
            System.out.println(col + " at index " + col.ordinal());
        }

        // 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException
        System.out.println(Color.valueOf("RED"));
        // System.out.println(Color.valueOf("WHITE"));
    }


}


enum Color {
    RED(1, "大红色五星红旗"),
    GREEN(2, "头顶青青草原");

    private Integer code;
    private String description;

    Color(Integer code, String description) {
        this.code = code;
        this.description = description;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Color{" +
                "code=" + code +
                ", description='" + description + '\'' +
                '}';
    }
}



public static SubdivisionOrderByTypeEnum getByCode(int code) {
    for (SubdivisionOrderByTypeEnum it : SubdivisionOrderByTypeEnum.values()) {
        if (it.getCode() == code) {
            return it;
        }
    }
    return null;
}

36.时间

1.duration && period

duration && period

37.@Not注解

空检查
@Null			验证对象是否为null
@NotNull		验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank		检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty		检查约束元素是否为NULL或者是EMPTY. 
    
@NotEmpty 用在集合类上面
@NotBlank 用在String上面
@NotNull 用在八种基本类型上{ byte、shor、intlongfloatdoublebooleanchar}

Booelan检查
@AssertTrue		验证 Boolean 对象是否为 true  
@AssertFalse	验证 Boolean 对象是否为 false  

长度检查
@Size(min=, max=)		验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  
@Length(min=, max=)		验证注解的元素值长度在min和max区间内

日期检查
@Past		验证 DateCalendar 对象是否在当前时间之前  
@Future		验证 DateCalendar 对象是否在当前时间之后  
@Pattern	验证 String 对象是否符合正则表达式的规则

数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng"",Integernull
@Min			验证 NumberString 对象是否大等于指定的值  
@Max			验证 NumberString 对象是否小等于指定的值  
@DecimalMax		被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin		被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits			验证 NumberString 的构成是否合法  
@Digits(integer=,fraction=)		验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。

@Range(min=, max=)	验证注解的元素值在最小值和最大值之间
@Range(min=10000,max=50000,message="range.bean.wage")
private BigDecimal wage;

@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
@CreditCardNumber信用卡验证
@Email  验证是否是邮件地址,如果为null,不进行验证,算通过验证。
@ScriptAssert(lang= ,script=, alias=)
@URL(protocol=,host=, port=,regexp=, flags=)

38.mysql 安装配置

强制关闭mysql

tasklist |findstr mysql
taskkill -f -pid 1812

初始化

mysqld  --initialize-insecure

39.新建application模板 bug

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ooa799wT-1667555042409)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220908102556804.png)]

1.接口访问404

扫描不到controller

application目录结果错误,要在web下,和controller一个层级

2.bean找不到

缺少yml配置文件

40.复制mysql表、

create table tb1 like tb2;

1
2、复制表的大体结构及全部数据,不会复制主键、索引等

create table tb1 select * from tb2;

3、分两步完成,先复制表结构,再插入数据

create table tb1 like tb2;
insert into tb1 select * from tb2;

41.mysql自增键过大

解决办法:DO的id上加一个注解

/**
 * 主键id
 */
@TableId(value="id",type = IdType.AUTO)
private Long id;

42.easyexcil 文件导出的使用

 /**
     *@Description: 导出发货列表信息
     * @param
     * @return
     * @author HuiLong.Ding
     * @date 2022/9/13 16:25
     */
    @Override
    public void exportGrantList(RewardGrantQueryVO rewardGrantQueryVO, HttpServletResponse response) throws IOException {
       // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        //清空response
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=gb2312");
        response.setCharacterEncoding("utf-8");
        String date = LocalDateUtils.format(LocalDateTime.now(), "yyMMddhhmmss");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        StringBuilder fileNameBuilder = new StringBuilder();
        fileNameBuilder.append("发货明细").append(date);
        String fileName = URLEncoder.encode(fileNameBuilder.toString(), "UTF-8").replace("\\+", "%20");
        // 置response的Header
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        // 开始写出
        EasyExcel.write(response.getOutputStream())
                .registerWriteHandler(getStyleStrategy())// 设置字体样式
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 设置单元格宽度自适应
                .head(RewardGrantExportTitleVO.class)// 标题列表 通过ExcelProperty注解
                .autoCloseStream(true) // 自动关闭流
                .sheet("发货明细")// 设置sheet
                .doWrite(data(rewardGrantQueryVO));// 写入数据 List

    }

    private List<RewardGrantExportTitleVO> data(RewardGrantQueryVO rewardGrantQueryVO) {
        // todo 添加查询条件
        QueryWrapper queryWrapper = queryCondition(rewardGrantQueryVO);

        List<ActivityRewardGrantDO> activityRewardGrantDOS = activityRewardGrantMapper.selectList(queryWrapper);
        log.info("activityRewardGrantDOS=={}", activityRewardGrantDOS);

        List<RewardGrantExportTitleVO> rewardGrantExportTitleVOs = new ArrayList<>();
        activityRewardGrantDOS.forEach(item -> {
            RewardGrantExportTitleVO rewardGrantExportTitleVO = new RewardGrantExportTitleVO();
            rewardGrantExportTitleVO.setRewardGrantGuid(item.getRewardGrantGuid());
            rewardGrantExportTitleVO.setUserPin(item.getUserPin());
            rewardGrantExportTitleVO.setActivityName(item.getActivityName());
            rewardGrantExportTitleVO.setRewardName(item.getRewardName());
            rewardGrantExportTitleVO.setReceiptName(item.getReceiptName());
            rewardGrantExportTitleVO.setReceiptMobile(item.getReceiptMobile());
            rewardGrantExportTitleVO.setReceiptAddress(item.getReceiptAddress());
            rewardGrantExportTitleVO.setExpressCompany(item.getExpressCompany());
            rewardGrantExportTitleVO.setExpressBill(item.getExpressBill());
            // 发货状态
            if(item.getShipStatus() == 0){
                rewardGrantExportTitleVO.setStatus("未发货");
            }else if(item.getShipStatus() == 1){
                rewardGrantExportTitleVO.setStatus("已发货");
            }
//            // 时间处理
//            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//            rewardGrantExportTitleVO.setAwardTime(formatter.format(item.getAwardTime()));
//            rewardGrantExportTitleVO.setShipTime(formatter.format(item.getShipTime()));
            rewardGrantExportTitleVOs.add(rewardGrantExportTitleVO);
        });
        log.info("rewardGrantExportTitleVOs=={}", rewardGrantExportTitleVOs);
        return rewardGrantExportTitleVOs ;
    }


    //设置样式 去除默认表头样式及设置内容居中
    public static HorizontalCellStyleStrategy getStyleStrategy(){
        //内容样式策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();

        //垂直居中,水平居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 内容边框
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        //设置 自动换行
//        contentWriteCellStyle.setWrapped(true);
        // 字体策略
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 12);
        contentWriteCellStyle.setWriteFont(contentWriteFont);

        //头策略使用默认
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        // 获取字体实例
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontName("宋体");
        headWriteFont.setFontHeightInPoints((short) 12);
        headWriteFont.setBold(true);
        headWriteCellStyle.setWriteFont(headWriteFont);

        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }
package cn.nascent.jdhd.common.utils;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;

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

/**
 * @BelongsProject: jd-hd
 * @BelongsPackage: cn.nascent.jdhd.common.utils
 * @Author: HuiLong.Ding
 * @Description: TODO
 * @Date: 2022/09/14  11:20
 */
public class Custemhandler extends AbstractColumnWidthStyleStrategy {

    private static final int MAX_COLUMN_WIDTH = 255;
    private  Map<Integer, Map<Integer, Integer>> CACHE = new HashMap(8);

    public Custemhandler() {
    }


    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
        if (needSetWidth) {
            Map<Integer, Integer> maxColumnWidthMap = (Map)CACHE.get(writeSheetHolder.getSheetNo());
            if (maxColumnWidthMap == null) {
                maxColumnWidthMap = new HashMap(16);
                CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
            }

            Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
            if (columnWidth >= 0) {
                if (columnWidth > 255) {
                    columnWidth = 255;
                }

                Integer maxColumnWidth = (Integer)((Map)maxColumnWidthMap).get(cell.getColumnIndex());
                if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
                    ((Map)maxColumnWidthMap).put(cell.getColumnIndex(), columnWidth);
                    writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
                }

            }
        }
    }

    private Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {
        if (isHead) {
            return 0;
        } else {
            CellData cellData = (CellData)cellDataList.get(0);
            CellDataTypeEnum type = cellData.getType();
            if (type == null) {
                return -1;
            } else {
                switch(type) {
                    case STRING:
                        return cellData.getStringValue().getBytes().length;
                    case BOOLEAN:
                        return cellData.getBooleanValue().toString().getBytes().length;
                    case NUMBER:
                        return cellData.getNumberValue().toString().getBytes().length;
                    default:
                        return -1;
                }
            }
        }
    }
}

42.自定义分页查询

<resultMap id="turntableJoinLogResultVO" type="cn.nascent.jdhd.service.activity.model.resultvo.activity.TurntableJoinLogResultBO">
    <result column="userPin" property="userPin"/>
    <result column="winStatus" property="winStatus"/>
    <result column="shipStatus" property="shipStatus"/>
    <result column="rewardType" property="rewardType"/>
    <result column="rewardName" property="rewardName"/>
    <result column="joinTime" property="joinTime"/>
</resultMap>

<select id="queryJoinLogPage" resultMap="turntableJoinLogResultVO">
    select atjl.user_pin userPin,
           atjl.win_status winStatus,
           arg.ship_status shipStatus,
           atjl.reward_type rewardType,
           atjl.reward_name rewardName,
           atjl.join_time joinTime
    from    activity_turntable_join_log atjl left join activity_reward_grant arg
    on atjl.join_guid = arg.process_id

    <where>
        atjl.state = 1 and arg.state = 1

        <if test="userPin != '' and userPin != null ">
            AND atjl.user_pin = #{userPin}
        </if>
        <if test="winStatus != '' and #winStatus != null ">
            AND atjl.win_status = #{winStatus}
        </if>
        <if test="shipStatus != '' and #shipStatus != null ">
            AND arg.ship_status = #{shipStatus}
        </if>
        <if test="rewardType != '' and #rewardType != null ">
            AND atjl.reward_type = #{rewardType}
        </if>

        <if test="startTime != '' and startTime != null and endTime != '' and endTime != null">
            AND atjl.join_time between #{startTime} and #{endTime}
        </if>


    </where>



</select>

43.遍历分页pagedto对象

@Override
public PageDTO<TurntableJoinLogResultVO> queryJoinLogPage(TurntableJoinLogQueryVO turntableJoinLogQueryVO) {
    log.info("分页查询参与记录列表入参: turntableJoinLogQueryVO={}", JSON.toJSONString(turntableJoinLogQueryVO));
    Page<ActivityTurntableJoinLogDO> activityTurntableJoinLogDOPage = new Page<>();
    PageDTO<TurntableJoinLogResultVO> resultVOPageDTO = new PageDTO<>();
    try {

        // todo 设置分页
        activityTurntableJoinLogDOPage.setCurrent(turntableJoinLogQueryVO.getStart());
        activityTurntableJoinLogDOPage.setSize(turntableJoinLogQueryVO.getLength());
        // todo 添加查询条件
        QueryWrapper<ActivityTurntableJoinLogDO> queryWrapper = queryCondition(turntableJoinLogQueryVO);
        // todo 分页查询
        activityTurntableJoinLogDOPage = this.page(activityTurntableJoinLogDOPage, queryWrapper);
        // todo 返回值封装
        System.out.println("resultVOPageDTO.getSize() = " + activityTurntableJoinLogDOPage.getRecords().size());
        List<TurntableJoinLogResultVO> turntableJoinLogResultVOList = new ArrayList<>();
        for (int i = 0; i < activityTurntableJoinLogDOPage.getRecords().size(); i++) {
            TurntableJoinLogResultVO turntableJoinLogResultVO = new TurntableJoinLogResultVO();
            System.out.println("JSON.toJSON(activityTurntableJoinLogDOPage.getRecords().get(i)) = " + JSON.toJSON(activityTurntableJoinLogDOPage.getRecords().get(i)));
            // 用户pin user_pin
            turntableJoinLogResultVO.setUserPin(activityTurntableJoinLogDOPage.getRecords().get(i).getUserPin());

            // 中奖状态
            Integer winStatus = activityTurntableJoinLogDOPage.getRecords().get(i).getWinStatus();
            if (winStatus == SystemConstant.ZERO) {
                turntableJoinLogResultVO.setWinStatus("未中奖");
            } else {
                turntableJoinLogResultVO.setWinStatus("已中奖");
            }

            // 奖品发放状态
            QueryWrapper<ActivityRewardGrantDO> qw = new QueryWrapper<>();
            qw.eq("process_id", activityTurntableJoinLogDOPage.getRecords().get(i).getJoinGuid()).last("limit 1");
            ActivityRewardGrantDO activityRewardGrantDO = activityRewardGrantMapper.selectOne(qw);
            turntableJoinLogResultVO.setShipStatus(RewardGrantShipStatusEnum.getDesc(activityRewardGrantDO.getShipStatus()));

            // 商品类型
            String rewardType = null;
            try {
                rewardType = ActivityRewardTypeEnum.getByCode(activityTurntableJoinLogDOPage.getRecords().get(i).getRewardType()).getDesc();
            } catch (Exception e) {
                throw new BadRequestException("奖品类型不存在!");
            }
            turntableJoinLogResultVO.setRewardType(rewardType);

            // 商品名称
            turntableJoinLogResultVO.setRewardName(activityTurntableJoinLogDOPage.getRecords().get(i).getRewardName());

            // 参与时间
            turntableJoinLogResultVO.setJoinTime(activityTurntableJoinLogDOPage.getRecords().get(i).getJoinTime());

            turntableJoinLogResultVOList.add(turntableJoinLogResultVO);
        }
        resultVOPageDTO.setData(turntableJoinLogResultVOList);
        resultVOPageDTO.setTotal(activityTurntableJoinLogDOPage.getTotal());
        resultVOPageDTO.setSize(activityTurntableJoinLogDOPage.getSize());
        resultVOPageDTO.setCurrent(activityTurntableJoinLogDOPage.getCurrent());

    } catch (BadRequestException e) {

        log.error("分页查询参与记录列表异常:e == " + e);
        throw new ApiException(e.getMessage());

    } catch (Exception e) {

        log.error("分页查询参与记录列表异常:e == " + e);
        throw new ApiException("查询失败");
    }
    return resultVOPageDTO;
}

43.导出文件

/**
 *@Description: 导出发货列表信息
 * @param
 * @return
 * @author HuiLong.Ding
 * @date 2022/9/13 16:25
 */
@Override
public void exportGrantList(RewardGrantQueryVO rewardGrantQueryVO, HttpServletResponse response) throws IOException {
    log.info("导出发货列表信息入参:rewardGrantQueryVO:{}", JSON.toJSONString(rewardGrantQueryVO));
    // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
    try {
        //清空response
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=gb2312");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("发货明细", "UTF-8").replace("\\+", "%20");
        // 置response的Header
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        // 开始写出
        EasyExcel.write(response.getOutputStream())
                .registerWriteHandler(ExcelUtils.buildHeadCellStyle())// 设置字体样式
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 设置单元格宽度自适应
                .head(RewardGrantExcelPropertyVO.class)// 标题列表 通过ExcelProperty注解
                .autoCloseStream(true) // 自动关闭流
                .sheet("发货明细")// 设置sheet
                .doWrite(data(rewardGrantQueryVO));// 写入数据 List
    } catch (IOException e) {
        log.error("导出信息列表异常:" + e);
        throw new RuntimeException(e);
    }

}
 /**
     * Build head cell style
     *
     * @return
     */
    public static HorizontalCellStyleStrategy buildHeadCellStyle() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为白色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short)10);
        //加粗
        headWriteFont.setBold(false);
        // 字体样式
        headWriteFont.setFontName("宋体");
        headWriteCellStyle.setWriteFont(headWriteFont);
        //自动换行
        headWriteCellStyle.setWrapped(false);
        // 水平对齐方式
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 垂直对齐方式
        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
//        contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES);
        // 背景白色
        contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        WriteFont contentWriteFont = new WriteFont();
        //自动换行
        contentWriteCellStyle.setWrapped(true);
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short)10);
        // 水平对齐方式
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 垂直对齐方式
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 字体样式
        contentWriteFont.setFontName("宋体");
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

    }

43.mybatis-plus 使用or

QueryWrapper<RewardCenterAwardDO> queryWrapper = new QueryWrapper<>();
queryWrapper.ne(null != rewardNameQueryVO.getId(), "id", rewardNameQueryVO.getId())
        .eq("master_id", masterId)
        .and(null != rewardNameQueryVO.getAwardType(), temp ->temp.eq("award_type",SystemConstant.ONE).or().eq("award_type", SystemConstant.TWO))
        .eq("award_name", rewardNameQueryVO.getAwardName())
        .eq("state", SystemConstant.STATE_1);
Long count = this.count(queryWrapper);

44.mysql中@的使用

select @a;

变量名,如果你不加的话,会认为这是一个列名,但是这列不存在,就报错了;

  • @变量名 : 定义一个用户变量.
  • = 对该用户变量进行赋值.

用户变量赋值有两种方式: 一种是直接用"=“号,另一种是用”:=“号。

其区别在于:

  • 使用set命令对用户变量进行赋值时,两种方式都可以使用;
  • 用select语句时,只能用”:=“方式,因为select语句中,”="号被看作是比较操作符。

(@i:=@i+1)

可以在生成查询结果表的时候生成一组递增的序列号

select (@i:=@i+5) as rownum, surname, personal_name from student, (select @i:=100) as init;

select @ids := 101,@l := 0

GROUP_CONCAT + group by

按照分组,连接字段上的数据,默认以,,也可以指定分割符

45.时间推移计算

@Test
    public void addTest(){
        SimpleDateFormat sdf =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date nowDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nowDate);
        Date updateDate1 = calendar.getTime();
        System.out.println("当前时间="+sdf.format(updateDate1));
        //往前推1个月
        calendar.add(Calendar.MONTH, -1);
        Date updateDate2 = calendar.getTime();
        System.out.println("往前推1个月的时间"+sdf.format(updateDate2));
        //往后推13个月
        calendar.add(Calendar.MONTH, 13);
        Date updateDate3 = calendar.getTime();
        System.out.println("往后推13个月的时间="+sdf.format(updateDate3));
        //往前推1天
        calendar.add(Calendar.DATE, -1);
        Date updateDate4 = calendar.getTime();
        System.out.println("往前推1天的时间"+sdf.format(updateDate4));
        //往前推1小时
        calendar.add(Calendar.HOUR_OF_DAY, -1);
        Date updateDate5 = calendar.getTime();
        System.out.println("往前推1小时的时间="+sdf.format(updateDate5));
        //往前推1分钟
        calendar.add(Calendar.MINUTE, -1);
        Date updateDate6 = calendar.getTime();
        System.out.println("往前推1分钟的时间="+sdf.format(updateDate6));
        //往前推1秒钟
        calendar.add(Calendar.SECOND, -1);
        Date updateDate7 = calendar.getTime();
        System.out.println("往前推1秒的时间="+sdf.format(updateDate7));
    }
**控制台输出:**
    当前时间=2017-10-27 16:35:58
    往前推1个月的时间2017-09-27 16:35:58
    往后推13个月的时间=2018-10-27 16:35:58
    往前推1天的时间2018-10-26 16:35:58
    往前推1小时的时间=2018-10-26 15:35:58
    往前推1分钟的时间=2018-10-26 15:34:58
    往前推1秒的时间=2018-10-26 15:34:57

46.node npm 重装

C:\Users\Administrator>npm install axios -save -g

added 8 packages, and audited 9 packages in 4s

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities
npm notice
npm notice New minor version of npm available! 8.15.0 -> 8.19.2
npm notice Changelog: https://github.com/npm/cli/releases/tag/v8.19.2
npm notice Run npm install -g npm@8.19.2 to update!
npm notice

C:\Users\Administrator>Run npm install -g npm@8.19.2 to update
'Run' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

C:\Users\Administrator> npm install -g npm@8.19.2 to update

47.mapper扫描不到

问题描述

No qualifying bean of type ‘xxx.xxx.mapper.XxxMapper‘ available: expected at least 1 bean which....

解决办法

@MapperScan(basePackages = "com.huilong.ding.dao.reward")

@SpringBootApplication
@ComponentScan(basePackages = "com.huilong.ding")
@MapperScan(basePackages = "com.huilong.ding.dao.reward")//加个扫描
public class MainApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(MainApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class,args);
    }
}

48.util 工具方法

/**
 * @Description: 计算两个日期的相隔天数,采用四舍 退1 如 [2022-09-20 11:30,2022-09-22 15:21] 返回2 不是3
 * @author HuiLong.Ding
 * @date 2022/9/26 16:08
 */
private Integer daysBetween(String date1str, String date2str) throws ParseException {
    log.info("计算两个日期的相隔天数入参:date1str = {},date2str = {} ", date1str, date2str);
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    Date date1 = format.parse(date1str);
    Date date2 = format.parse(date2str);
    return (int) ((date1.getTime() - date2.getTime()) / (1000 * 3600 * 24));
}

/**
 * @Description: 推算时间
 * @param timeStr      开始时间
 * @param intervalTime 间隔时间 eg: -1 往前推1 前, 5 往后推5天
 * @return
 * @author HuiLong.Ding
 * @date 2022/9/29 11:16
 */
private String calculationTime(String timeStr, Integer intervalTime) {
    log.info("根据开始时间推算结束时间入参:timeStr = {},intervalTime = {} ", timeStr, intervalTime);
    SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");
    Date nowDate = DateUtil.parse(timeStr);
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(nowDate);
    // 推移
    calendar.add(Calendar.DATE, intervalTime);
    Date updateDate2 = calendar.getTime();
    String resTime = sdf.format(updateDate2);
    return resTime;
}

49.java实现折线统计图

50.获取list中某个字段的重复数据

 List<String> expressBillList = rewardGrantExcelPropertyVOList.stream().filter(p -> StringUtils.isNotEmpty(p.getExpressBill())).map(p -> p.getExpressBill()).collect(Collectors.toList());
            //获取重复的物流单号
            List<String> expressBillList1 = expressBillList.stream()
                    // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
                    .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
                    .entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList());

            List<String> orderGuidList = rewardGrantExcelPropertyVOList.stream().filter(p->StringUtils.isNotEmpty(p.getRewardGrantGuid())).map(p -> p.getRewardGrantGuid()).collect(Collectors.toList());
            //获取重复的兑换编号
            List<String> orderGuidList1 = orderGuidList.stream()
                    // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
                    .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
                    .entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList());

51.double保留两位小数

https://blog.csdn.net/Coder_kiwi/article/details/109280005?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166528473916782425147477%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=166528473916782425147477&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-2-109280005-null-null.142v52pc_rank_34_queryrelevant25,201v3control_2&utm_term=double%E4%BF%9D%E7%95%99%E4%B8%A4%E4%BD%8D%E5%B0%8F%E6%95%B0&spm=1018.2226.3001.4187

52.mysql更新语句

UPDATE activity_turntable_join_log SET reward_type = 0   WHERE win_status = 0

53.如何新增测试模块

package cn.nascent.jdhd.service.activity.service.templatetrim;

import cn.nascent.jdhd.dao.reward.entity.ActivityRewardGrantDO;
import cn.nascent.jdhd.reward.service.ActivityRewardGrantService;
import cn.nascent.jdhd.service.activity.model.requestvo.activity.TurntableJoinLogQueryVO;
import cn.nascent.jdhd.service.activity.model.resultvo.activity.TurntableDataScreeningResultVO;
import cn.nascent.jdhd.service.activity.service.activity.ActivityTurntableJoinLogService;
import cn.nascent.jdhd.web.MainApplication;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

/**
 * @Author xiejinyou
 * @CreateTime 2022-09-16
 **/

@SpringBootTest(classes = {MainApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
@ActiveProfiles("dev")
class TemplateActivityConfigServiceTest {

    @Autowired
    private TemplateActivityConfigService templateActivityConfigService;

    @Autowired
    private ActivityTurntableJoinLogService activityTurntableJoinLogService;

    @Autowired
    private ActivityRewardGrantService activityRewardGrantService;

    @Test
    void updateReduceTemplateActivityTime() {

        templateActivityConfigService.updateReduceTemplateActivityTime("1222");
    }

    @Test
    void getDataScreening() {
        List<String> time = new ArrayList<>();
        time.add("2022-09-02");
        time.add("2022-10-23");

        TurntableJoinLogQueryVO turntableJoinLogQueryVO = new TurntableJoinLogQueryVO();
        turntableJoinLogQueryVO.setActivityId("129534d9-1ce9-4da4-956f-0e24c62878e5");
        turntableJoinLogQueryVO.setJoinTime(time);
        TurntableDataScreeningResultVO res = activityTurntableJoinLogService.getDataScreening(turntableJoinLogQueryVO);
        System.out.println("res = " + res);
    }

    @Test
    void  addActivityRewardGrant() {
        ActivityRewardGrantDO activityRewardGrantDO = new ActivityRewardGrantDO();
        activityRewardGrantDO.setRewardGrantGuid("测试_订单编号");
        activityRewardGrantDO.setUserPin("测试测试测试");
        activityRewardGrantDO.setActivityName("测试测试测试");
        activityRewardGrantDO.setRewardName("测试测试测试");
        activityRewardGrantDO.setShipStatus(1);
        activityRewardGrantDO.setReceiptName("生态合作");
        activityRewardGrantDO.setReceiptMobile("1433223");
        activityRewardGrantDO.setReceiptAddressDetail("杭州九堡东方电子商务园南讯软件");
        activityRewardGrantDO.setExpressCompany("EMS");
        activityRewardGrantDO.setExpressBill("5323132353231323");
        activityRewardGrantDO.setAwardTime(LocalDateTime.now());
        activityRewardGrantDO.setShipTime(LocalDateTime.now());
        for (int i = 0; i < 10; i++) {
            activityRewardGrantService.addActivityRewardGrant(activityRewardGrantDO);
        }
    }
}

54…stream().map().collect()

https://blog.csdn.net/weixin_40001125/article/details/105766744?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166597515216800186589620%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=166597515216800186589620&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~pc_rank_v39-1-105766744-null-null.142v58pc_rank_34_2,201v3control_2&utm_term=initiateInviteList.stream%28%29.map&spm=1018.2226.3001.4187

取list中的其中一列

List<String> joinTimeList = initiateInviteList.stream().map(DailyInviteDataStatisticsResultBO::getJoinTime).collect(Collectors.toList());

排序

List<String> initiateInviteNumList = initiateInviteList.stream()
        .sorted(Comparator.comparing(DailyInviteDataStatisticsResultBO::getJoinTime))
        .map(DailyInviteDataStatisticsResultBO::getCount).map(Object::toString).collect(Collectors.toList());

55.Function实现接口映射

private final Map<Integer, Function<ActivityDataScreeningQueryVO, ActivityDataScreeningResultVO>> grantTypeMap = new HashMap<>();

@PostConstruct
public void dispatcherInit() {
    grantTypeMap.put(ActivityTypeEnum.ACTIVITY_TURNTABLE_LUCK_DRAW.getCode(), activityTurntableJoinLogService::getDataScreening);
    grantTypeMap.put(ActivityTypeEnum.INVITE_FOLLOW_STORE.getCode(), activityInviteFollowStoreLogService::getDataScreening);
}


@Override
public ActivityDataScreeningResultVO getDataScreening(ActivityDataScreeningQueryVO request) {
    log.info("ActivityDataStatisticsService, 活动统计, request={}", JSONObject.toJSONString(request));
    Function<ActivityDataScreeningQueryVO, ActivityDataScreeningResultVO> function = grantTypeMap.get(request.getActivityType());
    if (null == function) {
        throw new ApiException("参数错误! 请传入正确的活动类型");
    }
    return function.apply(request);
}

56.内外两层的参数校验

public class InviteFollowInsertVO implements Serializable {
    @Valid
    @ApiModelProperty(value = "活动基础配置")
    private ActivityConfigSaveReqVO activityConfig;

    @NotEmpty(message = "活动奖品配置不能为空")
    @ApiModelProperty(value = "活动奖品配置")
    private List<@Valid ActivityRewardConfigSaveReqVO> activityRewardConfigList;

}

57.查询修改git提交的用户名

1 # 获取当前的用户名
2 git config user.name
3
4 # 修改用户名
5 git config --global user.name “新改用户名”

58.mysql 无密码登录

1.停止 MySQL 任务

net stop MySQL
1

2.mysqld 命令:无密码登录

mysqld --console --skip-grant-tables --shared-memory

59.git切换分支

首先通过

$ git branch -a 

来查看所在目录的分支

$ git branch -a
  master
* trunk
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/zhanghanlun

然后输入命令切换分支

适用于第一次创建并切换分支

$ git checkout -b zhanghanlun origin/zhanghanlun
1

其中远程分支为origin/zhanghanlun

本地分支为zhanghanlun

如果已经有本地分支

直接输入命令

git checkout zhanghanlun

60.安装nvm

https://blog.csdn.net/weixin_60187838/article/details/122261341?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166684164616782414942154%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=166684164616782414942154&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-4-122261341-null-null.142v62pc_search_tree,201v3control_2,213v1t3_esquery_v1&utm_term=nvm%20install%2014.15.1&spm=1018.2226.3001.4187

nvm 安装报错:Could not retrieve

在本地找到安装nvm的路径,在nvm文件夹下找到settings.txt,添加以下代码即可:

node_mirror:npm.taobao.org/mirrors/node/
npm_mirror:npm.taobao.org/mirrors/npm/

61.Invalid bound statement (not found): service的方法

Invalid bound statement (not found): cn.sprite.service.reward.service.RewardCenterAwardService.queryTable

意思就是无效绑定,找不到service的方法

原因

包下面所有的接口在编译后之后都会生成相应的实现类,也就是说除了我的AdminUserServiceImp外Spring Boot还注入了一个mapper实现类,当我在Controller中使用@AutoWired或@Resource获取时,获取到时这个Mapper实现类的实例,但实际上并没有真正继承AdminUserService接口,只有你在运行的时候服务器才会报错,找不到对应的方法。

解决办法:

参考地址:Invalid bound statement (not found): service的方法

1、@Mapper注解:
作用:在接口类上添加了@Mapper,在编译之后会生成相应的接口实现类
添加位置:接口类上面

@Mapper
public interface UserDAO {
   //代码
}

2、@MapperScan
作用:指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类
添加位置:是在Springboot启动类上面添加,

@SpringBootApplication
@ComponentScan(basePackages ={ "cn.sprite"})
@MapperScan("cn.sprite.dao")
public class MainApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(MainApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class,args);
    }
}

3、@ComponentScan

@ComponentScan 的作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中,注解定义

基本上所有bean都要扫描注入,否则会报错:找不到对应实体对象

Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐