Java-项目开发记录
mybatis-plus相关
软删除:
使用标志位进行软删除,通常在数据库表中添加一个deleted字段,标记记录是否被删除。通过在查询时过滤掉deleted字段为true的记录,实现软删除功能。
在MyBatis-Plus中,可以通过@TableLogic注解来实现软删除功能。只需在实体类的deleted字段上添加该注解,MyBatis-Plus会自动处理软删除逻辑。
1 | public class User { |
使用:
1 | List<User> users = userMapper.selectList(null); |
会自动拼接为:
1 | SELECT id, name, type, deleted |
在数据库中查询时,使用mybaits plus,Ipage有可能返回null吗?还是说只会返回零条记录?
在使用MyBatis Plus进行分页查询时,如果查询结果为空,则返回的IPage对象中的total属性为0,而不是null。
如果查找不到记录,使用gettRecords()方法获取list得到的结果为[];
请求和响应
在请求和响应中,有一些注解可以帮助我们更好地处理数据:
1 | // 用于将请求体中的JSON数据转换为Java对象 |
在请求和响应中vo对象中,有一些注解可以帮助我们更好地处理数据:
1 | // 用于格式化日期和时间 |
在写请求的vo时,应该去校验前端返回的字段是否正确。
比如:
1 | public class UserRequestVO { |
使用validator去校验,并把错误信息返回给前端:
1 | Set<ConstraintViolation<UserRequestVO>> violations = validator.validate(userRequestVO); |
在action中,使用@Valid注解,自动校验请求参数
1 |
|
对枚举值进行校验
示例枚举类:
1 | public enum AudioType { |
创建一个枚举值校验器:
1 |
|
IDEA配置
自动导包
File -> Settings -> Editor -> General -> Auto Import -> Add unambiguous imports on the fly
自动格式化代码
File -> Settings -> Editor -> Code Style -> Java -> Formatter Control -> Enable formatter markers in comments
自动删去无用的包
File -> Settings -> Editor -> General -> Auto Import -> Optimize imports on the fly
自动添加类描述
File -> Settings -> Editor -> File and Code Templates -> Class -> 在模板开头添加注释
异常处理
不能抛出非受检异常,应该定义自定义异常,常见的:BizException、RuntimeException等
1 | public void someMethod() throws BizException { |
全局异常处理
代码规范
1、抛出异常的地方都需要记录日志
2、日志的格式:时间+类名+方法名+异常信息:
1 | log.error("时间:{},类名:{},方法名:{},异常信息:{}", LocalDateTime.now(), this.getClass().getName(), "方法名", e.getMessage()); |
3、如果需要有空返回,先返回空,而不是先走业务逻辑
Spring Boot相关
@Value注解
为什么@Value注解可以注入配置文件中的值?
Spring 在创建 Bean 时,会使用专门的处理器(BeanPostProcessor)扫描
@Value注解,把${xxx}转成真正的配置值,然后通过反射赋值给字段。
这背后分三步:
1. Spring 会加载配置文件进 Environment
application.yml / application.properties
➡ 会被 Spring 解析成一堆 key-value
➡ 存进 Environment(它是所有配置的统一容器)
例如:
1 | app.name: demo |
Spring 会存成:
1 | Environment["app.name"] = "demo" |
2. Spring 创建 Bean 时,会扫描字段上的 @Value
Spring 在创建 Bean 时,会用到一个特殊的处理器:
1 | AutowiredAnnotationBeanPostProcessor |
它会检查字段上是否有:
@Autowired@Value@Resource- ……等
看到 @Value("${app.name}")
➡ 它会把 ${app.name} 交给 PlaceholderResolver 去解析。
3. Spring 解析占位符并通过反射把值注入字段
${app.name}
➡ 解析得到 "demo"
➡ 反射赋值给字段:
1 | this.name = "demo"; |
Bean 就成功拿到配置文件中的值了。
配置的优先级
- 命令行参数
- Java 系统属性(-Dkey=value)
- OS 环境变量
- jar 外部的 application.yml / properties
- jar 内部(/resources)的 application.yml / properties
- @PropertySource 指定的配置文件
- 默认配置(Spring Boot 自动配置设置的默认值)
启动参数
Java和 Spring Boot 常用启动参数:
1 | java -Xms1g -Xmx2g \ |
Serializable
在 Java 中,实现 Serializable 接口的类可以将其实例转换为字节流,从而实现对象的持久化存储或通过网络传输。
serialVersionUID 的作用
serialVersionUID 是 Java 序列化机制中的一个重要概念。它是一个唯一的标识符,用于验证序列化和反序列化过程中类的版本一致性。
- 当一个对象序列化后写入文件或缓存,再次反序列化时,JVM 会检查类的 serialVersionUID 是否一致。
- 如果类结构改变(新增/删除字段等),但 serialVersionUID 没变,可能导致 序列化不兼容问题。
- 如果没有显式定义,JVM 会根据类的结构生成一个默认的 serialVersionUID,但类结构一改,生成的值会变,导致反序列化失败。
事务
在 Spring 中,事务管理通常通过 @Transactional 注解来实现。它可以应用于类或方法上,以指定该类或方法需要在事务上下文中执行。
注意事项
- @Transactional 必须加在 public 方法上,才一定生效
- 同一个类内部方法调用(self-invocation)不会触发事务
- 事务方法应该放在 Service 层,而不是 Controller
正常调用的链路
1 |
|
外部调用实际执行的是:
1 | OrderService$$Proxy.createOrder() |
同一个类的内部调用:
1 |
|
实际执行的是:
1 | OrderService.methodA() |
此时不会触发事务,完全绕开了Spring AOP,因为没有经过代理对象。
拆成新的类:
1 |
|
实际执行是:
1 | OrderService → OrderApplyService$$Proxy → apply() |
tips
- 构造器注入优于@Autowired注入,推荐使用构造器注入。
- 少用 @Component 扫一切
- 推荐使用 @Service、@Repository、@Controller 等更具体的注解,明确类的角色和职责。
