使用ofbiz三年了,今天遇见了一个“大坑”

先来说说大坑的前世,由于开发微信小程序用到了上传图片的方法,当然得前后端配合了。后台接口调用的是文件上传的工具类,此工具类在项目中用了有一段时间了,没有发现任何问题。上传文件嘛,相信有经验的程序员都一定很熟悉了,但是同样的接口,pc端调用上传文图没问题,小程序端调用就获取不到图片流。思路如下:
1.小程序api文档没有看清楚?仔细研究小程序api文档,查询各种关于小程序上传图片的资料,无果
2.难道是后台接口不通用吗?查询资料,网上大多是用的spring来写的。但是这跟框架关系不大
3.ofbiz的问题,终于要静下心来,慢慢的解决这个问题。
容小弟喝口水,压压惊,慢慢道来……,分析问题,后台接收不到数据,是没有传递过来吗?带着这个疑问,我用真机测试,控制台log发现,request-headers里面的content-length是有值的,而且每次上传不同图片值的大小不同,这就说明前台图片一定是传递过去了。那么接下来,就是后台的事儿了,以前用spring的时候,记得出现过类似的问题,就是后台拿不到参数,但是前台确实是传过来了,就是因为servlet容器里面,已经解析过一遍了,所以第二次解析的时候,会拿不到数据。抱着这个想法,我看到,web.xml配置里面的

org.apache.ofbiz.webapp.control.ControlServlet

在这个servlet方法中requestHandler.doRequest(request, response, null, userLogin, delegator);,在doRequest方法中有一个checkLoginReturnString = this.runEvent(request, response, checkLoginEvent, null, “security-auth”);
我们继续往下看:

 public String runEvent(HttpServletRequest request, HttpServletResponse response,ConfigXMLReader.Event event, ConfigXMLReader.RequestMap requestMap, String trigger) throws EventHandlerException {EventHandler eventHandler = eventFactory.getEventHandler(event.type);String eventReturn = eventHandler.invoke(event, requestMap, request, response);if (Debug.verboseOn() || (Debug.infoOn() && "request".equals(trigger))) Debug.logInfo("Ran Event [" + event.type + ":" + event.path + "#" + event.invoke + "] from [" + trigger + "], result is [" + eventReturn + "]", module);return eventReturn;}

这个方法是用来判断当前请求的事件类型,具体的事件类型只要分为以下9类:Groovy、Java、Rome、SOAP、Script、Service、ServiceMulti、Simple、XmlRpc,不同的时间类型对应不同的处理器,分别是:GroovyEventHandler、JavaEventHandler、RomeEventHandler、SOAPEventHandler、ScriptEventHandler、ServiceEventHandler、ServiceMultiEventHandler、SimpleEventHandler、XmlRpcEventHandler,关键的点就在这了,通过debug发现,pc调用上传图片接口时,事件类型全部都是java,由于小程序需要验证用户身份token,所以我自定义了一个service,而pc验证用户身份的是LoginWorker,是一个java事件,所以走的是JavaEventHandler,而我这个则用的是ServiceEventHandler,打开ServiceEventHandler才发现了问题的出现的真正原因,下面我把ServiceEventHandler代码贴出来:

