2019独角兽企业重金招聘Python工程师标准>>>
文章图片
传统JavaWeb项目前后分离实践
很荣幸公司能分配给我前后分离的任务给我!给我这个js只会基础语法,也就能做做页面效果的人。到现在前后分离基本完成的阶段依然对nodejs基础一知半解,写这篇文章除了分享经验,也为能够抛砖引玉,能与大家探讨分离的技术
- 前后分离的目的
- 前后分离的过程
- 发现脚手架项目
- 启动脚手架
- 路由、处理404,500等错误
- 模块 request,log4js
- SpringMvc增加接口,jsp转html 以及 过滤器
- js跨域问题以及部署
- 总结
前后分离的过程 1. 发现脚手架项目
讲真,作为一个javaer去搞前端框架开始有点不知道如何下手!唯一知道点的js开发就是NODEJS,因为我用来测试API的一个小软件就是nodeJs开发的,所以当时特意百度了解下。万幸google‘前后分离’,让我搜出来个nodejs前后分离的脚手架代码front-end-separate,让我有种刚了解java servlet后发现struts2感觉~
2. 启动脚手架
脚手架源码front-end-separate,它是基于express和grunt的前后端分离框架,引擎使用的是nunjucks。不知道express,grunt,nunjucks 这3是啥玩意,不管,先启动。
按照文档:
$ npm i grunt-cli -g
$ npm i
$ grunt
提示我better-npm-run不是内部命令什么的,google+百度,也没查出个大概来,无奈给作者发邮件询问,不能干等回复,又去了官网看better-npm-run文档,英文,不懂,试着执行了
$ npm i better-npm-run
$ npm i
$ grunt
启动成功,看见首页啦!
3. 路由
nodejs的项目从代码看,还是挺简单的。
跟踪下脚手架里路由的配置文件。(我对这个了解过程与我写的顺序正好相反,因为开始我不懂express是什么)
var routes = require('./routes/routes');
var app = express();
routes(app);
通过这段代码,追踪到./routes/routes.js文件
module.exports = function (app) {require('./web/site')(app);
require('./web/common')(app);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
};
没有研究过nodejs模块具体怎么弄,但通过这块的代码,忍不住猜想,nodejs中模块引用,通过跟踪:./web/site.jsrequire(path)
获取 path对应文件中module.exports
,可以是方法或者是对象
到这里就是正常请求的路由配置了! 在springMvc,写法如下:
@RequestMapping("/{projectId}/{status}.html")
public String tmoduleData(@PathVariable String status,@PathVariable Long projectId,Model model){
特意查了下nodejs中路径中带有参数怎么弄,参考expressjs文档和众网友通过正则等获取参数方式 nodjs代码如下:
//`:projctId` 可以通过 req.params.projectId 获得其值,如果其后面没有正则表达式(\\d+)限制为数字,则可以是任意字符~
app.get('/f/event/:projectId(\\d+)/:status(\\w+).html', function (req, res) {
var request = require('request');
request(app.get('APIDomain') + 'event/index?projectId=' + req.params.projectId + '&status=' + req.params.status, function (error, response, body) {if (!error && response.statusCode == 200) {
var d = JSON.parse(body);
d.projectId = req.params.projectId;
d.status = req.params.status;
d.EVENT_SITE_APIDomain = EVENT_SITE_APIDomain;
res.render(d.data.returnUrl, d);
}
});
});
关于其他参数的获取,例如post提交的参数等建议参考expressjs文档4. 模块request、log4js
回顾上述的过程,就避不开2个开发中的需求
- 如何发出http请求java后台数据
- 如何记录日志
npm i request
才跑通!为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。 模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。踩过request这个坑后,也就对nodejs模块化机制不是一无所知了,搜索刚刚的问题,还有一点,就是我没有错误的输出,控制台很空空如也!那么在nodejs中是否也有日志系统呢?
发现nodejs也有log4j,叫log4js 官方文档 参考众多网友的博客 如:http://blog.fens.me/nodejs-log4js/ 也写出了自己的第一个模块! 其功能有
- 所有日志在控制台输出的同时也输出到日志文件中
- 日志分类 并 输出到不同的日志文件中
具体参数参考文档吧,我就不啰嗦了
function getLog4js(){
var log4js = require('log4js');
log4js.configure({
appenders : [{
type : 'console'
},
{
type : 'file',
filename : 'logs/console.log',
maxLogSize : 104800,
backups : 100,
category : 'console'
},
{
type : 'file',
filename : 'logs/log4js.log',
maxLogSize : 104800,
backups : 100,
category : ['[default]','eventSite','wxCaht']
},
{
type : 'file',
filename : 'logs/access.log',
maxLogSize : 104800,
backups : 100,
category : 'access'
}
],
replaceConsole : true
});
return log4js;
}module.exports = getLog4js();
使用demo:
var log4js = require('../../config/log4js');
app.get('/', function (req, res) {
console.log("app.get('env'):"+app.get('env'));
log4js.getLogger().info("默认 test");
//默认的日志类型为'[default]'
log4js.getLogger("console").info("console test", EVENT_SITE_APIDomain);
//效果与console.log()一样
log4js.getLogger("access").info("access test");
log4js.getLogger("eventSite").info("eventSite test");
res.render("index")
});
//访问日志
app.use(log4js.connectLogger(log4js.getLogger('access'), {level:'INFO', format:':method :url'}));
5. SpringMvc增加接口,jsp转html
从jsp转html,我的思路是重构下代码,保留之前的功能不变,新增ajax请求的方法,因为无论springMvc的Model还是request.Attribute 都与Map结构类似,所以之前的要传给jsp的参数都put 到Map中并把这部分代码提取到一个方法中,然后之前的渲染jsp的方法和新的ajax方法都使用该方法return的MAP作为数据传给Modle或序列化就可以了
也是为了快速分离,所以我用了这种方法,实际上,有些地方应该再拆分的。我这样只能一个页面一个接口!数据源解决了,开始把jsp改html吧!
jsp变html其实很简单,把jstl改为nunjucks模版的表达式就好了
做到这,不知道nunjucks是啥东西也就知道是啥了,这也算是个学习方法吧,一边用一边学,工作效率可能不高,但学习效率很高遇到了几个坑:
1. 过滤器 slice 的使用 官方文档原文,真心读不懂,原谅我渣渣的英文!多次调用下,真心没搞懂,,请懂的大神给讲讲
slice(value, slices, fill_with=None)没弄懂,最后还是自定义了fifter
Slice an iterator and return a list of lists containing those items. Useful if you want to create a div containing three ul tags that represent columns
env.addFilter('sliceArray', function (a, start, end) {if (a instanceof Array) {
start = start | 0;
return a.slice(start, end);
}
return a;
});
通过自定义的一些过滤器可以把jsp完美转成html
2. 在jsp中可以动态的include,而在nunjucks 没有找到类似的方法。 3. 渲染html的参数,没有全局的参数,js碰见跨域问题 渲染html的参数只能通过
res.render(path, data);
中data设置,全局参数是传不进去的,不知道其他人是怎么解决的,例如,我想在html中用到一个全局的参数,开发环境下页面AJAX请求的Domain和线上不一致问题,总不能上线前修改每个页面的domain吧我的临时解决方案在下面部署部分说
6. js跨域问题以及部署 在自己的项目中,jsp里写的ajax url 无非在一个tag.jsp set了basePath,或window.jsPath,然后${basePath}/url。 而我们的更加简单粗暴,在同域名下的jsp都是相对路径 /url。
现在在nodjs开发过程中就出问题了,nodejs监听3001端口,tomcat端口9010,在localhost:3001下的页面访问loalhost:9010的ajax受到跨域限制!!!当然这是我开发的时候,前端开发时ajax肯定是个局域网内的一个服务器。
解决方案:
- 局域网内配置nginx
add_header Access-Control-Allow-Origin *;
- 线上的策略简单多了,附上我的NGINX配置(我本地模拟上线时的场景)
server {
listen80;
server_namesong.yang.o;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:80;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:9010;
}#处理nodjs路由的请求
location ^~ /f/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:80;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3001;
}#nodejs下静态文件交由nginx处理
location ^~ /static/ {
root E:\\frontSeparate\eventSite\dist;
}
}
这样跨域问题就得到解决!
在说部署 吐槽下连个运维都没有的公司。。。
之前写的博客nodjs 服务器部署以及守护进程 这部分我没有啥发言权,我发邮件请教了脚手架作者,给回复:“线上建议pm2”
待我了解了pm2后再更新这里
总结 总结是啥玩意~~~
欢迎吐槽讨论~~
【java|传统JavaWeb项目前后分离实践】转载于:https://my.oschina.net/northerSong/blog/750365
推荐阅读
- JavaEE|文件操作和IO
- Flexbox和Sass Grid教程(如何简化响应式设计)
- 如何创建自定义Magento 2小部件
- 高效的React组件(优化React性能的指南)
- 高级布局和效果的八个CSS技巧
- Angular vs. React(Web开发哪个更好())
- Ngrx和Angular 2教程(构建响应式应用程序)
- SVG动画操作指南
- 如何选择最佳的前端框架