如何把jquery项目前后端分离?

起初的几点思考

  1. 原始的jquery项目是没有工程化可言的,单独把原本项目改成单页应用等于回炉重造
  2. jquery项目之间的重复页面很难有像现在vue,react等组件哪样的开发体验,只有iframe标签,object标签,或者get请求其文本文件镶嵌到当前页面($.load等)
  3. 如果需要改造,要重新做工程化?上webpack?no no no 十几个配置项都不够整的,时间成本不值当,想想 项目最终还是在nginx上部署的,我能否用最简单的方式改造?
  4. 还有一点html文件量很大 大概120个文件,有些是独立的,有些是相互嵌套的,资源都是独立引用的。
  5. 所以下面我采用最直接了当的方式,不改动源码,用nginx做请求处理,也作为开发和发布的容器来改造原始项目

文件结构

改造后的文件结构

其实整体就是一个nginx,cmcs_html就是前端文件

  • 项目启动:双击start.bat就行 linux的命令自己看常用命令自己手动启动或者做个启动脚本哈

  • 停止nginx服务:双击stop-all.bat 注意 是停止所有的nginx项目

  • 项目配置文件:conf/self/index.conf 在这里配置端口 以及访问规则

拆分流程

下面的拆分流程按照重要程度来码的,实际操作过程要按照倒序来~

下面环境说明:

原始项目端口:http://localhost:8080/cmcs/index

改造后的前端项目端口:http://localhost:3000/index

项目是一个桌面级的web应用

原始项目首页请求

接下来分析了

我们的目标是把所有的请求按照一定的规则,在nginx中做请求处理,我们需要做的是把请求分类

上诉请求分为三大类

  • 静态资源 .js .css.png等 项目素材

  • html 文档类型文件 请求的前端页面

  • xhr 请求后端获取数据的接口

拆分过程

在强调一遍~我们整体目标是把所有的请求通过nginx转发到服务器或者本地(静态资源)

代码中的需要处理的三块,不同的项目 根据场景来

  1. 这个项目通过后端控制路由的,Ajax的请求与html页面跳转在拦截规则的时候无法过滤,怎么做区分呢?(具体看上面的原始的环境的图) 比如请求/index 和访问/login 怎么区分 index是访问index.html login是登陆操作

    1.1 ajax的跳转的cookie怎么携带?

    1.2 当前项目在登陆失败后后端是直接sendRedirect 转发到/login怎么才能集中做请求拦截?

  2. 代码中的Html的页面跳转

    2.1 前端代码中通过loadPage方法请求,可以当做成ifream设置src请求后端(原代码是解析成Object标签 加data属性的形式),怎么让它直接请求前端根目录下的html文件呢?

    2.2 页面之间的跳转,处理的映射关系src\main\java\com\cmcc\cmdi\controller\PageController.java做的文件映射关系 有些是比如首页有两个index2.html和index1.html 在这个文件可以得到应证

  3. 原始项目后台路径转发有携带参数

    3.1 大部分页面有带有省份的参数provinceName 这个是存在session中 如果分离 怎么获取?

  4. 静态目录的问题
    4.1 如下图所示html的js和图片和字体图标都储存在static目录下的 如果不做特殊处理想引用对,那么要把static全部搬到根目录下,那么js和html和png都炸锅了~

改造后的前端目录结构

可以看到大致的资源引入方式,和文件的分布

解决方案

问题1.1~1.3Ajax的请求与html页面跳转在拦截规则的时候无法过滤 cookie的问题 登陆拦截的问题

思路:页面上所有的请求大部分都是jquery的$.ajax方法发送的,我要做的是重写ajax 在发送请求的时候在url上面拼接/api/路径 有固定的前缀 nginx方便做规则

实现:

  1. 重写的脚本放哪里合适?当然放到jquery后面,每一个文件都加太麻烦,看了下项目中大部分html都引入了<script src="js/util/util.js"></script> 脚本 为了减少工作量把重写ajax的方法写在尾部,在每个html中引入
<!--错误  后引入的jquery会覆盖$.ajax方法-->
<script src="jquery.js"></script>
<script src="js/util/util.js"></script>
<script src="jquery.js"></script>

<!--正确-->
<script src="jquery.js"></script>
<script src="js/util/util.js"></script>
login.html
  1. cookie的携带问题?nginx配置转发完事~
proxy_cookie_path  $path /;
  1. 登陆拦截怎么处理?原本项目中java的登陆拦截是在LogHandlerInterceptor.java中转发到\login但是由于 后端面项目加了项目名的原因 导致重定向给niginx的结果为http://localhost:3000/cmcs/login 单独去做拦截转发也有可能造成永久重定向的问题 所以 这里解决方案需要后端配合,当登陆失效的时候 返回的response.status的状态码为1002就行 返回不用给数据撒的,直接判断状态码后直接跳转到登陆页面,下图中的util.js中的180行代码,跳转login然后被niginx拦截会加上.html
