java开发暗坑记录

回顾自己程序员生涯中踩过的那些坑:
1,一开始的时候抱着什么都不会有人肯招就去的心态去了一家很小的传统软件公司,是写高校后台系统的,就是学生审批,成绩之类的学工系统。当时遇到一个需求是计算学生的绩点,你能想象我是蠢到一个学生学号去数据库查数据然后for循环N次吗?,当然直接慢到超时了,然后项目经理一个30多岁的大姐姐看了一眼后告诉了我人生中第一条写代码规则:别在for循环里一遍一遍查数据库!一开始我并不理解,只是当成准则记在心里,觉得可能是这样效率会很差?为什么会差呢?不知道。直到后来面试的时候别人问我你写代码的时候遇到过什么难关吗?我就说了这个,然后面试官当时就急了,怎么会只是效率差?这样数据库连接就....。当然不用想这家我肯定面试不过,太差了,我自己现在想想都太差了。

2,还是那家传统软件公司,还是统计学生学分绩点那个需求,要做排名还有数据导出,当时好像印象中超时时间是7秒还是几秒,然后学生的成绩数据在视图里有40几万吧,但超过一千个学生就各种慢了,反正要1-2分钟时间的样子,当时是死活没有解决办法,我就向项目经理提议干脆写个存储过程吧?一改或存成绩就计算后存到单独的结果表里,不要实时计算了(抱歉当时自己还没有定时任务的概念,简直太差了自己),然后小姐姐还是看了一眼就说:别搞这么复杂,前端做限制最多只能导出1000学生就可以了。
好吧,问题解决了---》能用设计解决的问题别用技术为难自己,这跟后面一个坑几乎是一样的。

3,第二家公司终于像点样子了,阿里系的互联网公司,分布式架构,Dubbo,SpringBoot,Velocity,react全家桶, .....等等各种技术像万花筒一样展现在我的面前,让我意识到自己是多么落后和孤陋寡闻,我像海绵一样在不断学习,不断接触最新技术。希望自己能赶上别的程序员直到来到现在的公司。当时做的一个数据上传系统,我记得产品和开发经理讨论的时候差点打起来了,为了解决数据一致性和服务降级,做了类似2一样的设计--》全局锁(这怎么说呢?当我看到石墨文档可以几个人同时编辑一个文档的时候我都惊呆了,但后来发现一保存就数据丢失,只保留某个人的提交数据。果然没有这么简单,想想连阿里都没办法解决这个问题也是没谁了,编辑文档时锁定只能一个人编辑,其他人没法编辑果然才是最后的解决办法,当然也可能是我太差,眼界不高吧)

4,上述说到现在公司,现在的公司是一家互联网创业企业,当初是被SpringCloud等技术吸引来的,进来后才发现果然人外有人,天外有天,你能想象毕业两年的架构师吗,能想象人家10年前就接触领域驱动设计了吗?能想象人家光书都买了好几千的吗?看看自己两年连本《Thinking in Java》都没看完,至今连一本书都没买过,都是蹭老婆的大学教材,什么《数据库结构》,《Java面对对象编程》之类的草草看看就不禁惭愧不已。于是一咬牙趁着京东半价买了200多的书,发奋学习。。。好吧跑偏了,回到正题。这次是一个重构需求,其中的权限控制模块因为我在上家公司写过权限中间件就分配给我了,写crud就花了不到两天时间搞完了,然后就是各种磨产品写业务校验,花了两个星期终于差不多交工了,突然问了一句权限范围做了没?(其中有个部分负责人角色要求只能看自己部门的信息)瞬间脑仁疼了,我这权限模块倒是没这权限范围问题,其他模块就蛋疼了啊,然后又是花了一天时间讨论,产品最后妥协给出了角色写死,不做权限范围控制的方案。这次真是的血的教训啊,延期不说,辛苦写了两个星期的代码瞬间无用了,写本文的时候正是加班改权限模块的时候,刚好看到同事在写简书,于是刚好把自己这些年来踩的几个小坑总结一下,当然水的很,第一次写,若干年后再回过头来看应该也会觉得幼稚吧。
此致

最容易碰到的就是SQL报错然后花半天排查不出来,明明复制SQL在navicat上能执行,但在项目就死活报错,要不就是空格特殊字符这种低级错误,好吧干货没多少,就这里简单记录一下,
1.批量插入时如果不是在代码里指定创建时间而是用now()函数会导致一批数据创建时间一样,进而导致分页按创建时间排序出现错误--》解决办法:代码new Date()生成批处理的创建时间不要用SQL函数now()
2.注意<foreach>标签是否带括号,下面这段代码两个<foreach>标签的区别浪费老子半天时间(这就是复制粘贴的缺点):

  UPDATE table
        SET order = CASE ID
        <foreach item="menu" index="index" collection="menus">
            WHEN #{menu.id} THEN #{menu.order}
        </foreach>
        END ,MODIFY_TIME = now()
        WHERE
        ID IN
        <foreach item="menu" index="index" collection="menus" open="("
                 separator="," close=")">#{menu.id}
        </foreach>

