zoukankan      html  css  js  c++  java
  • Struts2 项目 Action 查询结果异常 org.apache.struts2.json.JSONException

    问题描述

    今天进行一个订单管理模块的开发时遇到一个问题:查询的订单时有时会报这个异常:

    org.apache.struts2.json.JSONException: java.lang.IllegalAccessException: 
    Class org.apache.struts2.json.JSONWriter can not access a member of class oracle.jdbc.driver.PhysicalConnection with modifiers "public"

    经过反复测试,发现只要查询结果中的downloadurl这个字段有值就会报错,这在Oracle中是一个Clob字段,里面保存的是一个文件地址的URL。

    解决过程

    网上找资料说是Struts2中Action的属性json序列化的问题,有个博客写的比较清楚,摘录如下:

    异常形式:
    Class org.apache.struts2.json.JSONWriter can not access a member of * 或是 Class com.googlecode.jsonplugin.JSONWriter can not access a member of class*
    第一种是struct2.1.8与json结合时的异常,第二种是struct2.1.6与json结合的异常。
    具体:
    Class org.apache.struts2.json.JSONWriter can not access a member of class Oracle.jdbc.driver.BaseResultSet with modifiers "public"
    解释:
    不能把程序中的某种数据结构串行化成json格式。
    原因:
    struts2的Action里面的数据转换成json数据时,会将提供了get方法的Action属性都串行化为json输出到客户端。有的时候,很多属性并不能串行化成json数据,比如这里的oracle.jdbc.driver.BaseResultSet。这时还进行强行转换就会出现这样的异常。
    解决方法:
    在不能串行化到json的Action属性相应的get方法前加一条json标记 @JSON(serialize=false)。告诉json不需要转化这个属性。或者根本不写这个get方法。
    总结:
    对于不需要在前台输出的json数据,也可以用同样的方法进行处理,从而减少服务器和客户端间交互的信息量。
    可在需要在前台输出的Action属性的get方法前加上@JSON(name="status")标识,从而为该属性起了一个别名,在前台就可以通过status作为属性名来读取其值。

    问题处理

    这是我Action的配置,没有问题:

    <package name="ajax" namespace="/ajax" extends="json-default">
         <action name="*_*" class="com.wdxc.action.{1}Action" method="{2}">
              <result type="json" name="success">
                  <param name="root">result</param>
              </result>
         </action>
    </package>

    我这也是这种类型问题,将查询出来的结果put进Action的属性result,然后result在转json的时候报错了,原因就是result中保存的查询结果中的Clob类型的downloadurl无法进行串行化为json。把查询结果中的downloadurl这个字段进行类型转换成String,(对url编码是防止转换成json的时候url数据丢失的问题),主要代码修改如下:

    List<Map<String,Object>> list = orderService.selectFactoryOrders(map);//查询结果
    for (Map<String, Object> map2 : list) {
        if (map2.get("DOWNLOADURL") != null) {
            System.out.println(map2.get("DOWNLOADURL"));
            //将Clob转化成String
            Clob clob = (Clob)map2.get("DOWNLOADURL");
            String desc = null;
            Reader inStream = clob.getCharacterStream();
            long length = (clob == null) ? 0 : clob.length();
            char[] c = new char[(int) length];
            try {
                inStream.read(c);
                desc = new String(c);
                inStream.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            System.out.println(desc);
            //对String类型的URL进行编码,前台进行相应解码
            map2.put("DOWNLOADURL", URLEncoder.encode(desc,"utf-8"));
        }
    }
    result.put("status", "success");
    result.put("data", list);
    result.put("pageTotal", pageTotal);

    问题解决。

  • 相关阅读:
    [转]UNI-APP开发笔记之使用uni.navigateBack修改上一个页面值
    [转]移动端人员选择的设计思考
    [转]nginx安装及其配置详细教程
    [转]Vue 使用use、prototype自定义自己的全局组件
    [转]uniapp项目运行支付宝小程序,报错:xxx.json中没有申明component: true
    支付宝(钉钉)小程序使用uView控制台报错Cannot read property 'title-all' of undefined
    [转]commonJS规范和require,import区别
    [转]module.exports和export详解
    [转]如何在组件中去使用vuex的值和方法?
    [转]CryptoJS中AES256(CBC)加密算法简单使用
  • 原文地址:https://www.cnblogs.com/wbxk/p/6868828.html
Copyright © 2011-2022 走看看