欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

那些年,我们踩过的技术坑汇总

程序员文章站 2022-06-10 22:10:20
...

title: 那些年,我们踩过的技术坑汇总 author: Silence tags:

  • 技术bu g categories:
  • 其他 date: 2018-06-09 16:24:00

1、GET请求URL带中文参数乱码问题。

我们开发中可能会遇到这样的问题:例如和其他系统对接,其他系统会通过http的get请求同时带一些参数请求你的接口地址(类似于支付宝回调等)。如:http://xxx.com/xxxAction/notifyResult?param=xxxxxx。

如果param需要传递中文,这时候通知的那边一般会将中文的参数值做urlEncode之后再传递过来,一般会选择用UTF-8做编码,这时候param带过来的就是结果UTF编码之后的值。当这个url请求到我们服务器的时候,我们服务器会默认对中文的参数进行解码操作,而这个解码具体按照什么方式解码,直接会导致传递过来的中文是乱码的。例如:tomcat8以下的版本默认中文的解码格式都是ISO-8859-1,因此传递过来的中文参数就会出现乱码,因为编码是按照UTF-8,解码不是按照UTF-8。必定造成乱码的现象。

神坑重现:

  • params传递的中文内容是:你好。经过UTF-8编码之后get方式请求服务器

那些年,我们踩过的技术坑汇总

  • 调试代码:我们发现拿到的request就成了一堆的乱码。

那些年,我们踩过的技术坑汇总

那么如何解决这样的问题呢?

方式一:代码介入:

思路:既然拿到的值是经过ISO-8859-1解码的,则可以将这个字符串按照ISO-8859-1编码,然后再对参数进行UTF-8解码即可。

那些年,我们踩过的技术坑汇总

或者:

那些年,我们踩过的技术坑汇总

方式二:修改容器默认的解码方式

这个配置在:xxx/conf/server.xml中。添加:URIEncoding="utf-8"

那些年,我们踩过的技术坑汇总

问题衍生:

通过浏览器请求一个带有中文参数的url,浏览器默认会对中文进行编码,而具体的编码方式会因为每个浏览器不同而不同,因此在实际的开发中,url尽量要做urlencode!避免不同浏览器不同的编码方式造成编码混乱的局面。

2、当需要将一个存放了字符串的集合转换为一个以逗号分隔的字符串时,切勿偷懒使用集合的toString方法,然后截取掉“[”、“]”的方式获取,因为list的toString()元素中间是用的逗号加空格隔开的,多了空格。

解决办法:

1、使用apache的StringUtils.join方法。

2、java8可直接使用String的join方法。

3、Fastjson序列化内部类失败问题。

我们在某个vo里面有一个其他类的字段,而又不想重新写一个类文件,则会直接在需要这个类的地方定义使用内部类,这里我们有一个json格式的字符串,现在需要利用fastjson转换为内部类的一个对象。错误代码如下:

@Data
public class Outer {

    private String name;
    private Inner value;

    @Data
    public class Inner{
        private String key;
        private String info;
    }

    public static void main(String[] args) {
        String json = "{\" info \":\" info \",\" key \":\" key \"}";
        Outer.Inner inner = JSON.parseObject(json, Outer.Inner.class);
        System.out.println(inner);
    }
}

错误console:

那些年,我们踩过的技术坑汇总

错误原因:

内部类没有顶一个为static,这样在实例化内部类的时候,需要事先实例化好外部类,根据外部类的一个对象才能实例化一个内部类,例如实例化内部类的写法如下:

Outer.Inner inner1 = new Outer().new Inner();

定义成静态内部类的写法为:

Outer.Inner inner1 = new Outer.Inner();

4、Collections.emptyList()方法返回的集合只能作为返回一个size为0的集合用,切不可以做其他修改集合的操作。

错误代码示例:

        List<String> list =  Collections.emptyList();

        list.add("sss");

        System.out.println(list);

错误Exception:

那些年,我们踩过的技术坑汇总

错误原因:

分析源码,这个方法实际返回的是一个类型为EmptyList的集合,而这个集合只是实现了几个简单的判断方法,并没有实现集合修改的一些方法,没有实现默认会使用AbstractList的方法,AbstractList并没有对修改集合的方法提供逻辑实现,只是简单地抛出了UnsupportedOperationException。

EmptyList类源码:

那些年,我们踩过的技术坑汇总

AbstractList的add方法源码:

那些年,我们踩过的技术坑汇总

5.Arrays.asList生成的ArrayList集合问题

    public static void main(String[] args) {
        List<String> list = Arrays.asList("a", "b", "c");
        list.add("d");
        System.out.println(list);
    }

错误Exception:

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at com.fcbox.mall.trade.biz.eventbus.event.PackageReceiveEvent.main(PackageReceiveEvent.java:38)
    

原因

Arrays.asList生成的ArrayList并不是我们常用的java.util下的数组集合,而是Arrays的内部类。而我们发现Arrays内部类的ArrayList有很多方法是没有覆写的,而 ArrayList的父类AbstractList很多方法都是需要具体子类覆写的。否则直接抛出UnsupportedOperationException。 那些年,我们踩过的技术坑汇总 那些年,我们踩过的技术坑汇总

总结

使用Arrays.asList生成的是Arrays的内部类ArrayList,很多list的操作是不支持的,包括add、remove等,这个一定要注意。