reactjs重构java vm方案

起因

目前妈妈送房采用的是经典的MVC架构,前端模版使用vm,对于即会java又懂前端的人来说,这种方式没有什么不好,反而开发会很快。

但是,现在的互联网是分工协作的,我们现在的方式是前端开发人员负责静态页面样式及交互的开发,后端人员拿到静态页面进行数据的绑定,如果一次能搞定,那当然没什么问题,但是一旦涉及到bug的修改,功能的调整,那就是折磨了。再加上几经人手,前端代码已经丑陋不堪。所以,我萌生出了对项目进行重构并进行前后端分离的想法。为什么要前后端分离,这篇文章讲得不错

刚好最近学习了react,实战中也尝试了下,并且我们的这个项目特别适合做成一个SPA(single page application,单页面应用),所以就决定利用其进行逐步重构。

项目路径规划

因为SPA的代码最后都需要编译打包成一个文件,所以我把我的前端工程跟java工程放在一起,方便文件直接生成到java工程中

project.png

webpack打包路径设置

...
var staticPath = '../../webapp/assets'; // java工程静态文件路径
var viewFilename= '../../webapp/view/main/mmsf/mmsfIndex.vm' // java工程试图文件路径
...
// 文件打包后直接生成到java工程下
    entry: {
      bundle:path.resolve(__dirname, 'app/main.js')
  },
  output: {
    path: path.resolve(__dirname ,staticPath ),
    publicPath: '/',
    filename: '/js/mmsf/[name].js'
  },
...
// 图片
  module: {
    loaders:[
      ...
      { test: /\.(png|jpg)$/, loader: 'file-loader?limit=8192&name=i/mmsf/[name].[ext]'},
    ]
  },
...
// html文件及配置文件处理
plugins: [
    ...
    new CopyWebpackPlugin([
      { from: './app/mmsfIndex.html', to: path.resolve(__dirname, viewFilename) },
      { from: './app/config.js', to: path.resolve(__dirname ,staticPath + '/js/mmsf/config.js') },
    ]),
  ]

如何方便的与后端进行接口联调

前后端分离时,数据交换一般采取http的方式。开发时由于前后端不在同一个域,需要进行一些处理,以解决js跨越的限制。
常见的方法有:

  • 浏览器设置(chrome),原来确实是一个最方便的方式,在新版的chrome浏览器上试过,但是没成功
  • jsonp的方式,有点麻烦,放弃
  • 后端设置http头(Access-Allow-Control-Origin),本公司后端不会,懒得去求他们,还是自己想办法吧。
  • ngix,最后决定用这个

ngix配置

如果我将ngix配置成如下所示:

#user  nobody;
worker_processes  1;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
    #access_log  logs/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        #access_log  logs/host.access.log  main;
        location /api {
                  proxy_connect_timeout   3;  
            proxy_send_timeout      30;  
            proxy_read_timeout      30;
                  #rewrite (.*) site-web-personal/$1 permanent;
                  proxy_set_header   Host    $host;
            proxy_set_header   Remote_Addr    $remote_addr;
            proxy_set_header   X-Real-IP    $remote_addr;
            proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_pass http://192.168.10.171:8282/api;
        }       
        location / {
                  proxy_connect_timeout   3;  
            proxy_send_timeout      30;  
            proxy_read_timeout      30;
                  #rewrite (.*) site-web-personal/$1 permanent;
                  proxy_set_header   Host    $host;
            proxy_set_header   Remote_Addr    $remote_addr;
            proxy_set_header   X-Real-IP    $remote_addr;
            proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_pass http://192.168.10.169:8888/;  
        }       
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

这样当我访问http://localhost/*时会转发到我本地起的前端调试web服务,当我访问http://localhost/api时会转发到后端接口服务。

但是,我们的后端一开始并没有统一规划,所以也就没有区别接口的url地址和访问页面的url地址。

最后想到的办法是,利用eclipse->server可以给工程配置一个统一的url根目录来解决:

Paste_Image.png

然后ngix配置改成:

...
location /house-web-web {
    proxy_connect_timeout   3;  
    proxy_send_timeout      30;  
    proxy_read_timeout      30;
    #rewrite (.*) site-web-personal/$1 permanent;
    proxy_set_header   Host    $host;
    proxy_set_header   Remote_Addr    $remote_addr;
    proxy_set_header   X-Real-IP    $remote_addr;
    proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_pass http://192.168.10.171:8282/house-web-web;
}       
...

此时,访问http://localhost/house-web-web的请求会转发给后台接口,当然前端也需要进行配置:

// 上线需要改这两个参数
window.debug = true;

// baseurl
window.apiBase = window.debug ? '/house-web-web' : ''

// 前端路由
window.url = {
    'discoverIndex' : '/discover/index.htm', // 发现首页
    'discoverDetail' :  '/discover/detail.htm', //  发现详情
    'searchIndex' : '/search/index.htm', // 搜索首页
    'searchDetail' : '/search/detail.htm' // 搜索详情
}

// api
 window.api = {
    'discoverIndex': window.apiBase + '/discover/getIndexJson.htm', //发现首页
    'discoverDetail': window.apiBase + '/discover/detailPage.htm', // 发现详情
 }

这样,此时在浏览器中访问http://localhost/#/discover/index.htm则会到本地前端调试的服务,在该页面中访问http://localhost/house-web-web/discover/getIndexJson.htm则会访问后台的接口

前端路由

react的前端路由有两种方式hashHistorybrowserHistory
由于开发时webpack-dev-server启动的服务不支持browserHistory,所以开发时用hashHistory,生产上用browserHistory

  <Router history={window.debug ? hashHistory : browserHistory}>
            <Route path="/">
                 <Route path={window.url.discoverIndex} component={DiscoverList}/>
                 <Route path={window.url.discoverDetail} component={DiscoverDetail}/>
                 <Route path={window.url.searchIndex} component={SearchIndex}/>
                  <Route path={window.url.searchDetail} component={SearchDetail}/>
            </Route>
          </Router>

图片处理

图片有点不好弄,因为react中引入图片是相对于工程的路径,而到浏览器中访问时是相对于java静态文件目录的路径,所以这里的处理方式是:

  • 对于小图片,统一使用base64格式,这样不仅优化了访问速度,也解决了图片路径问题
  • 对于大图片,保证前端图片路径与java静态文件图片路径一致,且图片的访问路径用绝对路径

例子:

background-image: url('/assets/i/mmsf/search-banner.png')

为了确保webpack对图片进行处理,在react中对用到的图片均import

// 这里引入只是为了使webpack将图片拷贝到正确的路径
import bannerElderly from '../../assets/i/mmsf/discover-detail-banner.png'
import iconShare from '../../assets/i/mmsf/icon-share.png'

后端url处理

由于生产上还是需要使用真实路径,所以需要后端进行配合,所有用前端路由的url地址均渲染mmsfIndex.vm

Paste_Image.png

总结

总的下来,实现这一方案,用了很多非主流的方法,也让我知道了做技术只要掌握了原理,是可以根据自己的需要进行变通的。接下来就是逐步把原来的页面都迁移到新项目中来了,可以跟原来丑陋的代码说拜拜咯。
代码地址

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

推荐阅读更多精彩内容