Maven 打包 Excel 文件损坏

前几天在项目中遇到一个小问题,有一个 Excel 文件放在 classpath 下,通过流下载下来,本地测试的时候一点问题都没,但是部署到测试环境却不行了,说文件已损坏,然后打不开,简单代码如下: @RequestMapping(value = "/export", method = RequestMethod.GET) public void export(HttpServletResponse response) { ServletOutputStream servletOutputStream = null; String filename = "template.xlsx"; InputStream inputStream = ExcelHandleController.class.getClassLoader().getResourceAsStream(filename); try { byte[] b = new byte[inputStream.available()]; inputStream.read(b); response.setCharacterEncoding(StandardCharsets.UTF_8.name()); response.setHeader("Content-Disposition", "attachment;filename=" + filename); response.setContentType("application/octet-stream;charset=UTF-8"); //获取响应报文输出流对象 servletOutputStream = response.getOutputStream(); //输出 servletOutputStream.write(b); } catch (IOException e) { logger.error("文件下载出错", e); } finally { if (null != inputStream) { try { inputStream.close(); } catch (IOException e) { logger.error("文件下载出错", e); } } if (null != servletOutputStream) { try { servletOutputStream.flush(); servletOutputStream.close(); } catch (IOException e) { logger.error("文件下载出错", e); } } } } 当时就感觉这代码很简单啊,没什么问题的,但是下载下来就是不对,想到是不是测试环境有什么问题,查了一下没什么特殊之处,最后发现 Git 上的代码中的文件并没有什么问题,但是打成 war 包解压之后这文件本身就已经损坏了,而且比对了一下两个文件,发现 war 包之中的文件变大了,搜了一下资料,才知道原来 maven 打包会对一些文件转码,这个过程中会损坏一些文件,所以打不开,网上的资料也挺多,最简单的就是增加一个 plugin,不让该文件转码,代码如下: ...

January 13, 2019 · 2 min · 227 words · Bridge Li

Java 学习之路

前几天刷微博,看到博主 @Java大本营 发了一个图片,总结 Java 一些常见的知识点,感觉挺好,整理成文字版,发在我的个人博客,作为一个大家学习复习的文档,也欢迎有人在评论中留下各种参考资料,一下是正文。 一、基础篇 JVM ①. JVM 内存结构 堆、栈、方法区、直接内存、堆和栈的区别 ②. Java 内存模型 内存可见性、重排序、顺序一致性、volatile、锁、final ③. 垃圾回收 内存分配策略、垃圾收集器(G1)、GC 算法、GC 参数、对象存活的判定 ④. JVM 参数及调优 ⑤. Java 对象模型 oop-klass、对象头 ⑥. HotSpot 即时编译器、编译优化 ⑦. 类加载机制 ClassLoader、类加载过程、双亲委派(破坏双亲委派)、模块化(jboss、modules、osgl、jigsaw) ⑧. 虚拟机性能监控与故障处理工具 jps、jstack、jmap、jstat、jconsole、jinfo、jhat、javap、btrace、tprofiler 编译与反编译 javac、javap、jad、CRF Java 基础知识 ①. 阅读源代码 String、Integer、Long、Enum、BigDecimal、ThreadLocal、ClassLoader & URLClassLoader、ArrayList & LinkedList、HashMap & LinkedHashMap & TreeMap & ConcurrentHashMap、HashSet & LinkedHashSet & TreeSet ②. Java 中各种变量的类型 ③. 熟悉 Java String 的使用,熟悉 String 的各种函数 JDK 6 和 JDK 7 中 substring 的原理及区别、replaceFirst、replaceAll、replace 的区别、String 对 “+” 的重载、String.valueOf 和 Integer.toString 的区别、字符串的不可变性 ...

December 31, 2018 · 4 min · 717 words · Bridge Li

使用 Spring AOP 注意事项

说实话,由于我个人某些基础不是很牢固,所以前一段时间关于 Spring Aop 踩了一个坑,其实很简单,今天就记录一下,先说结论: 不能被 Spring AOP 增强的方法: 基于接口的动态代理:除 public 外的其它所有的方法,此外 public static 也不能被增强 基于 CGLib 的动态代理:private、static、final 的方法,也就是只有 public 和 protected 可以,但是要注意切入点语法的配置 测试用例如下,pom 文件: <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.11.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.11.RELEASE</version> </dependency> 配置文件就比较简单了: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <context:annotation-config/> <context:component-scan base-package="cn.bridgeli"/> <aop:aspectj-autoproxy/> </beans> 切面类: package cn.bridgeli.demo.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class LogInterceptor { // @Pointcut("execution(\* \* com.bjsxt.service..*.add(..))") @Pointcut("execution(\* cn.bridgeli.demo.service..\*.*(..))") public void myMethod() { } @Before("myMethod()") public void before() { System.out.println("method before"); } @Around("myMethod()") public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("method around start"); pjp.proceed(); System.out.println("method around end"); } } 测试类: ...

November 25, 2018 · 2 min · 279 words · Bridge Li

【转载】Redis 分布式锁进化史

按:系统架构经过多年演进,现在越来越多的系统采用微服务架构,而说到微服务架构必然牵涉到分布式,以前单体应用加锁是很简单的,但现在分布式系统下加锁就比较难了,我之前曾简单写过一篇文章,关于分布式锁的实现,但有一次发现实现的分布式锁是有问题的,因为出问题的概率很低,所以当时也没在意,前几天和朋友聊这个问题,想起来看过一篇文章,写的不错,今天特转载过来,希望能让更多的人看到,同时也加深一下记忆。原文链接是:http://tech.dianwoda.com/2018/04/11/redisfen-bu-shi-suo-jin-hua-shi/ 以下为原文: 近两年来微服务变得越来越热门,越来越多的应用部署在分布式环境中,在分布式环境中,数据一致性是一直以来需要关注并且去解决的问题,分布式锁也就成为了一种广泛使用的技术,常用的分布式实现方式为Redis,Zookeeper,其中基于Redis的分布式锁的使用更加广泛。 但是在工作和网络上看到过各个版本的Redis分布式锁实现,每种实现都有一些不严谨的地方,甚至有可能是错误的实现,包括在代码中,如果不能正确的使用分布式锁,可能造成严重的生产环境故障,本文主要对目前遇到的各种分布式锁以及其缺陷做了一个整理,并对如何选择合适的Redis分布式锁给出建议。 一. 各个版本的Redis分布式锁 V1.0 tryLock() { SETNX Key 1 EXPIRE Key Seconds } release() { DELETE Key } 这个版本应该是最简单的版本,也是出现频率很高的一个版本,首先给锁加一个过期时间操作是为了避免应用在服务重启或者异常导致锁无法释放后,不会出现锁一直无法被释放的情况。 这个方案的一个问题在于每次提交一个Redis请求,如果执行完第一条命令后应用异常或者重启,锁将无法过期,一种改善方案就是使用Lua脚本(包含SETNX和EXPIRE两条命令),但是如果Redis仅执行了一条命令后crash或者发生主从切换,依然会出现锁没有过期时间,最终导致无法释放。 另外一个问题在于,很多同学在释放分布式锁的过程中,无论锁是否获取成功,都在finally中释放锁,这样是一个锁的错误使用,这个问题将在后续的V3.0版本中解决。 针对锁无法释放问题的一个解决方案基于GETSET命令来实现 V1.1 基于GETSET tryLock() { NewExpireTime = CurrentTimestamp + ExpireSeconds if (SETNX Key NewExpireTime Seconds) { oldExpireTime = GET(Key) if (oldExpireTime < CurrentTimestamp) { NewExpireTime = CurrentTimestamp+ExpireSeconds CurrentExpireTime = GETSET(Key,NewExpireTime) if (CurrentExpireTime == oldExpireTime) { return 1; } else { return 0; } } } } release() { DELETE key } 思路: ...

October 14, 2018 · 1 min · 212 words · Bridge Li

【转载】设计 RPC 接口时,你有考虑过这些吗?

按:系统架构经过多年演进,现在越来越多的系统采用微服务架构,而微服务架构最重要的就是面向接口编程,所以接口的设计就尤为重要了,我一直认为一个好的接口自己会说话,也就是看到接口,我就知道这个接口是干啥的、参数是啥、返回值是啥以及可能会遇到哪些问题,但目前对 RPC 接口设计可以说有两派,前一段时间看了一篇文章是我的想法完全一样,特转载到本人博客,希望更多的能够看到、有更多的人参与讨论两种的优劣。 在开始之前呢,先吐槽一个本文没有提到的问题,我不知道有些人是怎么想的,对外暴露的接口,也就是最终被打成 jar 包供外部服务依赖模块,有些人喜欢在里面引入各种无关的第三方依赖,我遇到过把 spring mvc、spring、mybatis、dubbo 等等还有其他的像 POI 什么乱七八糟的第三方 jar 都依赖进来的,说实话,我只想问:可以说脏话吗?不可以啊,那好吧,我无话可说了,我们开始看原文吧。 RPC 框架的讨论一直是各个技术交流群中的热点话题,阿里的 dubbo,新浪微博的 motan,谷歌的 grpc,以及不久前蚂蚁金服开源的 sofa,都是比较出名的 RPC 框架。RPC 框架,或者一部分人习惯称之为服务治理框架,更多的讨论是存在于其技术架构,比如 RPC 的实现原理,RPC 各个分层的意义,具体 RPC 框架的源码分析…但却并没有太多话题和“如何设计 RPC 接口”这样的业务架构相关。 可能很多小公司程序员还是比较关心这个问题的,这篇文章主要分享下一些个人眼中 RPC 接口设计的最佳实践。 初识 RPC 接口设计 由于 RPC 中的术语每个程序员的理解可能不同,所以文章开始,先统一下 RPC 术语,方便后续阐述。 大家都知道共享接口是 RPC 最典型的一个特点,每个服务对外暴露自己的接口,该模块一般称之为 api;外部模块想要实现对该模块的远程调用,则需要依赖其 api;每个服务都需要有一个应用来负责实现自己的 api,一般体现为一个独立的进程,该模块一般称之为 app。 api 和 app 是构建微服务项目的最简单组成部分,如果使用 maven 的多 module 组织代码,则体现为如下的形式。 serviceA 服务 serviceA/pom.xml 定义父 pom 文件 <modules> <module>serviceA-api</module> <module>serviceA-app</module> </modules> <packaging>pom</packaging> <groupId>moe.cnkirito</groupId> <artifactId>serviceA</artifactId> <version>1.0.0-SNAPSHOT</version> serviceA/serviceA-api/pom.xml 定义对外暴露的接口,最终会被打成 jar 包供外部服务依赖 ...

September 2, 2018 · 3 min · 635 words · Bridge Li

关于 tomcat 排查错误的一个小小感悟

前几天响应公司的要求,系统日志接入公司的 ELK,按照中间件的同学要求之后,果然不出意外的遇到了问题,项目跑不起来了,控制台 catalina.out 打印日志如下: Aug 16, 2018 10:02:21 AM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["http-apr-8144"] Aug 16, 2018 10:02:21 AM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["ajp-apr-58144"] Aug 16, 2018 10:02:21 AM org.apache.catalina.startup.Catalina start INFO: Server startup in 28819 ms Aug 16, 2018 10:02:23 AM org.apache.catalina.loader.WebappClassLoaderBase loadClass INFO: Illegal access: this web application instance has been stopped already. Could not load com.alibaba.rocketmq.shade.io.netty.util.concurren t.DefaultPromise$2. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate t he thread which caused the illegal access, and has no functional impact. java.lang.IllegalStateException at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1743) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1701) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:590) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:398) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:151) at java.lang.Thread.run(Thread.java:745) Exception in thread "NettyClientWorkerThread_3" java.lang.NoClassDefFoundError: com/alibaba/rocketmq/shade/io/netty/util/concurrent/DefaultPromi se$2 at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:590) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:398) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:151) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.ClassNotFoundException: com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise$2 at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1858) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1701) &#8230; 4 more Aug 16, 2018 10:02:23 AM org.apache.catalina.loader.WebappClassLoaderBase loadClass INFO: Illegal access: this web application instance has been stopped already. Could not load com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise$2. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact. java.lang.IllegalStateException at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1743) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1701) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:590) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:398) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:151) at java.lang.Thread.run(Thread.java:745) Exception in thread "NettyClientWorkerThread_4" java.lang.NoClassDefFoundError: com/alibaba/rocketmq/shade/io/netty/util/concurrent/DefaultPromise$2 at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:590) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:398) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:151) at java.lang.Thread.run(Thread.java:745) Exception in thread "NettyClientWorkerThread_2" Exception in thread "NettyClientWorkerThread_1" java.lang.NoClassDefFoundError: com/alibaba/rocketmq/shade/io/netty/util/concurrent/DefaultPromise$2 at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:590) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:398) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:151) at java.lang.Thread.run(Thread.java:745) java.lang.NoClassDefFoundError: com/alibaba/rocketmq/shade/io/netty/util/concurrent/DefaultPromise$2 at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:590) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:398) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:151) at java.lang.Thread.run(Thread.java:745) Exception in thread "NettyClientSelector_1" java.lang.NoClassDefFoundError: com/alibaba/rocketmq/shade/io/netty/util/concurrent/DefaultPromise$2 at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:590) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:398) at com.alibaba.rocketmq.shade.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:151) at java.lang.Thread.run(Thread.java:745) Aug 16, 2018 10:02:28 AM org.apache.catalina.loader.WebappClassLoaderBase loadClass 很常见的一个错,java.lang.NoClassDefFoundError,找不到 com/alibaba/rocketmq/shade/io/netty/util/concurrent/DefaultPromise,但是不应该啊,因为什么都没有修改,之前都是跑的好好地,怎么会突然找不到这个类,莫名其妙,有同事说,是不是修改 jar 的版本之类的,不过我确实没有修改,只是引入了公司 ELK 相关的 jar 而已,而且看了一下这个类在 classpath 下是存在的,后来经同事提醒,这个地方可能不是真正的报错的地方,看一下 tomcat 的 localhost 日志,果然在发现了如下的报错: ...