boolean isMultiPart = ServletFileUpload.isMultipartContent(request);Map<String, Object> multiPartMap = new HashMap<String, Object>();if (isMultiPart) {// get the http upload configurationString maxSizeStr = EntityUtilProperties.getPropertyValue("general", "http.upload.max.size", "-1", dctx.getDelegator());long maxUploadSize = -1;try {maxUploadSize = Long.parseLong(maxSizeStr);} catch (NumberFormatException e) {Debug.logError(e, "Unable to obtain the max upload size from general.properties; using default -1", module);maxUploadSize = -1;}// get the http size threshold configuration - files bigger than this will be// temporarly stored on disk during uploadString sizeThresholdStr = EntityUtilProperties.getPropertyValue("general", "http.upload.max.sizethreshold", "10240", dctx.getDelegator());int sizeThreshold = 10240; // 10Ktry {sizeThreshold = Integer.parseInt(sizeThresholdStr);} catch (NumberFormatException e) {Debug.logError(e, "Unable to obtain the threshold size from general.properties; using default 10K", module);sizeThreshold = -1;}// directory used to temporarily store files that are larger than the configured size thresholdString tmpUploadRepository = EntityUtilProperties.getPropertyValue("general", "http.upload.tmprepository", "runtime/tmp", dctx.getDelegator());String encoding = request.getCharacterEncoding();// check for multipart content types which may have uploaded itemsServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory(sizeThreshold, new File(tmpUploadRepository)));// create the progress listener and add it to the sessionFileUploadProgressListener listener = new FileUploadProgressListener();upload.setProgressListener(listener);session.setAttribute("uploadProgressListener", listener);if (encoding != null) {upload.setHeaderEncoding(encoding);}upload.setSizeMax(maxUploadSize);List<FileItem> uploadedItems = null;try {uploadedItems = UtilGenerics.<FileItem>checkList(upload.parseRequest(request));} catch (FileUploadException e) {throw new EventHandlerException("Problems reading uploaded data", e);}if (uploadedItems != null) {for (FileItem item: uploadedItems) {String fieldName = item.getFieldName();//byte[] itemBytes = item.get();/*Debug.logInfo("Item Info [" + fieldName + "] : " + item.getName() + " / " + item.getSize() + " / " +item.getContentType() + " FF: " + item.isFormField(), module);*/if (item.isFormField() || item.getName() == null) {if (multiPartMap.containsKey(fieldName)) {Object mapValue = multiPartMap.get(fieldName);if (mapValue instanceof List<?>) {checkList(mapValue, Object.class).add(item.getString());} else if (mapValue instanceof String) {List<String> newList = new LinkedList<String>();newList.add((String) mapValue);newList.add(item.getString());multiPartMap.put(fieldName, newList);} else {Debug.logWarning("Form field found [" + fieldName + "] which was not handled!", module);}} else {if (encoding != null) {try {multiPartMap.put(fieldName, item.getString(encoding));} catch (java.io.UnsupportedEncodingException uee) {Debug.logError(uee, "Unsupported Encoding, using deafault", module);multiPartMap.put(fieldName, item.getString());}} else {multiPartMap.put(fieldName, item.getString());}}} else {String fileName = item.getName();if (fileName.indexOf('\\') > -1 || fileName.indexOf('/') > -1) {// get just the file name IE and other browsers also pass in the local pathint lastIndex = fileName.lastIndexOf('\\');if (lastIndex == -1) {lastIndex = fileName.lastIndexOf('/');}if (lastIndex > -1) {fileName = fileName.substring(lastIndex + 1);}}multiPartMap.put(fieldName, ByteBuffer.wrap(item.get()));multiPartMap.put("_" + fieldName + "_size", Long.valueOf(item.getSize()));multiPartMap.put("_" + fieldName + "_fileName", fileName);multiPartMap.put("_" + fieldName + "_contentType", item.getContentType());}}}}

看到这里我想大家都明白了吧,ServiceEventHandler里面已经判断content-type,当是Multipart-formData的时候,就会读取文件流,将文件存在runtime/tmp目录下,作为临时文件,既然request文件流已经读取一遍了,在我们的方法中自然拿不到数据,问题到这里就已经明白了,最后我把验证token的方法改为java事件类型,测试通过~~。

在这里就不得不说一句了,我没搞明白,为什么要在serviceEventHandler里面进行文件的临时读取,不知道原作者的思路,求明白的大神告知小弟一二,小弟在此先行谢过了

ofbiz使用之---坑一相关推荐

  1. OFBIz gradle构建与运行踩坑

    起源与碎碎念 这几天公司要重构ERP,让我负责去研究主流开源ERP系统.本来让我了解的是python的odoo,但是我对py太不熟练,项目代码的依赖本身也很脆弱,最后倒在了一个 Odoo LINE 1 ...

  2. [CVE-2020-9496]Apache Ofbiz RCE

    参考: Apache Ofbiz RCE (CVE-2020-9496) 漏洞分析 CVE-2020-9496 apache ofbiz xml-rpc反序列化漏洞分析 https://www.zer ...

  3. OFBiz终于起航了

    本人菜鸟,菜得不能再菜得那种,在大佬不厌其烦的指点下终于成功了,真的感谢这个网络时代,信息共享的时代 经过这两天的不断反思总结一个要点吧:如果要装软件,去官网,去读redme,根据redme一步不来, ...

  4. 【golang程序包推荐分享】分享亿点点golang json操作及myJsonMarshal程序包开发的踩坑经历 :)

    目录[阅读时间:约5分钟] 一.概述 1.Json的作用 2.Go官方 encoding/json 包 3. golang json的主要操作 二.Json Marshal:将数据编码成json字符串 ...

  5. java调用clang编译的so_写Java这么久,JDK源码编译过没?编译JDK源码踩坑纪实

    好奇害死羊 很多小伙伴们做Java开发,天天写Java代码,肯定离不开Java基础环境:JDK,毕竟我们写好的Java代码也是跑在JVM虚拟机上. 一般来说,我们学Java之前,第一步就是安装JDK环 ...

  6. flask sqlalchemy踩坑记录

    查询 坑1: 查询不存在返回值不全是None 当使用first().one()等函数进行查询时,如果查询不存在,返回值为None 但是如果使用all().paginate()等函数进行查询是,如果返回 ...

  7. mac git使用与配置踩过的坑

    #mac git使用与配置踩过的坑 标题mac配置git ssh密钥 参考链接mac配置git ssh key go get安装失败的解决方法 go get约等于git clone+go instal ...

  8. 你需要掌握的有关.NET DateTime类型的知识点和坑位 都在这里

    引言    DateTime数据类型是一个复杂的问题,复杂到足以让你在编写[将日期从Web服务器返回到浏览器]简单代码时感到困惑. ASP.NET MVC 5和 Web API 2/ASP.NETCo ...

  9. (转)面试必备技能:JDK动态代理给Spring事务埋下的坑!

    一.场景分析 最近做项目遇到了一个很奇怪的问题,大致的业务场景是这样的:我们首先设定两个事务,事务parent和事务child,在Controller里边同时调用这两个方法,示例代码如下: 1.场景A ...

