• 狗屎的Java规范


    规范

    标题真有点侮辱了狗。

    最近做Java,C#与Java对比笔记: http://www.cnblogs.com/newsea/p/4839540.html

    其实Java语法弱点就弱点,关键是Java程序员思想太保守,先讲湿猴定律: http://baike.baidu.com/link?url=loP9q4bz-T14pQ0y_sa9nZDDFyAjI_eySEHXtyBuB2mRgybuQLyLiKsc-1Tnkq0Vy0f-OYpaHpFMcN0C9XT3_a

    贴内容:

    把五只猴子关在一个笼子里,上头有一串香蕉实验人员装了一个自动装置。
    一旦侦测到有猴子要去拿香蕉,马上就会有水喷向笼子,而这五只猴子都会一身湿。
    首先有只猴子想去拿香蕉,当然,结果就是每只猴子都淋湿了。
    之后每只猴子在几次的尝试后,发现莫不如此。
    于是猴子们达到一个共识:不要去拿香蕉,以避免被水喷到。
    后来实验人员把其中的一只猴子释放,换进去一只新猴子A。
    这只猴子A看到香蕉,马上想要去拿。
    结果,被其他四只猴子海K了一顿。
    因为其他四只猴子认为猴子A会害他们被水淋到,所以制止他去拿香蕉,A尝试了几次,虽被打的满头包,依然没有拿到香蕉。
    当然,这五只猴子就没有被水喷到。
    后来实验人员再把一只旧猴子释放,换上另外一只新猴子B。
    这猴子B看到香蕉,也是迫不及待要去拿。
    当然,一如刚才所发生的情形,其他四只猴子海K了B一顿。
    特别的是,那只A猴子打的特别用力(这叫老兵欺负新兵,或是媳妇熬成婆^O^)。
    B猴子试了几次总是被打的很惨,只好作罢。
    后来慢慢的一只一只的,所有的旧猴子都换成新猴子了,大家都不敢去动那香蕉。
    但是他们都不知道为什么,只知道去动香蕉会被猴扁。
    这就是道德的起源。

    写这篇文章,主要是在接触Java之后,有一些感想。但对我震撼最大的莫过于Java程序员的思想束缚。

    1. Java很老,很多规范是在N年前就由一帮外国的老学究定下的。现在的猴子一直在遵守,很少有人去打破,他们发现一旦打破,程序就跑不起来了。

    2. Java 1.8比 Java 1.6好多了,但我面试的过程中,很多人都在使用 1.6

    3. Lambda对Java程序员来说,就像怪物。很多人仅听说过,没有用过。 

    4. 在年纪大的Java程序员眼中, 新版本是给小白用的,自己不会主动去用。违了Java规范的东西,都是怪物。

    一种约定俗成的东西,形成了规范,但是当这个规范被大众接受,再想溶入新东西,就很难了。

    Java对象序列化

    1. 字段大小写

    引出

    Java定义对象有N多规范,get , set 方法,private 字段。一旦形成规范,才能让映射,Json变的简单一些,同时也意味着,也变的死板。

    Javascript Post Json:

    { Id: 1 , Name:"abc" }

    =>C# Json

    public class Model{
        public int Id { get; set;}
        public String Name {get;set;}
    }

    => Java Json

    public class Model{
        public int Id;
        public String Name;
    }

    在 SpringMvc 里是映射不到的。很多人会先说,要用 get set。

    public class Model {
        private  String Name;  
        public String getName() {
            return Name;
        }
        public void setName(String name) {
            this.Name = name;
        } 
    
        private  String Id;
        public String getId() {
            return Id;
        }
        public void setId(String id) {
            this.Id = id;
        } 
    }

    还是不行,按照Java规范,需要把客户端Post Json 的Key 首字线变成小写。

    规范真是害死人啊。鸡肋的ModelBinder,很多人在这里妥协,要么传递首字母小写,要么传递Json字符串, 万能的字符串。

    破解

    自己实现序列化。

    对枚举进行规范化: 定义的枚举可以和数字相互转换(和C#一致),存储时,枚举保存为 Int,服务器传递到客户端的枚举,客户端传递到服务器端的枚举,都使用 Int。

    如果客户端Post的内容格式是  application/json ,还好说。 直接用 Json反序列化到 HasMap<String,Object> 上,再操作。

    如果客户端Post的内容格式是  url 格式的, 那就需要自己写转换函数。

    接收:

        @RequestMapping(method = RequestMethod.POST, value = "/testModel" )
        @ResponseBody
        public String test() {
            Test test = MyObject.Get(new Test());
            String ret =  JsonMapper.toJsonString(test);
            System.out.println(ret);
            return ret ;
        }

    关键是客户端Post的Json数据格式可能会是以下格式:

    PersonInfo[0].Id=1&PersonIndo[0].CityInfo.Name=北京

    需要把Key变成更精准的层级对象。把Url加载到HashMap中。再进行深层次对象化。

     public static <T> T Get( T defValue) {
            Class cls = defValue.getClass();
            HttpServletRequest request = HttpContext.getRequest();
            MapModel map = new MapModel();
            String result = "";
            try {
                BufferedReader inputStream = new BufferedReader(new InputStreamReader(request.getInputStream()));
    
                String line;
                while ((line = inputStream.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            if (request.getContentType().indexOf("application/json") >= 0) {
                map.Add(JsonMapper.fromJsonString(result, MapModel.class));
            } else {
                map.Add(MapModel.LoadFromUrl(result));
            }
    
            map.Add(MapModel.LoadFromUrl(request.getQueryString()));
    
            for (Field f : cls.getDeclaredFields()) {
                Object val = map.get(f.getName());
                if (val == null) continue;
    
                Class type = f.getType();
                if (type.isEnum()) {
                    val = MyEnum.ToEnum(type, MyObject.AsString(val));
                } else if (type.isAssignableFrom(Integer.class) || type.isAssignableFrom(int.class)) {
                    val = MyObject.AsInt(val);
                }
                else if( HashMap.class.isAssignableFrom(type)){
                    val = ToMap(val);
                }
                else if( IsSimpleType(type) == false){
                    try {
                        val = FromMap(ToMap(val), f.get(defValue));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
    
                try {
                    f.setAccessible(true);
                    f.set(defValue, val);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return defValue;
        }
    public class MapModel extends HashMap<String, Object> {
    
        public void Add(MapModel other) {
            if (other == null) return;
    
            for (String key : other.keySet()) {
                this.put(key, other.get(key));
            }
        }
    
        public static MapModel LoadFromUrl(String UrlQuery) {
            MapModel ret = new MapModel();
    
            List<String> list = MyString.MySplit(UrlQuery, '&');
            for (String item : list) {
    
                List<String> kv = MyString.MySplit(item, '=');
                ret.Tourch(kv.get(0), kv.get(1));
            }
    
            return ret;
        }
    
        public void Tourch(String KeyPath, String Value) {
            if (this.containsKey(KeyPath)) return;
    
            int sepIndex = GetNextCharIndex_SkipQuotes(KeyPath, 0, '.', '[');
            if (sepIndex >= KeyPath.length()) {
                this.put(KeyPath, Value);
                return;
            }
    
            char chr = KeyPath.charAt(sepIndex);
    
            String objKey = KeyPath.substring(0, sepIndex);
    
            if (chr == '.') {
                if (this.containsKey(objKey) == false) {
                    this.put(objKey, new MapModel());
                }
    
                MapModel vv = (MapModel) this.get(objKey);
                vv.Tourch(KeyPath.substring(sepIndex + 1), Value);
            } else {
                if (this.containsKey(objKey) == false) {
                    this.put(objKey, new ArrayList<Object>());
                }
    
                List<Object> list = (List<Object>) this.get(objKey);
    
                int nextDotIndex = KeyPath.indexOf('.', sepIndex + 1);
                if (nextDotIndex < 0) {
                    nextDotIndex = KeyPath.length();
                }
    
                List<String> aryIndexs_Strings = MySplit(TrimWithPair(Slice(KeyPath, sepIndex, nextDotIndex).replace(" ", "").replace("][", ","), "[", "]"), ',');
                List<Integer> aryIndexs = new ArrayList<Integer>();
                for (String k : aryIndexs_Strings) {
                    aryIndexs.add(MyObject.AsInt(k));
                }
    
    
                MapModel vv = (MapModel) PatchArrayLevels(list, aryIndexs, Value, KeyPath.indexOf('.', sepIndex + 1) > 0, 0);
    
                if (vv != null) {
                    vv.Tourch(Slice(KeyPath, nextDotIndex + 1), Value);
                    return;
                }
            }
        }
    
        /// <summary>
        /// a[0][0][0].Id = 1 , 则创建3级数组,返回 字典
        /// </summary>
        /// <param name="list"></param>
        /// <param name="indexs"></param>
        /// <param name="Value"></param>
        /// <param name="NextIsDict">下一个对象是否是字典。</param>
        /// <param name="level"></param>
        /// <returns></returns>
        private static Object PatchArrayLevels(List<Object> list, List<Integer> indexs, String Value, boolean NextIsDict, int level) {
            int index = indexs.get(level);
            if (level >= (indexs.size() - 1)) {
                if (NextIsDict) {
                    for (int i = list.size(); i <= index; i++) {
                        list.add(new MapModel());
                    }
                    list.set(index, new MapModel());
                    return list.get(index);
                } else {
                    for (int i = list.size(); i <= index; i++) {
                        list.add(null);
                    }
                    list.set(index, Value);
                    return null;
                }
            }
    
    
            for (int i = list.size(); i <= index; i++) {
                list.add(new ArrayList<Object>());
            }
    
            return PatchArrayLevels((List<Object>) list.get(index), indexs, Value, NextIsDict, level + 1);
        }
    }

    具体实现参考开源项目的实现,项目地址: http://code.taobao.org/svn/MyJavaMvc

    2. 属性名

    1. 狗B的Java到底做了什么 , 为什么实体属性是 isAdmin : Boolean ,客户端会返回 admin : Boolean

    2. 为什么SB的 Mongo驱动,会把 集合里的 id 变为 _id

    3. 最后一个SB的坑。 前端Post如下数据:

    cartIds[0].id:596713322b3fe4306a3a60f7
    cartIds[0].number:10000
    cartIds[0].amount:30000

      后端来接收:(Kotlin语法,和Java执行原理一样)

      data class abc(var cartIds: Array<CommitOrderDataItem> = arrayOf()){}
    
        @ApiOperation(value = "生成订单")
        @JsonpMapping("/toOrder")
        fun toOrder(@ApiParam("购物车中的id,number,amount的集合") abc:abc ){
    
    
        //再取出来。
        var cartIds = abc.cartIds;      
    }

    3. 依赖

    文件上传,使用 CommonsMultipartResolver  不报错, 编译不报错, 运行时报错。 添加以下依赖解决了。 

    <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
    </dependency>

     Java就是狗屎  !!!

    4.   @WebFilter 和   @Configuration 冲突。

    在 Get 请求时,会执行两次 filter

      

  • 相关阅读:
    [mysql]增加域设置 auto_increment
    【mysql乱码】解决php中向mysql插入中文数据乱码的问题
    WIN7 嵌入式系统安装教程 Windows Embedded Standard 2011 安装
    STM32F4 串口实验中收不到超级终端发送的数据,调试工具却可以
    STM32F4 输入输出(GPIO)模式理解
    STM32——GPIO之从库函数到寄存器的前因后果
    STM32 下的库函数和寄存器操作比较
    JLINK(SEGGER)灯不亮 USB不识别固件修复、clone修改
    lwip Light Weight (轻型)IP协议
    stm32开发之串口的调试
  • 原文地址:https://www.cnblogs.com/newsea/p/5010714.html
Copyright © 2020-2023  润新知