# Java 常用代码片段

# 1. JSON

# 1.1. JSON字符串 转 对象列表

ObjectMapper mapper = new ObjectMapper();

String userListStr = "[ { \"name\": \"张三\", \"age\": 18 } ]";

List<User> userList = mapper.readValue(
  userListStr, 
  mapper.getTypeFactory().constructCollectionType(List.class, User.class)
);

class User {
  private String name;
  private Integer age;
}

# 2. 类型

# 2.1. 判断字符串是不是日期

String dateString = "2023-04-01";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 转化失败会抛异常
LocalDate date = LocalDate.parse(dateString, formatter);
System.out.println(date);


String dateTimeString = "2023-04-01T15:30:00";
// 使用 单引号 包裹特殊字符
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
System.out.println(dateTime);

# 2.2. 字符串 转 数字

import org.apache.commons.lang3.math.NumberUtils;

private static Double objectToDouble(Object obj) {
    if (obj == null) {
        return null;
    }

    String valueStr = obj.toString();

    if (!NumberUtils.isCreatable(valueStr)) {
        return null;
    }

    double value = NumberUtils.toDouble(valueStr);

    return value;
}

# 3. 字节数组与流

字符串 转 字节数组:

String content = "MinIO, 你好!";

byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);

InputStream 转 byteArray:

byte[] byteArray = IOUtils.toByteArray(byteArrayInputStream);

String content = new String(byteArray, StandardCharsets.UTF_8);

byteArray 转 InputStream:

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);

# 4. 列表

# 4.1. 列表 转 Map

/*
  [ 
    { id: 1, age: 18 }, 
    { id, 2, age: 18 } 
  ] 
  => 
  { 
    1: { id: 1, age: 18 }, 
    2: { id: 2, age: 18 } 
  }
*/
Map<Long, User> map = list.stream().collect(Collectors.toMap(User::getId, Function.identity()));

/*
  [ 
    { id: 1, age: 18 }, 
    { id, 2, age: 18 } 
  ] 
  => 
  { 
    1: 18 , 
    2: 18  
  }
*/
Map<Long, User> map = list.stream().collect(Collectors.toMap(User::getId, User::getAge));

# 4.2. 列表 分组

/*
  [ 
    { id: 1, age: 18 }, 
    { id, 2, age: 18 }, 
    { id, 3, age: 20 } 
  ] 
  => 
  { 
    18: [{ id: 1, age: 18 }, { id, 2, age: 18 }], 
    20: [{ id, 3, age: 20 }]
  }
*/
Map<Long, List<User>> collect = list.stream().collect(Collectors.groupingBy(User::getAge));

# 5. 定时任务

# 5.1. 在 SpringBoot 中使用定时任务

步骤1: 在引导类上添加 @EnableScheduling 注解

@SpringBootApplication
@EnableScheduling
public class LabWindApplication extends SpringBootServletInitializer { /* ... */ }

步骤2: 在 bean 的方法上添加 @Scheduled(cron = "0 0/1 * * * ? ")

@Service
public class BookServiceImpl implements BookService {
  // 该方法是 public
  @Scheduled(cron = "0 0/1 * * * ? ") // 每分钟执行一次
  public void setInterval() {
    System.out.println("run ...");
  }

  @Scheduled(‌fixedRate‌ = 1000) // 每分钟执行一次
  @Scheduled(‌fixedRate‌ = 1, timeUnit = TimeUnit.MINUTES) // 每分钟执行一次
}

@Scheduled 的参数:

  • cron‌: 基于 cron 表达式定义执行周期,参考 Cron在线表达式生成器 (opens new window)
  • fixedDelay‌: 任务执行结束后间隔固定时间再次执行(毫秒)
  • ‌fixedRate‌: 任务间隔固定时间执行(毫秒),若当前任务未完成,后续执行将等待当前任务完成
  • timeUnit: 时间单位。TimeUnit.MILLISECONDS (默认) | TimeUnit.MINUTES | ...

注意:

  • 该任务需要等待 SpringBook 完全启动后,(有些项目要好几分钟才会开始执行)才会执行定时任务。

# 6. 资源目录

# 6.1. 获取 resource 目录下的资源

import org.apache.shiro.io.ResourceUtils;

InputStream inputStream = ResourceUtils.getInputStreamForPath("classpath:application.yml");

# 7. 字符串

# 7.1. 字符串模板

import java.text.MessageFormat;
 
String name = "张三";
int age = 18;

String pattern = "我是 {0},今年 {1} 岁";
String result = MessageFormat.format(pattern, name, age);

System.out.println(result); //=> "我是 张三,今年 18 岁"

# 8. 事务

# 8.1. 回滚

回滚所有:

@Transactional(rollbackFor = Exception.class)
public void doStep_1() {
  try {
    // ......
  } catch (Exception e) {  
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  }
}

@Transactional(rollbackFor = Exception.class)
public void doStep_2() {
  try {
    // ......
  } catch (Exception e) {  
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  }
}

// doStep_1() 或 doStep_2() 抛异常,会导致 doStep_1 、doStep_2 都回滚
@Transactional(rollbackFor = Exception.class)
public void doSomething() {
  doStep_1();
  doStep_2();
}

回滚部分:

@Transactional(rollbackFor = Exception.class)
public void doStep_1() {
  // 回滚点
  Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
  try {
    // ......
  } catch (Exception e) {  
    // 回滚到指定 回滚点
    TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
  }
}

@Transactional(rollbackFor = Exception.class)
public void doStep_2() {
  // 回滚点
  Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
  try {
    // ......
  } catch (Exception e) {  
    // 回滚到指定 回滚点
    TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
  }
}

// doStep_1() 或 doStep_2() 抛异常,只会回滚 step 方法本身涉及的 增删改,不会导致其他 step 方法回滚
@Transactional(rollbackFor = Exception.class)
public void doSomething() {
  doStep_1();
  doStep_2();
}

参考:

# 9. Spring

# 9.1. 在 非事务方法 里调用 事务方法

获取事务代理对象

步骤 1. 显式引入 aspectj 依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

步骤 2. 在启动类上通过注解暴露代理对象

@EnableAspectJAutoProxy(exposeProxy = true)
@SpringBootApplication
public class XyzApplication {
    public static void main(String[] args) {
        SpringApplication.run(XyzApplication.class, args);
    }
}

步骤 3. 获取事务代理对象


@Service
public class UserServiceImpl implements IUserService {
  
  // 非事务方法
  public void deleteUser() {
    IUserService userServiceProxy = (IUserService) AopContext.currentProxy();
    
    userServiceProxy.doDeleteUser();
  }

  // 事务方法
  @Transactional
  public void doDeleteUser() {
    // ...
  }
}

# 9.2. 基于 lombok 做构造函数的依赖注入

// 针对加了 final 的成员变量,会添加到构造函数的形参中,进而会被 spring 注入依赖
@RequiredArgsConstructor
@Controller
public class UserController {
    private final IUserService userService;
}

// 等价于:

@Controller
public class UserController {
    @Autowire
    private IUserService userService;
}
本章目录