August 17, 2018 · 2 min · 387 words · Bridge Li

JVM 群关于 Autowired 的讨论

前一段时间 JVM 群有人遇到了一个 stackoverflow 的问题,引发了一个关于 Autowired 的讨论,由于我做的项目可能比较小,并没有遇到过,但感觉这也许就是一个坑,记录下来 ,如果谁有遇到这个问题,说不定就有帮助。 下面我会贴出来群里面的讨论,如果不想看,直接看我的得出的结论,所以 TL;DR 版: spring 中依赖注入有两个注解:Autowired 和 Resource。Resource 的注入的时候是 byName,而 Autowired 注入的时候是 byType,所以平时并没有很大的区别,但 Autowired 和 getBean(Object.class) 会导致栈很深,有可能会导致 stackoverflow,所以如果遇到这个栈很深,不使用 Autowired 会缓解一下,也就是根据我的理解,在项目中能用 Resource 还是用 Resource 比较好。 原版群里的详细讨论如下图(至于深层次的原因,大家可以根据源码自己跟进看一下): 里面 深圳-随缘-颉 贴出的一张图: 感谢这一群小伙伴,如果有信息泄漏,很抱歉。 另外曾经有朋友因为 JVM 的存在,就认为 Java 没有内存泄漏的问题,这是对 Java 有多大的误解啊。

