23

记一次项目中遇到的坑

 3 years ago
source link: http://www.justdojava.com/2020/09/28/java-hole/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

hello~各位读者好,我是鸭血粉丝(大家可以称呼我为「阿粉」)。今天,阿粉带着大家来了解一下 最近在项目中遇到的一个坑。

1业务场景

前端用了个富文本插件 Ueditor ,插件初始化的时候需要从后端获取 config 配置。

2入坑经历

首先看下最开始的代码:

@RequestMapping(value = "/getConfig")
    public Object getConfig(HttpServletRequest request){
       return readConfig();
    }

	/**
     * 读取配置文件
     * @return
     */
    private UedConfig readConfig() {
        String path = this.getClass().getResource("/").getPath();
        FileInputStream fileInputStream = new FileInputStream(path + "config/ued_config.json");
        //读出来,转成对象返回
        ...
    }

代码大概就是这样,然后启动起来之后,前端告诉我没有获取到信息。纳尼,我postman自测都没问题,有数据返回。然后阿粉跑去问前端,有报错吗?前端说跨域了。当时阿粉就不乐意了,马上 ctrl+c 加上ctrl+v 把后端处理跨域请求的配置发给前端。然后前端告诉我是jsonp 请求跨域。阿粉一脸懵逼???jsonp 跨域?没听说过啊。马上找度娘去,果然一搜全是处理方式。因为是 springboot 项目,所以找了个最简单的。看代码:

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
    public JsonpAdvice(){
        super("callback");
    }
}

看,是不是很简单。要是 AbstractJsonpResponseBodyAdvice 这个单词下面没有红线就更完美了。没有引入类吗?怎么难得倒阿粉呢。alt+enter,嗯哼,什么情况,没有这个类?不可能啊。马上问度娘一下,原来这个类是 springboot 2.0以下才有。那怎么办呢?2.0以上好像没有处理 jsonp 跨域的方式啊。阿粉又在百度搜啊搜,果然,皇天不负有心人,阿粉看到 jackson 里面有个类 JSONPObject 可以处理,然后阿粉改了一下代码:

@RequestMapping(value = "/getConfig")
public Object getConfig(String callback,HttpServletRequest request){
    return new JSONPObject(callback,readConfig());
}

然后重启,自测没问题。让前端试下,可以正常获取。OK,完美。

后面项目完成了,前后端也对接完了,发到测试环境,让测试人员测试。Duang~一个bug扔阿粉头上,获取配置失败。不可能啊,肯定是前端的问题,跑去找前端让前端看下。前端看了之后给我来了一句,测试环境不跨域。瞬间一万头草尼玛从头上飘过。阿粉辛辛苦苦花了几个小时才把跨域问题处理了,你给我说测试环境不跨域。

哎,没办法,这口锅只能自己含泪抗下了。然后阿粉又改了一次代码:

@RequestMapping(value = "/getConfig")
public Object getConfig(String callback,HttpServletRequest request){
    return StringUtils.isEmpty(callback) ? readConfig() : new JSONPObject(callback,readConfig());
}

还是做了个兼容,因为前端还需要连我本地调试。不过这次应该没有问题了吧,阿粉心里还是有些小得意。提交代码,发测试,搞定。

Duang~同样的bug再一次扔在了阿粉脸上。心都凉了,怎么回事呢?日志也没报错啊。捣鼓半天,不知道什么原因,阿粉只能加写log,因为在测试环境不好调试,也没报错。然后让运维配合一下,然后发现 this.getClass().getResource(“/”).getPath() 得到的路径不对,阿粉再一次一脸懵逼,这个不是获取项目根路径吗?怎么回事呢。

然后阿粉有厚着脸皮找度娘,果然一下就找到原因了,因为 springboot 集成了tomcat,项目直接是打成 jar 包运行的,不能通过 this.getClass().getResource(“/”).getPath() 这种获取项目根路径的方式来获取,只能通过流的方式,然后阿粉又改了下代码:

/**
     * 读取配置文件
     * @return
     */
private UedConfig readConfig() {
    InputStream resourceAsStream = this.getClass().getResourceAsStream("/"+"config/ued_config.json");
    //读出来,转成对象返回
    ...
}

好了,这次提交之后终于可以了。解决了 bug ,阿粉心里美滋滋。

3 总结

经常看到一些小伙伴说,本地对接没问题,怎么一到测试环境就那么多 bug 呢。阿粉总结了一下,主要还是以下几点:

  1. 系统不一样,本地一般都是window系统,而测试和线上一般都是 linux 系统。
  2. 运行方式不一样,本地 springboot 项目是通过代码工具 (idea)启动,而测试和线上是通过 jar 包启动。
  3. 比如还有一些其他 jar 引入的问题
  4. 。。。

好了,阿粉这次的分享就到这里了。希望阅读阿粉文章的朋友少走一些弯路。要是觉得有用的话,记得点个赞哦。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK