Java 问题与修复
指定配置和端口 --- 直接命令运行代码 1. 确认项目结构和入口 src/ 里是源码(.java 文件) bin/ 里是编译后的 .class 文件(如果已经编译过) lib/ 里是依赖的 jar …
指定配置和端口
1java -jar -server blog-1.0.jar --spring.profiles.active=prod --server.port=9001
直接命令运行代码
1.
2├── bin
3│ ├── encrypt
4│ │ ├── AesUtil.class
5│ └── test
6│ ├── RestClientFetchData.class
7│ └── TestMain.class
8├── lib
9│ ├── bcprov-jdk15-143.jar
10│ ├── commons-codec-1.3.jar
11│ └── json.jar
12├── src
13│ ├── encrypt
14│ │ ├── AesUtil.java
15│ └── test
16│ ├── RestClientFetchData.java
17│ └── TestMain.java
18└──
- 确认项目结构和入口
src/ 里是源码(.java 文件)
bin/ 里是编译后的 .class 文件(如果已经编译过)
lib/ 里是依赖的 jar 包
- 编译源码(如果还没编译)
假设你的源码在 src/,目标 class 文件输出到 bin/,可以用如下命令:
1mkdir -p bin
2javac -d bin -cp "lib/*" src/**/*.java
- 找到主类(Main class)
主类一般有 public static void main(String[] args) 方法。假设主类叫 com.example.Main,你需要知道它的全限定名(包名+类名)。
- 运行项目
1java -cp "bin:lib/*" com.example.Main
-cp "bin:lib/*":包含编译输出和依赖com.example.Main:主类的全限定名
注意:在 macOS 或 Linux 下用冒号 : 分隔 classpath,Windows 下用分号 ;
-cp 是 -classpath 的缩写
DTO 类返回从命令从驼峰变成下划线
整个类用 @JsonNaming
1import com.fasterxml.jackson.databind.PropertyNamingStrategies;
2import com.fasterxml.jackson.databind.annotation.JsonNaming;
3
4@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
5public class ExampleDto {
6 // … 字段不变 …
7}
单个字段用 @JsonProperty
1import com.fasterxml.jackson.annotation.JsonProperty;
2
3public class DaypartingCalcResultDto {
4 @JsonProperty("total_use_electricity")
5 private Double totalUseElectricity;
6
7 @JsonProperty("peak_cost")
8 private String peakCost;
9
10 // …其余字段类似…
11}
数据库连接池 HikariCP 对比 Druid
- 选HikariCP:当项目需要高性能、简单配置,且以性能为核心考量。
- 选Druid:当项目需要详细监控、SQL优化功能,且愿意接受稍复杂的配置。有控制台
String 类中 empty 和 blank 的区别
1"".isEmpty(); // true
2" ".isEmpty(); // false(因为有空格)
3null.isEmpty(); // 会抛出 NullPointerException
isEmpty()判断某字段字符串是否为空,为空的标准是 str == null 或者 str.length() == 0
1"".isBlank(); // true
2" ".isBlank(); // true
3"\n\t".isBlank(); // true
4"abc".isBlank(); // false
5null.isBlank(); // 会抛出 NullPointerException
isBlank()【Java 11+】判断某字符串是否为空或长度为 0 或由空白符、制表符、换行符、换页符、回车符构成
建议用 import org.springframework.util.StringUtils;
!StringUtils.hasLength(str) = isEmpty
!StringUtils.hasText(str) = isBlank
BeanUtils.copyProperties 用法
BeanUtils.copyProperties 可以用于更新,将源数据更新到目标数据中
1import org.springframework.beans.BeanUtils;
2public Result updatePostgraduate(@RequestBody EasPostgraduate easPostgraduate) {
3 EasPostgraduate oldPostgraduate = easPostgraduateService.getById(easPostgraduate.getId());
4 BeanUtils.copyProperties(easPostgraduate, oldPostgraduate); easPostgraduateService.updateById(oldPostgraduate);
5}
6
7// 集合类需要遍历复制
8List<Company> companies = companyMapper.selectList(new QueryWrapper<Company>().lambda().like(name != null
9&& !"".equals(name), Company::getName, name) );
10List<CompanyInfoVO> companyInfo = new ArrayList<>();
11for (Company company : companies) {
12 CompanyInfoVO companyInfoVO = new CompanyInfoVO();
13 BeanUtils.copyProperties(company, companyInfoVO);
14 companyInfo.add(companyInfoVO);
15}
@WebFilter 过滤路径太广
@WebFilter不加任何属性时为过滤全部路径
@WebFilter(urlPatterns = "")加上这个属性之后只过滤指定路径,指定路径在其他地方写
JSONObject 链式添加元素
new JSONObject().fluentPut("code", 400);
且可以直接 new 对象放入在其他 JSONObject 里
jo.put("data", new JSONObject().fluentPut("status", "read"));
JSONArray 转换成 Java 列表
1JSONArray records = respJson.getJSONArray("records");
2List<JSONObject> javaList = records.toJavaList(JSONObject.class);
或者直接
1List<JSONObject> list = respJson.getList("records", JSONObject.class);
使用 JSONObject 和 VO 区别
如果查询的 SQL 返回 null,则 JSONObject 不返回此字段值,VO 则返回字段值 "field" : null
请求参数的限制
参数上写上@RequestParam这个注解,代表参数需要存在默认是(required = true)
参数上什么都不写等于@RequestParam(required = false),就是这个参数不传值就为null
参数上写上@NonNull,参数为不传则直接抛出 NPE 异常,是 Lombok 的注解
建议必传参数用@RequestParam,不必传参数就不写注解
@WebFilter 注解方式不生效
注意filterName不要显示的写类的驼峰命名法,直接去掉会默认以类名驼峰命名法来注入到 bean 中,在Application中加上@ServletComponentScan注解来启动
打印字体输出颜色
System.out.println可以输出一段文本,并且默认的字体颜色是黑色。如果想要把部分文本以红色字体显示,需要使用控制台输出时支持 ANSI 转义序列的终端工具。
1System.out.println("\033\[31m" + "哈哈" + "\033\[0m");
其中,\033\[31m表示设置当前输出文本的颜色为红色,
\033\[0m表示重置输出文本的格式,确保之后的文本不会受到前面设置属性的影响。
ANSI 转义序列中的\033\[33m 表示将文本颜色设置为黄色,其中 33 代表颜色代码。具体而言,在 ANSI 颜色编码中,30-37 分别代表黑、红、绿、黄、蓝、紫、青和白。
项目运行立即执行一次任务
1@PostConstruct
2public void executeTask() {}
这将使任务在 Spring 应用程序上下文加载后立即执行一次,并且不会重复执行。请注意,此方法不是传统的基于时间的 cron 表达式方式,而是基于事件的触发器方法,在Spring框架中比较常见。
字段值为 null 不返回此字段
1// 实体类上加 @JsonInclude(JsonInclude.Include.NON_NULL)
2@JsonInclude(JsonInclude.Include.NON_NULL)
3public class SuccessResult extends Result { public Object data; ... }
实体类日期类型格式化
在实体类上增加@JsonFormat注解
1@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
2private LocalDateTime createTime;
@Secured 和 @PreAuthorize 注解的区别
@Secured和@PreAuthorize是 Spring Security 框架中用于方法安全性检查的两个注解。它们的主要区别在于安全检查的方式和表达式的使用。
- 安全检查方式:
- @Secured:基于角色和权限进行安全性检查。该注解通过指定一个或多个角色或权限,限制方法的访问。例如,@Secured(“ROLE_ADMIN”)表示只有具有“ROLE_ADMIN”角色的用户才能访问该方法。
- @PreAuthorize:基于表达式进行安全性检查。该注解使用 Spring Expression Language(SpEL)表达式来定义访问规则。例如,@PreAuthorize(“hasRole(‘ROLE_ADMIN’)”)表示只有具有“ROLE_ADMIN”角色的用户才能访问该方法。
- 表达式使用:
- @Secured:不支持使用表达式,只能直接指定角色或权限。例如,@Secured(“ROLE_USER”)表示只有具有“ROLE_USER”角色的用户才能访问该方法。
- @PreAuthorize:支持使用Spring Expression Language(SpEL)表达式来进行访问控制。SpEL 是一种强大的表达式语言,可以访问方法参数、方法返回值、作用域对象等。例如,@PreAuthorize(“hasRole(‘ROLE_ADMIN’)”)表示只有具有“ROLE_ADMIN”角色的用户才能访问该方法。
在实际应用中,@PreAuthorize注解通常更为灵活,因为它可以使用表达式来定义复杂的访问规则,如基于多个角色、权限以及其它条件的组合进行访问控制。而@Secured注解则更适用于简单的角色或权限检查场景。
忽略实体类值为null的字段
1List<User> records = pageInfo.getRecords();
2List<JSONObject> list = JSONObject.parseArray(JSON.toJSONString(records), JSONObject.class);
3// 泛型可以变成自己设置的VO类来接收
4List<MemberInfoVO> list = JSONObject.parseArray(JSON.toJSONString(records), MemberInfoVO.class);
Lambda 批量插入数据库写法
1List<String> authoritiesList = wrapper.getJSONArray("authorities").toJavaList(String.class)
2List<UserAuthority> list = new ArrayList<>();
3authoritiesList.forEach(authority -> list.add(new UserAuthority().setUid(uid).setAuthority(authority));
Token 前缀去除
1// 去除token前面的"Bearer "
2token = token.replaceFirst("^\\\S+\\\s", "");
日期字符串解析成 LocalDateTime
1// 格式必须为 2023-01-01T00:00:00 才行 String startDateTimeStr = wrapper.getString("startDateTime");
2LocalDateTime startDateTime = LocalDateTime.parse(startDateTimeStr);
3// 2023-01-01 00:00:00 就不行会报错 要用以下办法
4DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
5LocalDateTime startDateTime = LocalDateTime.parse(startDateTimeStr, formatter);
jar 包增量更新
- 将解压后的文件放在一个没有任何其他内容的文件夹中。
- 删除原 jar 包,确保当前文件夹中只包含你想要压缩的文件。
- 在该文件夹中打开命令行窗口(在文件路径中输入 cmd 即可进入)。
- 在命令行中输入
jar cvf0M name.jar ./,其中 name 代表你想要的 jar 包的名字,./表示当前文件夹中的所有文件。 - 按下回车键,命令行会开始压缩文件,并生成一个新的 jar 包。
Java 命令传递键值对形式的配置
1java -DmyProperty=myValue -jar app.jar
可以使用 System.getProperty("myProperty") 来获取这个属性的值:
1public class Main {
2 public static void main(String[] args) {
3 String myProp = System.getProperty("myProperty");
4 System.out.println("My Property: " + myProp);
5 }
6}
跳过单元测试
点击 Maven 中的禁止图标 Toggle ‘Skip Tests’ Mode
自动装配 mapper 报红线解决方式
1@Autowired(required = false)
2private UserMapper userMapper;
1@Resource
2private UserMapper userMapper;
1@Repository
2// Mapper 接口加上 @Repository 注解
1@RequiredArgsConstructor(onConstructor = @__(@Autowired))
2// Lombok 的注解,使用构造方法注入的方式