July 29, 2018 · 1 min · 43 words · Bridge Li

Markdown 基本语法介绍

Markdown 是我很喜欢的一个轻量级标记语言,但也因为不常写,所以有些语法记得不是很清楚,经常写的时候需要查一些资料,所以这次就把一些简单的常用的语法做个笔记。 在介绍 markdown 语法之前,先写一点废话。 一. markdown是什么? 简单的一句话就是,Markdown 可谓是程序员必备的一种写作格式!你还在用 word 写文档么?简直 low 爆了,赶紧抛弃,从现在开始,立刻,马上,学习下 markdown。 二. markdown有什么好处? 简单说,语法简单、再也不用专注排版、兼容 html、还有其他的的很多很强大的功能(这么厉害,你的博客为啥不用?因为 WordPress 原生编辑器不支持 markdown,也一直没有安装第三方的插件,所以就没有) 三. markdown 编辑器有哪些? 个人最喜欢的开发工具是,GitHub 出品的 Atom,自带提示;之前也在 Windows 下用过 markdownpad,也还行,mac 下有很多人推荐 mou,另外据说 Sublime 也不错,还有一些在线工具据说也不错。 四. markdown 语法 标题 1 到 6:#1 到 #6 代码示例: \# 标题一 \### 标题三 区块:> 代码示例: > 这是区块 > > 第二行区块 斜体:*斜体* 代码示例: \*斜体\* 加粗:**加粗** 代码示例: \*\*该部分加粗\*\* 删除线:删除线 示例代码: ~~这是加删除线的文字~~ 换行和分段 换行:只需在行末加两个空格键和一个回车键即可换行。快捷键:control + 回车键 分段:段落之间空一行即可 ...