\sdwy_sx\src\main\java\com\cmcc\cmdi\interceptor\LogHandlerInterceptor.java 登陆拦截器文件
util.js 全局改造文件

cmcs-web\conf\self\index.conf nginx的配置文件

解释下niginx配置
后端地址 http://localhost:8080/cmcs/loginVertify
前端请求地址: http://localhost:3000/api/loginVertify
nginx的配置作用:

  1. 拦截api
  2. 加上项目名
  3. $path设置
  4. 去除/api/
  5. 代理和cookie的path -这里是因为原本项目带项目名转发的cookie的path /cmcs 所以要去除path cookie的path特性是当前路径下的所有请求才会带上cookie
    cookie:/cmcs ---> /
    url:http://localhost:3000/api/loginVertify ----> http://localhost:8080/cmcs/loginVertify

问题2.1请求ajax的url处理了那么请求静态文件的呢?就是一个抄底的做法,

思路:前端代码中通过loadPage方法请求,可以当做成ifream设置src请求后端(原代码是解析成Object标签 加data属性的形式),怎么让它直接请求前端容器根目录下的html文件呢?

实现: 下面的请求地址,在原始项目中都是请求后端的PageController.java处理的映射关系,需要吧请求的地址 直接请求到前端项目容器的html文件,只需要加后缀就行了
htmlName ----> htmlName.html

PageController.java

index.html loadpage方法
Index.conf

其实这里没有任何的规则项 直接配置一个兜底的配置就行

问题2.2页面之间的跳转,处理的映射关系

思路:上诉的配置 已经可以把所有的html文件正常访问了,接下来只是改文件和应证的工作

实现:下面拿index1.html index2.html举例

  1. 如果看到页面上有两个相识的文件 什么12结尾的,什么old 什么cp 都去pageController里面去看下是否是注释掉的, 返回的字符串如果是index2那么index2.html是项目正在使用的页面

  2. 把不要的html的页面 移动到delete/文件加目录下

  3. 把index2.html改成index.html

PageController.java

代码含义
如果请求 /index 返回的是template/index2.html文件
如果请求 /indexnew 返回的是template/index.html文件
Indexold被注释掉了 就删掉吧

删的文件放这里,防止误删

问题3原始项目后台路径转发有携带参数

思路:多页面传参provinceName的解决方案基本上大部分页面都有这个参数还有一些页面有其他参数,用混入模式的方式 尽量保证不动原有代码 如果改动小可以根据原本的代码获取方式变动,在unit.js里面全局统一改动

实现:先了解原始的传参过程获取参数的方式。在登陆的时候获取省份保存在localStorage里面每个页面加载util.js在适当的时候赋值上去,保证原始代码在获取的时候不出问题 如果出现选择器的影响可以判断下当前ifream的url来区分

如果有其他其他参数 手法一样,这里全局配置通过url判断一下

index.html发现问题
请求404报错请求看堆栈信息定位错误所在文件
分析代码逻辑找到报错关键点kpiinfo.html
kpiinfo.html<

如何赋值呢?在util里面全局处理,如果怕其他页面造成选择器的污染 加url(这个url是当前ifream的url ) 做判断

util.js

赋什么值?答~看原始系统

url是原始项目的首页,F12收下名字就可以啦 北京市!

数据哪里来?

login.html

坐等后端改登陆接口,注意加rlpt_的前缀的原因是防止本地缓存的变量名冲突 因为localStorage没有path

到此项目已经拆分完毕!!!

关键文件

nginx 配置文件

server {
    listen       3000;
    server_name  localhost;

    #本地
    set $baseUrl "http://127.0.0.1:8080";

    #测试
    #set $baseUrl "http://192.168.110.240:8080";
    
    #发布
    #set $baseUrl "http://127.0.0.1:8080";

    #路径  后台项目名或者多出来的请求路径 不要以/结尾  原本的项目的cookie  path是没有/的
    set $path "/cmcs";
    #根目录
    set $baseRoot "cmcs_html";
    
    gzip on; #启动
    gzip_buffers 32 4K;
    gzip_comp_level 6; #压缩级别,1-10,数字越大压缩的越好
    gzip_min_length 100; #不压缩临界值,大于100的才压缩,一般不用改
    gzip_types application/javascript text/css text/xml;
    gzip_disable "MSIE [1-6]\."; # IE6对Gzip不友好,对Gzip
    gzip_vary on;

    #编码
    charset utf-8;

    #静态目录
    root $baseRoot;
    
    #传输大小
    client_max_body_size 100M;

    #----api拦截---- ajax会重写 在前面拼接api路径
    location ~^/api(.*) {
        #转发的时候服务地址的配置 加上了端口
        proxy_set_header   Host             $host:$server_port;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cookie_path  $path /;
        rewrite ^/api(.*) $path$1 break;
        proxy_pass $baseUrl;
    }
    
    #static文件下的静态文件的地址拼接
    #$1为上面匹配的正则表达式如果访问 /a/index.css--->static/a/index.css
    location ~(.*\.(css|js|swf|jpg|gif|png|jpep|jpg|mp3|xx|xmlbak|xml|ttf|woff2|woff)) {
        alias $baseRoot/static/$1;
    }

    #html页面
    location ~(.*\.(html|htm)) {
        alias $baseRoot/$1;
    }

    #访问所有 html文件名(htmlName) 重定向到htmlName.html
    location ~(.*) {
        if ( $request_uri = /) {
            rewrite (.*) /index.html break;
        }
        rewrite (.*) $1.html break;
    }
    
    #----其他文件   正常情况不会出现----
    location / {
       return 888 "未捕获的路径,请重新配置nginx";
    }

}

