整理一下自己遇到的坑

整理一下自己遇到的坑(长期更新)


RPC相关

1.dubbo中传输的DTO首先一定要序列化,其次不能为LocalDateTime类型,否则会报序列化异常(有可能是我dubbo版本不是最新的原因)

Mybatis相关

1.新版本的Mybatis,在mapper.xml文件中的方法如果入参类型是JAVA 8 中的新的日期类,如LocalDate,则不能直接通过#{date}的方式在SQL中进行日期比较。要在DAO中相关的方法对日期类加@Param(“date”) 注解,这样对#{date}才能解析为一个时间而不是类下的参数,否则会报异常。

2.当mybatis驱动类为6.0以上时,即

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.6</version>
</dependency>

数据库的写数据和查数据会有时区问题,解决方式:在数据库链接中增加
&serverTimezone=GMT%2b8 指定时区为东八区(能看到我这个页面的都是中国人吧。。)

3.mybaits-plus自定义sql不生效的问题,如果在配置文件中增加了下列配置仍无法生效的话
mybatis-plus.mapper-locations=classpath:/mapper/*.xml
则在config中手动为MybatisSqlSessionFactoryBean类增加xml资源文件

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactory.setMapperLocations(resolver.getResources("classpath*:/mapper/**/*.xml"));

4.最近在使用原生的jdbc中的PreparedStatement进行查询时,发现了一个坑,因为PreparedStatement源码中,在第一次查询时,会预先根据sql查询元数据结构,并将元数据结构缓存下来以提高性能,其中部分源码如下。
这样会造成的问题:如果表的结构变了,新增列或者删除列,会导致查询报错,抛出java.lang.ArrayIndexOutOfBoundsException异常
解决方案:指定cachePrepStmts参数为false则会每次查询都去初始化pStmt,当然这么做有点蠢,但是目前来不及想更好的解决方案了,先这么做,在jdbc的链接参数中增加jdbc:mysql://xxx?useUnicode=true&cachePrepStmts=false即可
更好的解决方案:PreparedStatement设置缓存就是为了提高性能,但是如果表结构确实会发生变化,建议使用Statement,并自己实现查询sql的转义,防止sql注入

			if (this.cachePrepStmts.getValue()) {
                    synchronized (this.serverSideStatementCache) {
                        pStmt = this.serverSideStatementCache.remove(new CompoundCacheKey(this.database, sql));

                        if (pStmt != null) {
                            ((com.mysql.cj.jdbc.ServerPreparedStatement) pStmt).setClosed(false);
                            pStmt.clearParameters();
                        }

                        if (pStmt == null) {
                            try {
                                pStmt = ServerPreparedStatement.getInstance(getMultiHostSafeProxy(), nativeSql, this.database, resultSetType,
                                        resultSetConcurrency);
                                if (sql.length() < this.prepStmtCacheSqlLimit.getValue()) {
                                    ((com.mysql.cj.jdbc.ServerPreparedStatement) pStmt).isCached = true;
                                }

                                pStmt.setResultSetType(resultSetType);
                                pStmt.setResultSetConcurrency(resultSetConcurrency);
                            } catch (SQLException sqlEx) {
                                // Punt, if necessary
                                if (this.emulateUnsupportedPstmts.getValue()) {
                                    pStmt = (ClientPreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);

                                    if (sql.length() < this.prepStmtCacheSqlLimit.getValue()) {
                                        this.serverSideStatementCheckCache.put(sql, Boolean.FALSE);
                                    }
                                } else {
                                    throw sqlEx;
                                }
                            }
                        }
                    }
                } else {
                    try {
                        pStmt = ServerPreparedStatement.getInstance(getMultiHostSafeProxy(), nativeSql, this.database, resultSetType, resultSetConcurrency);

                        pStmt.setResultSetType(resultSetType);
                        pStmt.setResultSetConcurrency(resultSetConcurrency);
                    } catch (SQLException sqlEx) {
                        // Punt, if necessary
                        if (this.emulateUnsupportedPstmts.getValue()) {
                            pStmt = (ClientPreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
                        } else {
                            throw sqlEx;
                        }
                    }
                }

Controller调用相关

1.通过在url中传递的参数中原生只支持ASC编码,对于一些特殊字符或者中文必须在返回或者接收时使用URLDecode/URLEncode进行编码。

2.spring-boot对controller的json格式返回值默认使用jackson进行序列化,默认的时区配置是有问题的,会导致debug时的时间为正确的,返回给前端就时间错误了。
解决方式:在配置文件或ymal里增加以下两条配置项
// 时间格式化配置
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
// 时间时区指定
spring.jackson.time-zone=GMT+8

3.某个项目,有个开发在不通知任何人的情况下设置了controller返回对象的json序列化方式为fastjson,并配置了序列化策略为不输出null值,导致排查了很久才发现这个问题,最后解决方式如下,添加SerializerFeature.WriteMapNullValue策略即可

	//创建配置类
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    //修改配置返回内容的过滤
    fastJsonConfig.setSerializerFeatures(
            SerializerFeature.DisableCircularReferenceDetect,
            SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteNullStringAsEmpty
    );

java相关

1.如果对使用了Arrays.asList(arr)的集合进行add或者remove等集合的差并补操作,都会抛出java.lang.UnsupportedOperationException异常。

2.时间格式化字符串YYYY-MM-dd HH:mm:ss和yyyy-MM-dd HH:mm:ss的区别
YYYY根据官方文档的说明是weak year,如果本周跨年则转换出的年份会属于后一年,所以强制使用yyyy进行日期字符串年份的格式化。

3.java debug模式启动应用时如果遇到卡顿的问题,在本机的域名映射中(/private/etc/hosts)的配置一下解决
127.0.0.1 localhost [hostname].local
其中[hostname]的值为执行hostname命令所返回的值

4.如果java启动时指定了远程debug相关配置,在结束应用时,kill -9立即杀死会导致远程debug端口不会被关闭,再次启动发生端口占用的情况

5.java 自己提供的线程池扩展默认是不会向上层抛异常的,有两种方法可以解决,一是自定义线程池实现afterExecute方法处理异常,二是自己在submit方法中手动try catch抛异常

spring相关

1.spring 4.0一下版本无法使用lambda表达式,否则在项目启动时无法加载class文件导致抛出Failed to read candidate component class异常

2.在spring-boot应用中想应用hive-jdbc的话,要排除一系列的jar包冲突问题(谁让hive-jdbc的jar包是个全家桶)。建议:可以去github上找大型的项目,复制他们的maven pom下来,也可以用下面这个。

		<dependency>
			<groupId>org.apache.hive</groupId>
			<artifactId>hive-jdbc</artifactId>
			<version>2.1.0</version>
			<exclusions>
				<exclusion>
					<artifactId>slf4j-log4j12</artifactId>
					<groupId>org.slf4j</groupId>
				</exclusion>
				<exclusion>
					<groupId>org.eclipse.jetty.aggregate</groupId>
					<artifactId>jetty-all</artifactId>
				</exclusion>

				<exclusion>
					<groupId>org.apache.ant</groupId>
					<artifactId>ant</artifactId>
				</exclusion>
				<exclusion>
					<groupId>io.dropwizard.metrics</groupId>
					<artifactId>metrics-json</artifactId>
				</exclusion>
				<exclusion>
					<groupId>io.dropwizard.metrics</groupId>
					<artifactId>metrics-jvm</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.github.joshelser</groupId>
					<artifactId>dropwizard-metrics-hadoop-metrics2-reporter</artifactId>
				</exclusion>

				<exclusion>
					<groupId>io.netty</groupId>
					<artifactId>netty-all</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.google.code.gson</groupId>
					<artifactId>gson</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.google.code.findbugs</groupId>
					<artifactId>jsr305</artifactId>
				</exclusion>
				<exclusion>
					<groupId>io.dropwizard.metrics</groupId>
					<artifactId>metrics-core</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.servlet</groupId>
					<artifactId>servlet-api</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.apache.avro</groupId>
					<artifactId>avro</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.apache.commons</groupId>
					<artifactId>commons-compress</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.apache.curator</groupId>
					<artifactId>curator-client</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.apache.hadoop</groupId>
					<artifactId>hadoop-auth</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.apache.hadoop</groupId>
					<artifactId>hadoop-mapreduce-client-core</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.apache.hadoop</groupId>
					<artifactId>hadoop-yarn-api</artifactId>
				</exclusion>

				<exclusion>
					<groupId>org.apache.zookeeper</groupId>
					<artifactId>zookeeper</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.codehaus.jackson</groupId>
					<artifactId>jackson-jaxrs</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.codehaus.jackson</groupId>
					<artifactId>jackson-xc</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.google.protobuf</groupId>
					<artifactId>protobuf-java</artifactId>
				</exclusion>

				<exclusion>
					<groupId>org.json</groupId>
					<artifactId>json</artifactId>
				</exclusion>
				<exclusion>
					<artifactId>log4j-slf4j-impl</artifactId>
					<groupId>org.apache.logging.log4j</groupId>
				</exclusion>
				<exclusion>
					<artifactId>javax.servlet</artifactId>
					<groupId>org.eclipse.jetty.orbit</groupId>
				</exclusion>
				<exclusion>
					<artifactId>servlet-api-2.5</artifactId>
					<groupId>org.mortbay.jetty</groupId>
				</exclusion>
				<exclusion>
					<artifactId>jasper-runtime</artifactId>
					<groupId>tomcat</groupId>
				</exclusion>
			</exclusions>
		</dependency>

MQ相关

1.在使用rabbitMq做延迟消息时(自带死信机制),死信队列中的消息是从头到尾一条条依次处理消息的过期时间的(FIFO),举个例子,第一条消息过期时间2分钟,第二条消息过期时间5s,只要第一条消息没过期,第二条消息永远不会过期。

猜你喜欢

转载自blog.csdn.net/lvqinglou/article/details/79841693
今日推荐