July 15, 2018 · 1 min · 196 words · Bridge Li

Git 配置多个用户身份和强制检查各个项目用户名邮箱设置

今天的文章比较简单,1. 就是为 Git 单个项目做身份配置,就是配置单独的邮箱和用户名。因为我们平时可能会在不同的几个项目中工作,各个项目的用户名可能不同,最基本的就是公司的项目和我们自己在 GitHub 上玩,所以为了保证日志的准确性和提交时无误,最好对各个项目设置。以前没有研究过,所以就一只默认用公司的用户名玩,但一直感觉不太好,2. 在提交时,user.name, user.email会进入日志。这些信息,是追踪代码变更的关键,所以必须配置,偶然看见秋大有篇文章写这个,试了一些不错,记录一下。 全局配置和项目配置 全局配置信息在: ~/.gitconfig 项目配置在项目目录下的: ./.git/config 配置多个用户身份 git config –global 操作全局配置, 不带 –global 选项的话,会尝试相对于当前目录下找:./git/config, 找不到的话,报错,所以如此一来,我们就可以: \# for global setting git config &#8211;global user.name xxx git config &#8211;global user.email xxx@xxx.com \# for repository git config user.name xxxx git config user.email xxxx@xxx.com 另,我们都知道 Linux 下,我们可以通过 alias 命令设置别名(之前一直就不住这个命令,每次都是查一下,后来一朋友说多好记啊 ali as,阿里 as,就再也忘不了了),我们可以通过一个短命令把 git 日志重新格式化一下,至于其他的像:git status,git commit 是否重命名就看习惯了(看过有人把常错的单词都重命名为正确的,省时间,机智) git config &#8211;global alias.lg "log &#8211;color &#8211;graph &#8211;pretty=format:&#8217;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset&#8217; &#8211;abbrev-commit &#8211;" 强制检查各个项目用户名邮箱设置 使用 pre-commit 钩子进行检查,所以在 .git/hooks 中添加一个 pre-commit 文件(注意权限),内容如下: ...

