标题真有点侮辱了狗。html
最近作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程序员的思想束缚。json
1. Java很老,不少规范是在N年前就由一帮外国的老学究定下的。如今的猴子一直在遵照,不多有人去打破,他们发现一旦打破,程序就跑不起来了。后端
2. Java 1.8比 Java 1.6好多了,但我面试的过程当中,不少人都在使用 1.6数组
3. Lambda对Java程序员来讲,就像怪物。不少人仅据说过,没有用过。 服务器
4. 在年纪大的Java程序员眼中, 新版本是给小白用的,本身不会主动去用。违了Java规范的东西,都是怪物。app
一种约定俗成的东西,造成了规范,可是当这个规范被大众接受,再想溶入新东西,就很难了。svn
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
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; }
文件上传,使用 CommonsMultipartResolver 不报错, 编译不报错, 运行时报错。 添加如下依赖解决了。
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
Java就是狗屎 !!!
4. @WebFilter 和 @Configuration 冲突。
在 Get 请求时,会执行两次 filter