3.开发前一定确认好需求,并考虑后续升级方便再动工,返工是很伤人的
4.数据库乐观锁一定要有异常解锁机制,别造成锁一直解不掉的问题
5.出于方便部署后查看服务状态的考虑,可以加上test方法,部署好访问test接口返回HelloWorld就好,上线前删掉
6.swagger文档上线一定要关掉
7.如果想直接使用接口功能不用前端的话可以用swagger的接口调试功能实现
8.只要能远程生产服务器(堡垒机或直接远程都可以),就不用再开向日葵(国产远程桌面软件,非常好用,强烈推荐,再不用担心恶心的TeamViewer报检测为商业用途了)或TeamViewer去上传jar包到邮箱再上传服务器这么恶心了,随便上传到OSS设为公共读后将url在远程命令页面wget一下就把jar之类的资源上传到生产服务器了,看数据库也可以用命令操作,具体看另一篇文章。
9.需要https最好是买个负载均衡(不贵几十块钱)配在负载均衡上然后转发到后端服务,不要用网关来代替,非常蠢,很多坑
10.Feign调用接口时,返回值没有也最好用Result<Void>指定返回对象类型而不是Result或Result<?>,因为fastjson有坑会报错,具体参考这篇博文:fastjson的坑
11.需要实时更新前端数据的最方便快速的做法是前端轮询调用接口,而不是用websocket,坑很多,看到同事用websocket一堆bug真是怕了
12.不要一味追求新技术,新技术代表的是新特性是很好用但文档少,后期维护不方便等也要做好准备,就像webfulx,一堆坑,同事发现解决不了后又换回springMVC了,很多技术往往不是不好用而是不会用,所以在确定自己能用好前不要在生产环境用自己不熟悉的新技术,学习成本很高的
13.git文件是隐藏的,所以需要将复制的代码重新上传到个新项目的话要把Windows隐藏文件夹查看打开删掉.git文件夹再重新上传git
14.调用第三方系统时,最好通过接口实现而不是直接改库,有很多暗坑
15.注意mybatis调用返回对象的构造函数,如果有空构造函数会返回一堆null对象导致npe,如果SQL返回没有构造函数的参数会报
No constructor found in (# MyBatis小问题(1)-Mapper中错误No constructor found...

16.用swagger UI 做页面写了一个上传的接口给别人用,过了一段时间居然报这个错:

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-datarequest failed. /tmp/tomcat.4251146331506026853.80/work/Tomcat/localhost/ROOT/upload_5b3f21c2_d1a2_4984_8ee6_25e0f1e51be4_00000002.tmp (No such file or directory) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:165) at org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:142) at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1099) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:932) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:105) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:107) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:522) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Caused by: org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed./tmp/tomcat.4251146331506026853.80/work/Tomcat/localhost/ROOT/upload_5b3f21c2_d1a2_4984_8ee6_25e0f1e51be4_00000002.tmp (No such file or directory) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:351) at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115) at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:158) ... 46 more Caused by: java.io.FileNotFoundException: /tmp/tomcat.4251146331506026853.80/work/Tomcat/localhost/ROOT/upload_5b3f21c2_d1a2_4984_8ee6_25e0f1e51be4_00000002.tmp (No such file or directory) at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(FileOutputStream.java:270) at java.io.FileOutputStream.<init>(FileOutputStream.java:213) at java.io.FileOutputStream.<init>(FileOutputStream.java:162) at org.apache.commons.io.output.DeferredFileOutputStream.thresholdReached(DeferredFileOutputStream.java:178) at org.apache.commons.io.output.ThresholdingOutputStream.checkThreshold(ThresholdingOutputStream.java:224) at org.apache.commons.io.output.ThresholdingOutputStream.write(ThresholdingOutputStream.java:128) at org.apache.commons.fileupload.util.Streams.copy(Streams.java:107) at org.apache.commons.fileupload.util.Streams.copy(Streams.java:70) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:347) ... 48 more

1、检查bean:

<!-- 配置上传文件的组件 id的值必须为“multipartResolver” -->
        <!-- class spring-web  org.springframework.web.multipart.commons -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!-- 配置最大的上传文件10兆 -->
            <property name="maxUploadSize" value="10000000"></property>
            <!-- 设置默认的编码格式 -->
            <property name="defaultEncoding" value="utf-8"></property>
        </bean>

2、检查表单form设置

 <form id="form1" method="POST" enctype="multipart/form-data">

3、控制器方法

@RequestMapping(value = "/upload.shop",headers = "content-type=multipart/*", method = RequestMethod.POST) 

4、检查相关jar包
commons-fileupload/io.jar

根据多方查找,找到了原因,原来是Linux下会自动清除tmp目录下10天没有使用过的文件,SpringBoot启动的时候会在/tmp目录下生成一个Tomcat.*的文件目录,用于"java.io.tmpdir"文件流操作,因为放假期间无人操作,导致Linux系统自动删除了临时文件,所以导致上传报错

解决方案

一、临时方案(快速解决方案,但是不推荐)
重启服务,重启后被删除的tomcat目录会重新生成

二、添加启动配置项(如果你的应用是用脚本启动的,可以考虑)
启动时增加参数-Djava.io.tmpdir=自定义目录

三、添加文件配置类(添加配置类,可以考虑)

@Bean
 MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    factory.setLocation("/var/tmp");
    return factory.createMultipartConfig();
}

四、修改tmpwatch 删除文件的逻辑(修改了系统,不推荐)
tmpwatch 删除文件的逻辑

五、修改application.yml配置文件(推荐)

设置文件临时存储路径
spring.http.multipart.location = /var/tmp

原文地址:https://somta.com.cn/#/blog/view/ef507e4e6e28434d9787ec715d406491

17.sql报错:

org.springframework.jdbc.UncategorizedSQLException: 
Error updating database. Cause: java.sql.SQLException: sql injection violation, syntax error: ERROR. token : WHERE, pos : 315 

SQL多了一个逗号;
关键看token后面,这里通过token可以直接定位报错地点;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容