util.js

/*******************************************重写jaquery的ajax*****************************************************************/
/**
 * 目的前后端分离的情况下
 * 请求  index   login  分不清是请求页面还是请求连接  nginx已经配置  会去请求  index.html和login.htm
 *
 * 如果想让login请求对应的后台服务器而不是前端页面需要加上api特定的前缀  已做区分
 *
 * 登陆失效:返回状态码为1002即可重定向到首页
 *
 * 完整的拆分方案 请阅读本项目根目录下的  "项目说明".doc文件
 */
(function () {
  //避免jquery没引用报错
  if (!$) return;
  //ajax重写
  (function ($) {
    //保留原始ajax
    let _ajax = $.ajax;
    //重写
    let ajax = function (url, option) {
      //参数处理
      let opts = url || {};
      if (typeof url == "string") {
        option.url = url;
        opts = option;
      }
      //api路径拼接
      opts.url = "/api/" + opts.url;
      let complete = opts.complete;
      opts.complete = function (res) {
        //全局处理登陆失效
        if (res.status == 1002) window.location.href = "login";
        complete && complete.call(complete, res);
      };

      //调用
      return _ajax.apply($, arguments);
    };
    //赋值
    $.ajax = ajax;
  })(jQuery);

  //改造参数  多页面传参provinceName的解决方案 基本上大部分页面都有这个参数  还有一些页面有其他参数  不改动原始代码的情况下  在里面全局改动
  //原理  在登陆的时候获取省份保存在localStorage里面  每个页面加载util.js在适当的时候赋值上去 如果出现选择器的影响 可以判断下当前ifream的url来区分
  //其他参数  手法一样,这里全局配置 通过url判断一下  混入模式的方式  尽量保证不动原有代码  如果改动小可以根据原本的代码获取方式变动
  //参数改造
  $(() => {
    $("#provinceName").val(localStorage.getItem("rlpt_provinceName"));
  });
})();

完成页面

index.html

待完成问题

需要后端协调的地方

  1. 登陆拦截sdwy_sx\src\main\java\com\cmcc\cmdi\interceptor\LogHandlerInterceptor.java 返回response.status=1002 一个标记 让前端做跳转就行

  2. 页面间的跳转映射关系 可以不用管,前端不会受影响 毕竟是两个容器了,但是别删 方便核对

  3. 因为provinceName是在session中拿的,不是同一个项目拿不到,在登陆的时候给就行。形式也可以选其他的。接口格式

{
  "status": 1,//1 登陆成功  //2登陆失败
  "userInfo": {
    "provinceName": "北京市"
  }
}
  1. 报错处理,确认下后端代码报错后配置的页面是error下面的404.html和500.html,如果需要处理 需要后端在后台拦截所有的异常信息返回给前端对应的status 可以像方案1一样 1003 1004 对应的显示404和500页面

后续前端工作

主要是看其他界面功能是否正常

  1. 全局的util.js所有的页面已经加了(花了30分钟差不多,一百多个页面每个还只是加个js引用...不敢想想单个改难度会有多大)

  2. 有些后台页面跳转有其他参数传递需要后面跟进

  3. 文件上传是否也OK

  4. 这个肯定有问题,bootstarpTable自身的url做请求 这里它会用bootstarpTable插件内部的ajax 登陆失效并不会拦截 这个需要定位文件,方案是bootstarpTable的默认属性去覆盖它。后续优化,问题不大 大部分的bootstarpTable 是以data赋值塞数据的形式写的。

  5. 测试过的只有首页和登陆页面,看见其他页面很多接口报错~需要前后端联调报错接口,如果调试不知道是否是nginx的问题,那么请对照原始项目对应页面看是否也有问题来判断

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容