IDEA Spring Boot 项目相关问题
Tamako

IDEA设置

字体不规则

在使用idea2019.2时存在中文字体忽大忽小不规范的问题,

File => Settings => Editor => Font调整Fallback fontSimHeiSimSunYouYuan

自动换行

  • settings => editor => code style => default options勾选wrap on typing
  • settings => editor => code style => java => wrapping and braces勾选ensure right margin is not exceeded

编译问题

duplicate declaration of version

版本重复,检查pom.xml定义是否重复

引用自定义包报错

The POM for xxxx is missing, no dependency information available

可能是打包方式错误,使用了

mvn package -Dmaven.test.skip=true

而不是

mvn clean install -Dmaven.test.skip=true

  • mvn clean package:删除目标文件夹、编译代码并打包
  • mvn clean install:删除目标文件夹、编译代码并打包、将打好的包放置到本地仓库中

依赖问题

新下载的项目,下载依赖后依赖还是显示无法找到,或者IDEA中一直显示波浪线

分为以下两种情况:

  • 依赖未下载完整,文件全部为*.lastUpdated

  • 依赖文件完整,IDEA飘红不报错

对于第一种情况,可以删除相关临时文件后尝试重新下载。

以下为删除脚本,在相应目录下执行:

1
2
# windows
for /r %i in (*.lastUpdated) do del %i
1
2
# linux
find ./ -name "*.lastUpdated*" | xargs rm -f

对于第二种情况,可能是IDEA的缓存导致,可以尝试剪切pom.xml文件中相关依赖,import change后重新添加并刷新。

启动问题

启动时找不到主类

1
2
错误: 找不到或无法加载主类 XXXX
原因: java.lang.ClassNotFoundException: XXXX

大概率是编译结果问题,尝试mvn clean install

警告非法的反射访问操作

An illegal reflective access operation has occurred

原因:JDK9以上模块不能使用反射去访问非公有的成员/成员方法以及构造方法,除非模块标识为opens去允许反射访问。旧JDK制作的库(JDK8及以下)运行在JDK9上会自动被标识为未命名模块,为了处理该警告,JDK9以上提出了一个新的JVM参数:--illegal-access

该参数有四个可选值:

  • permit:默认值,允许通过反射访问,因此会提示像上面一样的警告,这个是首次非法访问警告,后续不警告
  • warn:每次非法访问都会警告
  • debug:在warn的基础上加入了类似e.printStackTrace()的功能
  • deny:禁止所有的非法访问除了使用特别的命令行参数排除的模块,比如使用–add-opens排除某些模块使其能够通过非法反射访问

解决方法一: 设置以下JVM参数

1
--illegal-access=deny --add-opens java.base/java.lang=ALL-UNNAMED

IDEA可以在运行配置中的VM options中添加上述参数

如果使用Maven打包的时候还是会出现警告,可以在IDEA中的Maven配置中添加全局的Maven参数

如果使用Gradle,在build.gradle中添加

1
2
3
4
5
test {
useJUnitPlatform()
jvmArgs('--illegal-access=deny')
jvmArgs('--add-opens', 'java.base/java.lang.invoke=ALL-UNNAMED')
}

MalformedInputException

启动服务时报错:

Caused by: java.nio.charset.MalformedInputException: Input length = 1

编码设置有问题,

File => Settings => Editor => File Encodings

将所有的格式都转成utf-8格式。

运行问题

MySQL插入emoji报错

Incorrect string value: '\xF0\x9F\x90\x96' for column

原因:

MySQLutf8编码最多3个字节,算不上真正的utf8字符集。

