Java日常使用


字符串

(1)使用 TypeReference序列化复合结构

1
2
Map<String, List<String>> reqVO = JsonUtil.string2Obj(paramString, 
new TypeReference<Map<String, List<String>>>() {});

(2)正则处理

1
2
// 手机号中间4位隐藏为 *
phone.replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2")

(3)正则匹配

1
2
3
Pattern p = Pattern.compile("^[a-zA-Z0-9_\\u4e00-\\u9fa5]+$");
Matcher m = p.matcher("hello_");
System.out.println(m.matches());

日期

(1)LocalDataTime与其他类型互转

1
2
3
4
5
6
7
8
9
// String to LocalDataTime
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime startTime = LocalDateTime.parse("2024-02-06 12:00:00", DATE_TIME_FORMATTER);

// LocalDataTime to String
String startTimeString = DATE_TIME_FORMATTER.format(startTime);

// LocalDataTime to Long(时间戳,8位)
long timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));

(2)获取当天零点

1
LocalDateTime.of(LocalDateTime.now().toLocalDate(), LocalTime.MIN);

数组

(1)list to list

1
2
3
4
5
6
7
8
// list 转 list
List<Integer> l = Arrays.asList(2, 2, 3);
List<Integer> l2 = l.stream().map(i -> i + 1).collect(Collectors.toList());
System.out.println(l2); // [3, 3, 4]

// list 去重
List<Integer> l3 = l.stream().distinct().collect(Collectors.toList());
System.out.println(l3); // [2, 3]

(2)list to map

1
2
3
List<Integer> l = Arrays.asList(1, 2, 3);
Map<Integer, Integer> m = l.stream().collect(Collectors.toMap(Function.identity(), Function.identity()));
System.out.println(m); // {1=1, 2=2, 3=3}

(3)数组 to list

1
2
String[] s = "a,b,c".split(",");
List<String> l = Arrays.asList(s); // 注意此时 l 不可变更,如需变更可在外层包一下 new ArrayList<>()

集合

(1)交集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void test5() {
String cacheRoomData = "1,2,4";
List<Long> finishedRoomIdList = Arrays.stream(cacheRoomData.split(","))
.map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); // [1,2,4]
List<Long> roomIdList = new ArrayList<>(Arrays.asList(1L,2L,3L,5L)); // [1,2,3,5]
boolean updateCache = finishedRoomIdList.retainAll(roomIdList); // finishedRoomIdList 取交集
System.out.println(updateCache); // true
System.out.println(finishedRoomIdList); // [1, 2]
System.out.println(roomIdList); // [1, 2, 3, 5]

roomIdList.removeAll(finishedRoomIdList); // roomIdList 取差集
System.out.println(finishedRoomIdList); // [1, 2]
System.out.println(roomIdList); // [3, 5]
}

(2)初始化

1
2
3
4
5
// HashMap 初始化
public static final Map<String, String> OCEAN_ENGINE_COOKIE_MAP = new HashMap<String, String>() {{
put("a", 1);
put("b", 2);
}};

(3)常规操作

1
2
3
4
5
6
7
8
// HashMap computeIfAbsent: 如果没有对应元素,则进行初始化操作
Map<Integer, List<String>> m = new HashMap<>();
m.computeIfAbsent(1, k -> new ArrayList<>()).add("a");
m.computeIfAbsent(1, k -> new ArrayList<>()).add("b");
m.computeIfAbsent(2, k -> new ArrayList<>()).add("c");
m.computeIfAbsent(2, k -> new ArrayList<>());
m.computeIfAbsent(3, k -> new ArrayList<>());
System.out.println(m); // {1=[a, b], 2=[c], 3=[]}

参数校验

(1)@Valid注解

常用注解如下:

  • 注意在Controller参数前面加上 @Valid

    1
    2
    3
    4
    5
    6
    import javax.validation.Valid;

    @PostMapping("/add")
    public void add(@Valid @RequestBody AddReqVO reqVO) {
    return;
    }
  • 如果是多层嵌套,注意在每一层嵌套参数上加上 @Valid

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import javax.validation.Valid;
    import javax.validation.constraints.NotEmpty;

    public class AddReqVO {
    @NotEmpty(message = "id不能为空")
    private String id;

    @Valid
    private Address address;
    }

    public static class Address {
    @NotEmpty(message = "name不能为空")
    private String name;
    }
  • 如果是在Service层进行校验,则需要如下处理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // interface
    public interface MyService {
    void add(@Valid Entity e);
    }

    // impl
    @Validated // 注意加上这个注解
    public class MyServiceImpl implementsMyService {
    @Override
    public void add(Entity e) {
    }
    }
  • 如果想在Service层复用VO上配置的校验规则(例如 @NotEmpty,@NotNull等),可以直接使用使用进行校验:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import javax.validation.ConstraintViolation;
    import javax.validation.Validator;

    @Resource
    private Validator validator;

    Set<ConstraintViolation<BatchAddBaseTag>> violations = validator.validate(entity1);
    if (!CollectionUtils.isEmpty(violations)) {
    violations.forEach(violation -> errorMessageList.add(violation.getMessage()));
    }