July 1, 2018 · 1 min · 176 words · Bridge Li

org.apache.ibatis.builder.IncompleteElementException: Could not find parameter map

上周和同事一块开发一个功能模块,在开发中拉下来同事代码,在测试的时候,突然跑不通了,报错信息如下: org.apache.ibatis.builder.IncompleteElementException: Could not find parameter map java.util.Map at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementParameterMap(MapperBuilderAssistant.java:320) at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:296) at org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode(XMLStatementBuilder.java:109) at org.apache.ibatis.session.Configuration.buildAllStatements(Configuration.java:753) at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:723) at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:718) at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:201) at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:48) at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:59) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52) at com.sun.proxy.$Proxy40.insertSelective(Unknown Source) at com.weidai.urge.service.disposition.BidDispositionOrderServiceTest.testInsertSelective(BidDispositionOrderServiceTest.java:48) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) Caused by: java.lang.IllegalArgumentException: Parameter Maps collection does not contain value for java.util.Map at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:853) at org.apache.ibatis.session.Configuration.getParameterMap(Configuration.java:625) at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementParameterMap(MapperBuilderAssistant.java:318) &#8230; 39 more 看报错信息,也就是自己跑一个 junit test,测试批量插入,突然他就不行了,再看看自己写的批量插入没问题啊,我也没用 map,感觉好奇怪,就网上搜了一下这个问题,原来确实有问题,也确实在这个配置文件中,提示的错误也对,就是提示的位置不对。mybatis 中只要有任何一个地方报错,都无法通过。最后搜了一下发现是刚刚来下来的代码,同事新增了一个方法上将 parameterType 写成了 parameterMap 了 ...

June 2, 2018 · 1 min · 153 words · Bridge Li