MySQL5.5.3的版本增加了utf8mb4编码集,专门用于兼容4个字节的unicode

  1. 检查MySQL版本是否支持utf8mb4编码:

    select version();

  2. 修改MySQL配置文件
    打开MySQL配置文件mysql/my.cnfmysql/my.ini, 并且添加如下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [client]
    default-character-set=utf8mb4

    [mysql]
    default-character-set=utf8mb4

    [mysqld]
    character-set-client-handshake=FALSE
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    init_connect='SET NAMES utf8mb4'
  3. 重启数据库

    • Windows到服务管理界面重新启动MySql服务:services.msc
    • Linux执行命令:/etc/init.d/mysql restart
  4. 检查数据库配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';

    +--------------------------+--------------------+
    | Variable_name | Value |
    +--------------------------+--------------------+
    || character_set_client | utf8mb4
    || character_set_connection | utf8mb4
    || character_set_database | utf8mb4
    || character_set_filesystem | binary
    || character_set_results | utf8mb4
    || character_set_server | utf8mb4
    || character_set_system | utf8
    || collation_connection | utf8mb4_unicode_ci
    || collation_database | utf8mb4_unicode_ci
    || collation_server | utf8mb4_unicode_ci
    +--------------------------+--------------------+

    必须保证:
    character_set_clientcharacter_se_connectioncharacter_set_databasecharacter_set_resultscharacter_set_serverutf8mb4

  5. 更新客户端配置文件

    1
    2
    3
    4
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/database?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
    jdbc.username=username
    jdbc.password=password

    注意:jdbc.url的内容,characterEncoding=utf8可以被自动识别为utf8bm4

  6. 修改数据库、表和列的字符集SQL语句:

    1
    2
    3
    ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
    ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    ALTER TABLE table_name table_name CHANGE column_name VARCHAR(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  7. 修改应用连接字符串(druid):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="driverClassName" value="${jdbc-driver}"/>
    <property name="url" value="${jdbc-url}"/>
    <property name="username" value="${jdbc-user}"/>
    <property name="password" value="${jdbc-password}"/>
    <property name="filters" value="stat"/>
    <property name="maxActive" value="20"/>
    <property name="initialSize" value="1"/>
    <property name="maxWait" value="60000"/>
    <property name="minIdle" value="1"/>
    <property name="timeBetweenEvictionRunsMillis" value="3000"/>
    <property name="minEvictableIdleTimeMillis" value="300000"/>
    <property name="validationQuery" value="SELECT 'x'"/>
    <property name="testWhileIdle" value="true"/>
    <property name="testOnBorrow" value="false"/>
    <property name="testOnReturn" value="false"/>
    <property name="poolPreparedStatements" value="true"/>
    <property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>
    <property name="connectionInitSqls" value="set names utf8mb4;"/> //必须添加
    </bean>

    注意:mysql-connector-java驱动在5.1.13之前是不支持utf8mb4,请使用5.1.13以后的版本。

Collectors.toMap 报错

错误

  1. valuenull时会报错

    解决方法为

    1
    List.stream().collect(HashMap::new,(m,v)->m.put(v.getId(),v.getValue()),HashMap::putAll);
  2. 当主键重复时会报错,解决方法为

    1
    List.stream().collect(Collectors.toMap(V::getId, V::getValue, (oldValue, newValue) -> newValue));

原因

Oracle JDK1.8.0_291为例,查询Collectors.toMap调用链,

1
2
3
4
5
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}

这里找到throwingMerger()实现

1
2
3
private static <T> BinaryOperator<T> throwingMerger() {
return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}

可以看出默认的合并方法是不允许重复key出现的。

往下继续看,

1
2
3
4
5
6
7
8
9
10
public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier) {
BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}

找到map.merge的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}

从这里就可以看出来默认的toMap思想是不支持重复键,也不支持空值。

向下找到HashMap的实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
if (value == null)
throw new NullPointerException();
if (remappingFunction == null)
throw new NullPointerException();
......
if (old != null) {
V v;
if (old.value != null)
v = remappingFunction.apply(old.value, value);
else
v = value;
if (v != null) {
old.value = v;
afterNodeAccess(old);
}
else
removeNode(hash, key, null, false, true);
return v;
}
}

可以看出,和默认方法基本一致,也就导致了报错。