文件

(1)MultipartFile

1
2
3
4
5
6
MultipartFile file;
// 文件大小比较
file.getSize() > 1 * 1024 * 1024 // 1M大小

// 文件名(包含文件后缀)
String imageName = file.getOriginalFilename();

Mybatis

(1)Mybatis Plus 添加 分页插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 添加 config
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}

// LambdaQueryWrapper 使用
// 注意,queryWrapper 存在缓存,如果需要重复使用 queryWrapper,使用前要调用 queryWrapper.clear();
LambdaQueryWrapper<Hello> queryWrapper = new QueryWrapper<Hello>().lambda();
queryWrapper.eq(Hello::getType, reqVO.getType())
.eq(Hello::getName, reqVO.getName())
.orderByDesc(Hello::getId());

// Page 使用
com.baomidou.mybatisplus.extension.plugins.pagination.Page<Hello> recordPage =
new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(page, pageSize);
com.baomidou.mybatisplus.extension.plugins.pagination.Page<Hello> recordList =
this.getBaseMapper().selectPage(recordPage, queryWrapper);

(2)MybatisPlusGenerator使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.TemplateType;
import com.baomidou.mybatisplus.generator.config.po.LikeTable;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.HashMap;

public class MybatisPlusGenerator {
// 注意修改表名和作者名
public static final String TABLE_NAME = "comment_record";
public static final String AUTHOR = "";

// 暂时使用 tracking 数据库
public static final String MYSQL_HOST = "jdbc:mysql://127.0.0.1:8080/tracking" +
"?serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=false";
public static final String MYSQL_USER_NAME = "";
public static final String MYSQL_USER_PASSWORD = "";
public static final String DATA_FORMAT = "yyyy-MM-dd";

public static final String PROJECT_NAME = "commentservice";
public static final String PARENT_PACKAGE = String.format("cn.com.hello.health.%s", PROJECT_NAME);
public static final String SERVICE_PACKAGE = "service.i";
public static final String SERVICE_IMPL_PACKAGE = "service.impl";
public static final String ENTITY_PACKAGE = "model.po";
public static final String MAPPER_PACKAGE = "mapper";

public static final String SERVICE_PATH = String.format("src/main/java/cn/com/hello/%s/service/i", PROJECT_NAME);
public static final String SERVICE_IMPL_PATH = String.format("src/main/java/cn/com/hello/%s/service/impl", PROJECT_NAME);
public static final String ENTITY_PATH = String.format("src/main/java/cn/com/hello/%s/model/po", PROJECT_NAME);
public static final String MAPPER_PATH = String.format("src/main/java/cn/com/hello/%s/mapper", PROJECT_NAME);
public static final String XML_PATH = "src/main/resources/mapper";


public static void main(String[] args) {
FastAutoGenerator
.create(MYSQL_HOST, MYSQL_USER_NAME, MYSQL_USER_PASSWORD)
.globalConfig(b -> {
//用户名,日期,swagger可选
b.author(AUTHOR).commentDate(DATA_FORMAT)
// .enableSwagger()
.disableOpenDir()
.build();
}).packageConfig(b -> {
//只需要实体、mapper和xml
b.parent(PARENT_PACKAGE)
.service(SERVICE_PACKAGE)
.serviceImpl(SERVICE_IMPL_PACKAGE)
.entity(ENTITY_PACKAGE)
.mapper(MAPPER_PACKAGE)
// .xml("")
.pathInfo(new HashMap<OutputFile, String>() {{
put(OutputFile.service, SERVICE_PATH);
put(OutputFile.serviceImpl, SERVICE_IMPL_PATH);
put(OutputFile.entity, ENTITY_PATH);
// mapper接口的保存路径
put(OutputFile.mapper, MAPPER_PATH);
// mapper.xml文件的保存路径
put(OutputFile.xml, XML_PATH);
}});
}).templateConfig(b -> b.disable(TemplateType.CONTROLLER
// ,TemplateType.SERVICE
// ,TemplateType.SERVICEIMPL
// 阻止生成 mapper
// ,TemplateType.MAPPER
// 阻止生成 xml
// ,TemplateType.XML
))
.strategyConfig(b -> {
//表,驼峰命名,相关注解等更详细配置 TableField可选
b.addTablePrefix("_").likeTable(new LikeTable(TABLE_NAME))
.entityBuilder().naming(NamingStrategy.underline_to_camel).enableLombok().enableRemoveIsPrefix()
// 开启链式模型。会在实体类前添加 [@Accessors(chain = true)] 注解。
// 用法如 [User user=new User().setAge(31).setName("snzl");](这是Lombok的注解,需要添加Lombok依赖)
.enableChainModel()
.idType(IdType.AUTO)
// .enableTableFieldAnnotation()
.fileOverride()
.mapperBuilder()
// 开启 @Mapper 注解。
// 会在mapper接口上添加注解[@Mapper]
// .enableMapperAnnotation()
.enableBaseResultMap().enableBaseColumnList().fileOverride()
.build();
})//engine可选,org.freemarker/org.apache.velocity
.templateEngine(new FreemarkerTemplateEngine())
.execute();
}
}

