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 = 128,Integer 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)取得的是下标为0到0的元素,不包含下标为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.自动类型转换(隐式转换)
小的类型自动转化为大的类型
- 示例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();
Date转String:
Date 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);
LocalDateTime 转 String
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
String 转 LocalDateTime
String dateStr = "2019-10-28 12:03:15";
DateTimeFormatter localDateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime date = LocalDateTime.parse(dateStr, localDateTimeFormat);
Date转LocalDateTime
LocalDateTime localDateTime = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime转Date
Date date = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
31.数据初始值
包装类 | 基本数据类型 |
---|---|
Boolean | boolean false |
Byte | byte 0 |
Short | short 0 |
Integer | int 0 |
Long | long0 L |
Character | char /0000 |
Float | float 0.0F |
Double | double 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
37.@Not注解
空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
@NotEmpty 用在集合类上面
@NotBlank 用在String上面
@NotNull 用在八种基本类型上{ byte、shor、int、long、float、double、boolean、char}
Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) 验证注解的元素值长度在min和max区间内
日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符合正则表达式的规则
数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null
@Min 验证 Number 和 String 对象是否大等于指定的值
@Max 验证 Number 和 String 对象是否小等于指定的值
@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits 验证 Number 和 String 的构成是否合法
@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都要扫描注入,否则会报错:找不到对应实体对象