最新文章

  1. C# 消息处理学习总结
  2. 个人对北理工2020级硕士研究生张××一篇学术论文涉嫌抄袭的看法
  3. 作为团队技术负责人,我是这样面试前端的
  4. linux终端中使用ctrl+c和ctrl+v
  5. JAVA的字节码技术
  6. wince版本ffmpeg的编译 第四篇
  7. Vue 使用 token
  8. 实数范围内(包含负数)的求模与求余运算异同
  9. Dubbo管理控制台dubbo-admin搭建
  10. java 输出helloword
  11. 自动给神经网络找bug,Google发布TensorFuzz
  12. LaTex使用Excel实现快速插入表格
  13. 国内pinterest模式昙花一现 社交电商不该这么玩
  14. 安卓加密视频播放器使用教程
  15. 徐思201771010132《面向对象程序设计(java)》第十五周学习总结
  16. 批量替换 Word 文档前几页
  17. 【May Be DNK】JSON.parse() and JSON.stringify()的两个实用技巧
  18. 基于物联网的智慧农业监测系统(前端界面有web端和微信小程序端)
  19. for和if嵌套使用
  20. Sci-Hub创始人收到苹果的通知:2年前就把她的账户数据给了FBI

热门文章

  1. 再谈CPU使用率100%的问题
  2. linux 麒麟V10 更改磁盘格式ext4-->xfs
  3. 有一台电脑可以做那些副业
  4. Java AWT 布局管理器
  5. 一键搭建微信小程序开发环境 及demo运行(腾讯云上一键搭建node.js服务器环境,PHP,Java,.NET服务类似)
  6. Python实用案例,Python脚本,Python实现批量加水印
  7. PDF批量加水印加密丨Acrobat Pro DC
  8. 高数下|偏导数|高数叔|手写笔记
  9. Spring Boot 第三篇:理解 spring-boot-starter-parent
  10. android.mk是在哪儿,Android.mk基础