Json

(1)主动去除 null 值

1
2
3
4
5
6
7
8
9
10
11
12
private final static ObjectMapper objectMapper =
new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);

private Map<String, Object> transferToMap(Object data) {
try {
return objectMapper.readValue(objectMapper.writeValueAsString(data),
new TypeReference<Map<String, Object>>() {
});
} catch (JsonProcessingException e) {
log.error("序列化失败", e);
}
}

Http

(1)HttpServletResponse构造返回

1
2
3
4
5
6
7
private void buildSuccessResponse(HttpServletResponse response) throws IOException {
response.setCharacterEncoding("utf-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("jsonString"); // 写入Json格式字符串
response.getWriter().flush();
}

easyexcel

easyexcel读取

依赖引入

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Data {

@ExcelProperty(value = "名称")
private String name;

// 按 String 读,转为 Long
@ExcelProperty(value = "编号", converter = LongStringConverter.class)
private Long no;

// 按 String 读,转为 LocalDate
@ExcelProperty(value = "日期",converter = LocalDateNumberConverter.class)
private LocalDate date;

// 按 String 读,转为 LocalDateTime
@ExcelProperty(value = "时间", converter = LocalDateTimeNumberConverter.class)
private LocalDateTime time;
}

读取类
```java
import com.alibaba.excel.EasyExcel;

@PostMapping("/upload-data")
public void uploadData(@RequestParam("file") MultipartFile file) {
if (file == null || file.isEmpty()) {
return;
}

List<Data> readResult = new ArrayList<>();
try {
EasyExcel.read(file.getInputStream(), UploadDataVO.class,
new UploadDataListener(readResult)).sheet().doRead();
} catch (IOException e) {
//
}
}

UploadDataListener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

public class UploadDataListener extends AnalysisEventListener<Data> {

private List<Data> readResult;

public UploadDataListener(List<Data> readResult) {
this.readResult = readResult;
}

@Override
public void invoke(Data data, AnalysisContext context) {
// data即为每行数据
// 获取当前行号
Integer currentRowNum = context.readRowHolder().getRowIndex() + 1;
// 处理 readResult
this.readResult.add(data);
}

@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 所有数据解析完成后可在此处执行其他操作
}
}

easyexcel写入

Controller中写入Excel文件返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// controller代码
@PostMapping("/test")
public void test(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws IOException {
HttpServletResponse response;

// 待写入数据
List<Data> result;

//表头集合
response.setHeader("Content-Disposition", "attachment; filename=1.xlsx");

// 如果文件名包含中文等字符,需要如下处理
String fileName = URLEncoder.encode("文件名", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);

// 响应类型,编码
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
EasyExcel.write(response.getOutputStream(), Data.class)
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(null)).sheet("Sheet1").doWrite(result);
}


Data

1
2
3
4
5
6
7
8
@Data
public class Data {
@ExcelProperty(value = "姓名")
private String name;

@ExcelProperty(value = "年龄")
private String age;
}
作者

lei.ch1941

发布于

2024-02-06

更新于

2024-05-14

许可协议

评论